Skip to content

Commit

Permalink
server extension points. Closes #2685
Browse files Browse the repository at this point in the history
  • Loading branch information
hueniverse committed Aug 8, 2015
1 parent ee52f45 commit 6bced99
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 25 deletions.
36 changes: 26 additions & 10 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,8 @@ server starts (only called if the server is started) where:
their `after()` methods. There is no requirement for the other [plugins](#plugins) to be
registered. Setting dependencies only arranges the after methods in the specified order.

The `server.after()` method is identical to setting a server extension point on `'onPreStart'`.

```js
var Hapi = require('hapi');
var server = new Hapi.Server();
Expand Down Expand Up @@ -840,6 +842,8 @@ Used within a plugin to declares a required dependency on other [plugins](#plugi
- `err` - internal error condition, which is returned back via the
[`server.start()`](#serverstartcallback) callback.

The `after` method is identical to setting a server extension point on `'onPreStart'`.

```js
exports.register = function (server, options, next) {

Expand Down Expand Up @@ -899,25 +903,37 @@ exports.register = function (server, options, next) {

### `server.ext(event, method, [options])`

Registers an extension function in one of the available [extension points](#request-lifecycle)
where:
Registers an extension function in one of the available extension points where:
- `event` - the event name.
- `method` - a function or an array of functions to be executed at a specified point during request
processing. The required extension function signature is `function(request, reply)` where:
- `request` - the [request object](#request-object).
- `reply` - the [reply interface](#reply-interface) which is used to return control back to the
framework. To continue normal execution of the [request lifecycle](#request-lifecycle),
`reply.continue()` must be called. To abort processing and return a response to the client,
call `reply(value)` where value is an error or any other valid response.
- `this` - the object provided via `options.bind` or the current active context set with
[`server.bind()`](#serverbindcontext).
processing. The required extension function signature is:
- server extension points: `function(server, next)` where:
- `server` - the server object.
- `next` - the continuation method with signature `function(err)`.
- `this` - the object provided via `options.bind` or the current active context set with
[`server.bind()`](#serverbindcontext).
- request extension points: `function(request, reply)` where:
- `request` - the [request object](#request-object).
- `reply` - the [reply interface](#reply-interface) which is used to return control back to the
framework. To continue normal execution of the [request lifecycle](#request-lifecycle),
`reply.continue()` must be called. To abort processing and return a response to the client,
call `reply(value)` where value is an error or any other valid response.
- `this` - the object provided via `options.bind` or the current active context set with
[`server.bind()`](#serverbindcontext).
- `options` - an optional object with the following:
- `before` - a string or array of strings of plugin names this method must execute before (on
the same event). Otherwise, extension methods are executed in the order added.
- `after` - a string or array of strings of plugin names this method must execute after (on the
same event). Otherwise, extension methods are executed in the order added.
- `bind` - a context object passed back to the provided method (via `this`) when called.

The available extension points include the [request extension points](#request-lifecycle) as well
as the following server extension points:
- `'onPreStart'` - called before the connection listeners are started.
- `'onPostStart'` - called after the connection listeners are started.
- `'onPreStop'` - called before the connection listeners are stopped.
- `'onPostStop'` - called after the connection listeners are stopped.

```js
var Hapi = require('hapi');
var server = new Hapi.Server();
Expand Down
3 changes: 0 additions & 3 deletions lib/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,6 @@ internals.Connection.prototype._stop = function (options, callback) {

var self = this;

options = options || {};
options.timeout = options.timeout || 5000; // Default timeout to 5 seconds

if (!this._started) {
return process.nextTick(callback);
}
Expand Down
10 changes: 5 additions & 5 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ internals.Server.prototype.start = function (callback) {

var self = this;

callback = callback || Hoek.ignore;

Hoek.assert(this.connections.length, 'No connections to start');
Hoek.assert(!this._registring, 'Cannot start server before plugins finished registration');

Expand Down Expand Up @@ -189,12 +187,14 @@ internals.Server.prototype.start = function (callback) {
};


internals.Server.prototype.stop = function (/*[options], [callback]*/) {
internals.Server.prototype.stop = function (/* [options], callback */) {

var self = this;

var callback = (arguments.length === 1 ? (typeof arguments[0] === 'function' ? arguments[0] : Hoek.ignore) : arguments[1]);
var options = (arguments.length === 1 ? (typeof arguments[0] === 'function' ? null : arguments[0]) : arguments[0]);
var callback = (arguments.length === 1 ? arguments[0] : arguments[1]);
var options = (arguments.length === 1 ? {} : arguments[0]);

options.timeout = options.timeout || 5000; // Default timeout to 5 seconds

this._invoke('onPreStop', function (err) {

Expand Down
36 changes: 29 additions & 7 deletions test/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,21 +174,43 @@ describe('Server', function () {
});
});

it('stops with only an option object', function (done) {
it('returns an extension error', function (done) {

var server = new Hapi.Server();
server.connection();
server.ext('onPreStop', function (srv, next) {

server.connections[0]._stop = function (options, callback) {
return next(new Error('failed cleanup'));
});

server.start(function (err) {

expect(err).to.not.exist();
server.stop(function (err) {

expect(options).to.deep.equal({
timeout: 1
expect(err.message).to.equal('failed cleanup');
done();
});
done();
});
});

it('returns a connection stop error', function (done) {

var server = new Hapi.Server();
server.connection();
server.connections[0]._stop = function (options, next) {

return next(new Error('stop failed'));
};

server.stop({
timeout: 1
server.start(function (err) {

expect(err).to.not.exist();
server.stop(function (err) {

expect(err.message).to.equal('stop failed');
done();
});
});
});
});
Expand Down

0 comments on commit 6bced99

Please sign in to comment.