Skip to content

Commit

Permalink
Config function. Closes #3277
Browse files Browse the repository at this point in the history
  • Loading branch information
hueniverse committed Aug 1, 2016
1 parent af4e5f0 commit 0272560
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 11 deletions.
6 changes: 4 additions & 2 deletions API.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 14.0.x API Reference
# 14.1.x API Reference

- [Server](#server)
- [`new Server([options])`](#new-serveroptions)
Expand Down Expand Up @@ -2134,7 +2134,9 @@ The route configuration object supports the following options:
an object with a single key using the name of a registered handler type and value with the
options passed to the registered handler.

- `config` - additional [route options](#route-options).
- `config` - additional [route options](#route-options). The `config` value can be an object
or a function that returns an object using the signature `function(server)` where `server` is
the server the route is being added to and `this` is bound to the current realm's `bind` option.

Note that the `options` object is deeply cloned (with the exception of `bind` which is shallowly
copied) and cannot contain any values that are unsafe to perform deep copy on.
Expand Down
18 changes: 12 additions & 6 deletions lib/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,19 @@ exports = module.exports = internals.Route = function (route, connection, plugin

Hoek.assert(route.path, 'Route missing path');
const routeDisplay = route.method + ' ' + route.path;
Hoek.assert(route.handler || (route.config && route.config.handler), 'Missing or undefined handler:', routeDisplay);
Hoek.assert(!!route.handler ^ !!(route.config && route.config.handler), 'Handler must only appear once:', routeDisplay); // XOR

let config = route.config;
if (typeof config === 'function') {
config = config.call(realm.settings.bind, connection.server);

This comment has been minimized.

Copy link
@devinivy

devinivy Aug 1, 2016

Member

Any reason not to call it with the server and pluginOptions relevant to the current realm? That's what I usually see folks closing around their route configs.

This comment has been minimized.

Copy link
@AdriVanHoudt

AdriVanHoudt Aug 2, 2016

Contributor

I would indeed expect that the server being passed would be the one where .route is called on and not the root/connection one

}

Hoek.assert(route.handler || (config && config.handler), 'Missing or undefined handler:', routeDisplay);
Hoek.assert(!!route.handler ^ !!(config && config.handler), 'Handler must only appear once:', routeDisplay); // XOR
Hoek.assert(route.path === '/' || route.path[route.path.length - 1] !== '/' || !connection.settings.router.stripTrailingSlash, 'Path cannot end with a trailing slash when connection configured to strip:', routeDisplay);

route = Schema.apply('route', route, routeDisplay);

const handler = route.handler || route.config.handler;
const handler = route.handler || config.handler;
const method = route.method.toLowerCase();
Hoek.assert(method !== 'head', 'Method name not allowed:', routeDisplay);

Expand All @@ -54,7 +60,7 @@ exports = module.exports = internals.Route = function (route, connection, plugin
const handlerDefaults = Handler.defaults(method, handler, connection.server);
let base = Hoek.applyToDefaultsWithShallow(connection.settings.routes, handlerDefaults, ['bind']);
base = Hoek.applyToDefaultsWithShallow(base, realm.settings, ['bind']);
this.settings = Hoek.applyToDefaultsWithShallow(base, route.config || {}, ['bind']);
this.settings = Hoek.applyToDefaultsWithShallow(base, config || {}, ['bind']);
this.settings.handler = handler;
this.settings = Schema.apply('routeConfig', this.settings, routeDisplay);

Expand Down Expand Up @@ -95,8 +101,8 @@ exports = module.exports = internals.Route = function (route, connection, plugin

// Assert on config, not on merged settings

Hoek.assert(!route.config || !route.config.payload, 'Cannot set payload settings on HEAD or GET request:', routeDisplay);
Hoek.assert(!route.config || !route.config.validate || !route.config.validate.payload, 'Cannot validate HEAD or GET requests:', routeDisplay);
Hoek.assert(!config || !config.payload, 'Cannot set payload settings on HEAD or GET request:', routeDisplay);
Hoek.assert(!config || !config.validate || !config.validate.payload, 'Cannot validate HEAD or GET requests:', routeDisplay);

validation.payload = null;
}
Expand Down
5 changes: 4 additions & 1 deletion lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,10 @@ internals.route = Joi.object({
path: Joi.string().required(),
vhost: internals.vhost,
handler: Joi.any(), // Validated in routeConfig
config: Joi.object().allow(null)
config: Joi.alternatives([
Joi.object(),
Joi.func()
]).allow(null)
});


Expand Down
2 changes: 1 addition & 1 deletion npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "hapi",
"description": "HTTP Server framework",
"homepage": "http://hapijs.com",
"version": "14.0.0",
"version": "14.1.0",
"repository": {
"type": "git",
"url": "git://github.com/hapijs/hapi"
Expand Down
30 changes: 30 additions & 0 deletions test/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,36 @@ const expect = Code.expect;

describe('Route', () => {

it('registers with config function', (done) => {

const server = new Hapi.Server();
server.connection();
server.bind({ a: 1 });
server.app.b = 2;
server.route({
method: 'GET',
path: '/',
config: function (srv) {

const a = this.a;

return {
handler: function (request, reply) {

return reply(a + srv.app.b);
}
};
}
});

server.inject('/', (res) => {

expect(res.statusCode).to.equal(200);
expect(res.result).to.equal(3);
done();
});
});

it('throws an error when a route is missing a path', (done) => {

expect(() => {
Expand Down

0 comments on commit 0272560

Please sign in to comment.