diff --git a/examples/basic/extensions.js b/examples/basic/extensions.js new file mode 100644 index 000000000..925236ec4 --- /dev/null +++ b/examples/basic/extensions.js @@ -0,0 +1,49 @@ +'use strict' + +const Hemera = require('./../../packages/hemera') +const nats = require('nats').connect() + +const hemera = new Hemera(nats, { + logLevel: 'info' +}) + +hemera.ready(() => { + hemera.ext('onServerPreRequest', function(hemera, request, reply, next) { + console.log('onServerPreRequest') + next() + }) + hemera.ext('onServerPreHandler', function(hemera, request, reply, next) { + console.log('onServerPreHandler') + next() + }) + hemera.ext('onServerPreResponse', function(hemera, request, reply, next) { + console.log('onServerPreResponse') + next() + }) + + hemera.add( + { + topic: 'math', + cmd: 'add' + }, + function(req, cb) { + cb(null, req.a + req.b) + } + ) + + hemera.act( + { + topic: 'math', + cmd: 'add', + a: 1, + b: 20 + }, + function(err, resp) { + if (err) { + this.log.error(err) + return + } + this.log.info(resp) + } + ) +}) diff --git a/packages/hemera/lib/index.js b/packages/hemera/lib/index.js index df103439d..2db253d6b 100644 --- a/packages/hemera/lib/index.js +++ b/packages/hemera/lib/index.js @@ -236,7 +236,7 @@ class Hemera extends EventEmitter { * @memberof Hemera */ _registerErrors() { - for (var error in Hemera.errors) { + for (let error in Hemera.errors) { Errio.register(Hemera.errors[error]) } } diff --git a/packages/hemera/lib/reply.js b/packages/hemera/lib/reply.js index ec42ae2be..ab682cfdd 100644 --- a/packages/hemera/lib/reply.js +++ b/packages/hemera/lib/reply.js @@ -148,7 +148,9 @@ class Reply { ).causedBy(extensionError) self.log.error(internalError) self.hemera.emit('serverResponseError', extensionError) - self.send(extensionError) + // don't use send() here in order to avoid rexecution of serverPreResponse + // and to send the "send-error" as final response + self.error = extensionError } if (self._response.replyTo) { diff --git a/test/hemera/async-schemaCompiler.spec.js b/test/hemera/async-schemaCompiler.spec.js index 977f16d4f..49c2010fc 100644 --- a/test/hemera/async-schemaCompiler.spec.js +++ b/test/hemera/async-schemaCompiler.spec.js @@ -154,7 +154,11 @@ describe('Async Schema Compiler', function() { (err, resp) => { expect(err).to.be.exists() expect(err.name).to.be.equals('TimeoutError') - hemera.close(done) + // give the promise the chance to respond within active nats connection + // otherwise we will run into a connection error + setTimeout(() => { + hemera.close(done) + }, 200) } ) }) diff --git a/test/hemera/server-extensions.spec.js b/test/hemera/server-extensions.spec.js index 1ae20ca27..3d55db666 100644 --- a/test/hemera/server-extensions.spec.js +++ b/test/hemera/server-extensions.spec.js @@ -333,7 +333,7 @@ describe('Server Extensions', function() { }) }) - it('Should not be able to send the payload in onServerPreResponse because payload was already set', function(done) { + it('Should not be able to send the payload in onServerPreResponse because success payload was already set', function(done) { let ext = Sinon.spy() const nats = require('nats').connect(authUrl) @@ -376,7 +376,103 @@ describe('Server Extensions', function() { }) }) - it('Should not be able send the extension error in onServerPreResponse because payload was already set', function(done) { + it('Should send the onServerPreRequest error instead the last extension error payload', function(done) { + let onServerPreRequestSpy = Sinon.spy() + let onServerPreHandlerSpy = Sinon.spy() + + const nats = require('nats').connect(authUrl) + + const hemera = new Hemera(nats) + + hemera.ready(() => { + hemera.ext('onServerPreRequest', function(ctx, req, res, next) { + onServerPreRequestSpy() + next(new Error('test1')) + }) + hemera.ext('onServerPreHandler', function(ctx, req, res, next) { + onServerPreHandlerSpy() + next(new Error('test2')) + }) + + hemera.add( + { + topic: 'email', + cmd: 'send' + }, + (resp, cb) => { + cb(null, true) + } + ) + + hemera.act( + { + topic: 'email', + cmd: 'send', + email: 'foobar@gmail.com', + msg: 'Hi!' + }, + (err, resp) => { + expect(err).to.be.exists() + expect(err.name).to.be.equals('Error') + expect(err.message).to.be.equals('test1') + expect(resp).to.be.undefined() + expect(onServerPreRequestSpy.called).to.be.equals(true) + expect(onServerPreHandlerSpy.called).to.be.equals(false) + hemera.close(done) + } + ) + }) + }) + + it('Should send the extension error in onServerPreResponse instead previous extensions errors', function(done) { + let onServerPreHandlerSpy = Sinon.spy() + let onServerPreResponse = Sinon.spy() + + const nats = require('nats').connect(authUrl) + + const hemera = new Hemera(nats) + + hemera.ready(() => { + hemera.ext('onServerPreHandler', function(ctx, req, res, next) { + onServerPreHandlerSpy() + next(new Error('test1')) + }) + hemera.ext('onServerPreResponse', function(ctx, req, res, next) { + onServerPreResponse() + next(new Error('test2')) + }) + + hemera.add( + { + topic: 'email', + cmd: 'send' + }, + (resp, cb) => { + cb(null, true) + } + ) + + hemera.act( + { + topic: 'email', + cmd: 'send', + email: 'foobar@gmail.com', + msg: 'Hi!' + }, + (err, resp) => { + expect(err).to.be.exists() + expect(err.name).to.be.equals('Error') + expect(err.message).to.be.equals('test2') + expect(resp).to.be.undefined() + expect(onServerPreHandlerSpy.called).to.be.equals(true) + expect(onServerPreResponse.called).to.be.equals(true) + hemera.close(done) + } + ) + }) + }) + + it('Should send the extension error in onServerPreResponse instead the success payload', function(done) { let ext = Sinon.spy() const nats = require('nats').connect(authUrl) @@ -407,8 +503,10 @@ describe('Server Extensions', function() { msg: 'Hi!' }, (err, resp) => { - expect(err).to.be.not.exists() - expect(resp).to.be.equals(true) + expect(err).to.be.exists() + expect(err.name).to.be.equals('Error') + expect(err.message).to.be.equals('test') + expect(resp).to.be.undefined() expect(ext.called).to.be.equals(true) hemera.close(done) }