node.jsapi-gatewaymoleculermoleculer-web

moleculer-web API gateway. onError never hit


We used the example from the moleculer website as the basis for our API gateway, and are a having issues when routes throw errors - the onError handler is never hit, the exception is unhandled and node crashes the app. Not the idea!

I realise this is NOT a complete example but a quick eye cast over if we have made any gross errors of concept, or if we should expect the onError handler to be hit would be nice...

const OpenApiMixin = require('./openapi.mixin')
const { MoleculerError } = require('moleculer').Errors

class BadRequestError extends MoleculerError {
  constructor (message) {
    message = message || 'Bad request'
    super(message, 400, 'Bad request')
  }
}

...
const functionThatCanThrowError = async (req, res)=>{
    if (!req.body.email) {
      throw new BadRequestError('No email transferred.')
    }
    ...
}

module.exports = {
  name: 'api-gateway',
  mixins: [ApiGateway, OpenApiMixin()],
  settings: {
    ...
    path: '/',
    routes: [
    {
      path: '/api',
      ...
      aliases: {
            'POST /route-can-throw-error': functionThatCanThrowError
      },

      // Route error handler
      onError (req, res, err) {
        let { type, code, message, data, name } = err
        res.writeHead(Number(code) || 500, { 'Content-Type': 'application/json' })
        res.end(JSON.stringify({ type, code, message, data, name }))
      }
    }
 ]
}``

Solution

  • The defined functionThatCanThrowError is a middleware. It should be an Express-like middleware where you can't throw an error. To do it, you should call next(err).

    E.g:

    const functionThatCanThrowError = async (req, res, next)=>{
        if (!req.body.email) {
          next(new BadRequestError('No email transferred.'))
        }
        ...
    }
    

    More info: https://expressjs.com/en/guide/error-handling.html