Skip to content

Commit 0272560

Browse files
committed
Config function. Closes #3277
1 parent af4e5f0 commit 0272560

File tree

6 files changed

+52
-11
lines changed

6 files changed

+52
-11
lines changed

API.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 14.0.x API Reference
1+
# 14.1.x API Reference
22

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

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

21392141
Note that the `options` object is deeply cloned (with the exception of `bind` which is shallowly
21402142
copied) and cannot contain any values that are unsafe to perform deep copy on.

lib/route.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,19 @@ exports = module.exports = internals.Route = function (route, connection, plugin
3939

4040
Hoek.assert(route.path, 'Route missing path');
4141
const routeDisplay = route.method + ' ' + route.path;
42-
Hoek.assert(route.handler || (route.config && route.config.handler), 'Missing or undefined handler:', routeDisplay);
43-
Hoek.assert(!!route.handler ^ !!(route.config && route.config.handler), 'Handler must only appear once:', routeDisplay); // XOR
42+
43+
let config = route.config;
44+
if (typeof config === 'function') {
45+
config = config.call(realm.settings.bind, connection.server);
46+
}
47+
48+
Hoek.assert(route.handler || (config && config.handler), 'Missing or undefined handler:', routeDisplay);
49+
Hoek.assert(!!route.handler ^ !!(config && config.handler), 'Handler must only appear once:', routeDisplay); // XOR
4450
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);
4551

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

48-
const handler = route.handler || route.config.handler;
54+
const handler = route.handler || config.handler;
4955
const method = route.method.toLowerCase();
5056
Hoek.assert(method !== 'head', 'Method name not allowed:', routeDisplay);
5157

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

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

96102
// Assert on config, not on merged settings
97103

98-
Hoek.assert(!route.config || !route.config.payload, 'Cannot set payload settings on HEAD or GET request:', routeDisplay);
99-
Hoek.assert(!route.config || !route.config.validate || !route.config.validate.payload, 'Cannot validate HEAD or GET requests:', routeDisplay);
104+
Hoek.assert(!config || !config.payload, 'Cannot set payload settings on HEAD or GET request:', routeDisplay);
105+
Hoek.assert(!config || !config.validate || !config.validate.payload, 'Cannot validate HEAD or GET requests:', routeDisplay);
100106

101107
validation.payload = null;
102108
}

lib/schema.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,10 @@ internals.route = Joi.object({
230230
path: Joi.string().required(),
231231
vhost: internals.vhost,
232232
handler: Joi.any(), // Validated in routeConfig
233-
config: Joi.object().allow(null)
233+
config: Joi.alternatives([
234+
Joi.object(),
235+
Joi.func()
236+
]).allow(null)
234237
});
235238

236239

npm-shrinkwrap.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "hapi",
33
"description": "HTTP Server framework",
44
"homepage": "http://hapijs.com",
5-
"version": "14.0.0",
5+
"version": "14.1.0",
66
"repository": {
77
"type": "git",
88
"url": "git://github.com/hapijs/hapi"

test/route.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,36 @@ const expect = Code.expect;
2626

2727
describe('Route', () => {
2828

29+
it('registers with config function', (done) => {
30+
31+
const server = new Hapi.Server();
32+
server.connection();
33+
server.bind({ a: 1 });
34+
server.app.b = 2;
35+
server.route({
36+
method: 'GET',
37+
path: '/',
38+
config: function (srv) {
39+
40+
const a = this.a;
41+
42+
return {
43+
handler: function (request, reply) {
44+
45+
return reply(a + srv.app.b);
46+
}
47+
};
48+
}
49+
});
50+
51+
server.inject('/', (res) => {
52+
53+
expect(res.statusCode).to.equal(200);
54+
expect(res.result).to.equal(3);
55+
done();
56+
});
57+
});
58+
2959
it('throws an error when a route is missing a path', (done) => {
3060

3161
expect(() => {

0 commit comments

Comments
 (0)