Comparing version 13.0.0 to 13.1.0
@@ -55,2 +55,3 @@ 'use strict'; | ||
response: { | ||
ranges: true, | ||
emptyStatusCode: 200, // HTTP status code when payload is empty (200, 204) | ||
@@ -57,0 +58,0 @@ options: {} // Joi validation options |
@@ -139,3 +139,3 @@ 'use strict'; | ||
exports.prerequisites = function (config, server) { | ||
exports.prerequisitesConfig = function (config, server) { | ||
@@ -142,0 +142,0 @@ if (!config) { |
@@ -62,18 +62,15 @@ 'use strict'; | ||
this.auth = { | ||
default: (opts) => { | ||
default: (opts) => this._applyChild('auth.default', 'auth', 'default', [opts]), | ||
scheme: (name, scheme) => this._applyChild('auth.scheme', 'auth', 'scheme', [name, scheme]), | ||
strategy: (name, scheme, mode, opts) => this._applyChild('auth.strategy', 'auth', 'strategy', [name, scheme, mode, opts]), | ||
test: (name, request, next) => request.connection.auth.test(name, request, next) | ||
}; | ||
this._applyChild('auth.default', 'auth', 'default', [opts]); | ||
}, | ||
scheme: (name, scheme) => { | ||
this.cache.provision = (opts, callback) => { | ||
this._applyChild('auth.scheme', 'auth', 'scheme', [name, scheme]); | ||
}, | ||
strategy: (name, scheme, mode, opts) => { | ||
if (!callback) { | ||
return Promises.wrap(null, this.cache.provision, [opts]); | ||
} | ||
this._applyChild('auth.strategy', 'auth', 'strategy', [name, scheme, mode, opts]); | ||
}, | ||
test: (name, request, next) => { | ||
return request.connection.auth.test(name, request, next); | ||
} | ||
return this.root._createCache(opts, callback); | ||
}; | ||
@@ -80,0 +77,0 @@ |
@@ -118,5 +118,5 @@ 'use strict'; | ||
internals.unstate = function (name) { | ||
internals.unstate = function (name, options) { | ||
this.request._clearState(name); | ||
this.request._clearState(name, options); | ||
}; | ||
@@ -123,0 +123,0 @@ |
@@ -500,3 +500,8 @@ 'use strict'; | ||
try { | ||
payload = JSON.stringify(payload, replacer, space); | ||
if (replacer || space) { | ||
payload = JSON.stringify(payload, replacer, space); | ||
} | ||
else { | ||
payload = JSON.stringify(payload); | ||
} | ||
} | ||
@@ -503,0 +508,0 @@ catch (err) { |
@@ -8,3 +8,2 @@ 'use strict'; | ||
const Hoek = require('hoek'); | ||
const Joi = require('joi'); | ||
const Subtext = require('subtext'); | ||
@@ -108,3 +107,3 @@ const Auth = require('./auth'); | ||
validation[type] = internals.compileRule(validation[type]); | ||
validation[type] = Validation.compile(validation[type]); | ||
}); | ||
@@ -127,6 +126,6 @@ | ||
else { | ||
this.settings.response.schema = internals.compileRule(rule); | ||
this.settings.response.schema = Validation.compile(rule); | ||
for (let i = 0; i < statuses.length; ++i) { | ||
const code = statuses[i]; | ||
this.settings.response.status[code] = internals.compileRule(this.settings.response.status[code]); | ||
this.settings.response.status[code] = Validation.compile(this.settings.response.status[code]); | ||
} | ||
@@ -215,3 +214,3 @@ } | ||
this.settings.handler = Handler.configure(this.settings.handler, this); | ||
this._prerequisites = Handler.prerequisites(this.settings.pre, this.server); | ||
this._prerequisites = Handler.prerequisitesConfig(this.settings.pre, this.server); | ||
@@ -264,15 +263,2 @@ // Route lifecycle | ||
internals.compileRule = function (rule) { | ||
// null, undefined, true - anything allowed | ||
// false - nothing allowed | ||
// {...} - ... allowed | ||
return (rule === false ? Joi.object({}).allow(null) | ||
: typeof rule === 'function' ? rule | ||
: !rule || rule === true ? null // false tested earlier | ||
: Joi.compile(rule)); | ||
}; | ||
internals.Route.prototype.rebuild = function (event) { | ||
@@ -279,0 +265,0 @@ |
@@ -22,14 +22,2 @@ 'use strict'; | ||
internals.cache = Joi.object({ | ||
name: Joi.string().invalid('_default'), | ||
partition: Joi.string(), | ||
shared: Joi.boolean(), | ||
engine: Joi.alternatives([ | ||
Joi.object(), | ||
Joi.func() | ||
]) | ||
.required() | ||
}).unknown(); | ||
internals.access = Joi.object({ | ||
@@ -127,8 +115,9 @@ entity: Joi.string().valid('user', 'app', 'any'), | ||
emptyStatusCode: Joi.number().valid(200, 204), | ||
schema: Joi.alternatives(Joi.object(), Joi.func()).allow(true, false), | ||
status: Joi.object().pattern(/\d\d\d/, Joi.alternatives(Joi.object(), Joi.func()).allow(true, false)), | ||
sample: Joi.number().min(0).max(100), | ||
failAction: Joi.string().valid('error', 'log'), | ||
modify: Joi.boolean(), | ||
options: Joi.object() | ||
options: Joi.object(), | ||
ranges: Joi.boolean(), | ||
sample: Joi.number().min(0).max(100), | ||
schema: Joi.alternatives(Joi.object(), Joi.func()).allow(true, false), | ||
status: Joi.object().pattern(/\d\d\d/, Joi.alternatives(Joi.object(), Joi.func()).allow(true, false)) | ||
}) | ||
@@ -200,7 +189,3 @@ .without('modify', 'sample') | ||
app: Joi.object().allow(null), | ||
cache: Joi.alternatives([ | ||
Joi.func(), | ||
internals.cache, | ||
Joi.array().items(internals.cache).min(1) | ||
]).allow(null), | ||
cache: Joi.allow(null), // Validated elsewhere | ||
connections: internals.connectionBase, | ||
@@ -286,2 +271,17 @@ debug: Joi.object({ | ||
internals.cacheConfig = Joi.object({ | ||
name: Joi.string().invalid('_default'), | ||
partition: Joi.string(), | ||
shared: Joi.boolean(), | ||
engine: Joi.alternatives([ | ||
Joi.object(), | ||
Joi.func() | ||
]) | ||
.required() | ||
}).unknown(); | ||
internals.cache = Joi.array().items(internals.cacheConfig, Joi.func()).min(1).single(); | ||
internals.cachePolicy = Joi.object({ | ||
@@ -288,0 +288,0 @@ cache: Joi.string().allow(null).allow(''), |
@@ -65,10 +65,7 @@ 'use strict'; | ||
if (options.cache) { | ||
const caches = [].concat(options.cache); | ||
for (let i = 0; i < caches.length; ++i) { | ||
this._createCache(caches[i]); | ||
} | ||
this._createCache(options.cache); | ||
} | ||
if (!this._caches._default) { | ||
this._createCache({ engine: CatboxMemory }); // Defaults to memory-based | ||
this._createCache([{ engine: CatboxMemory }]); // Defaults to memory-based | ||
} | ||
@@ -82,30 +79,53 @@ | ||
internals.Server.prototype._createCache = function (options) { | ||
internals.Server.prototype._createCache = function (options, _callback) { | ||
if (typeof options === 'function') { | ||
options = { engine: options }; | ||
} | ||
Hoek.assert(this._state !== 'initializing', 'Cannot provision server cache while server is initializing'); | ||
const name = options.name || '_default'; | ||
Hoek.assert(!this._caches[name], 'Cannot configure the same cache more than once: ', name === '_default' ? 'default cache' : name); | ||
options = Schema.apply('cache', options); | ||
let client = null; | ||
if (typeof options.engine === 'object') { | ||
client = new Catbox.Client(options.engine); | ||
const added = []; | ||
for (let i = 0; i < options.length; ++i) { | ||
let config = options[i]; | ||
if (typeof config === 'function') { | ||
config = { engine: config }; | ||
} | ||
const name = config.name || '_default'; | ||
Hoek.assert(!this._caches[name], 'Cannot configure the same cache more than once: ', name === '_default' ? 'default cache' : name); | ||
let client = null; | ||
if (typeof config.engine === 'object') { | ||
client = new Catbox.Client(config.engine); | ||
} | ||
else { | ||
const settings = Hoek.clone(config); | ||
settings.partition = settings.partition || 'hapi-cache'; | ||
delete settings.name; | ||
delete settings.engine; | ||
delete settings.shared; | ||
client = new Catbox.Client(config.engine, settings); | ||
} | ||
this._caches[name] = { | ||
client: client, | ||
segments: {}, | ||
shared: config.shared || false | ||
}; | ||
added.push(client); | ||
} | ||
else { | ||
const settings = Hoek.clone(options); | ||
settings.partition = settings.partition || 'hapi-cache'; | ||
delete settings.name; | ||
delete settings.engine; | ||
delete settings.shared; | ||
client = new Catbox.Client(options.engine, settings); | ||
if (!_callback) { | ||
return; | ||
} | ||
this._caches[name] = { | ||
client: client, | ||
segments: {}, | ||
shared: options.shared || false | ||
}; | ||
// Start cache | ||
if (['initialized', 'starting', 'started'].indexOf(this._state) !== -1) { | ||
const each = (client, next) => client.start(next); | ||
return Items.parallel(added, each, _callback); | ||
} | ||
return Hoek.nextTick(_callback)(); | ||
}; | ||
@@ -181,13 +201,17 @@ | ||
const errorCallback = Hoek.nextTick(callback); | ||
const nextTickCallback = Hoek.nextTick(callback); | ||
if (!this.connections.length) { | ||
return errorCallback(new Error('No connections to start')); | ||
return nextTickCallback(new Error('No connections to start')); | ||
} | ||
if (this._registring) { | ||
return errorCallback(new Error('Cannot start server before plugins finished registration')); | ||
return nextTickCallback(new Error('Cannot start server before plugins finished registration')); | ||
} | ||
if (this._state === 'initialized') { | ||
return nextTickCallback(); | ||
} | ||
if (this._state !== 'stopped') { | ||
return errorCallback(new Error('Cannot initialize server while it is in ' + this._state + ' state')); | ||
return nextTickCallback(new Error('Cannot initialize server while it is in ' + this._state + ' state')); | ||
} | ||
@@ -205,3 +229,3 @@ | ||
if (!connection.registrations[dep]) { | ||
return errorCallback(new Error('Plugin ' + dependency.plugin + ' missing dependency ' + dep + ' in connection: ' + connection.info.uri)); | ||
return nextTickCallback(new Error('Plugin ' + dependency.plugin + ' missing dependency ' + dep + ' in connection: ' + connection.info.uri)); | ||
} | ||
@@ -215,3 +239,3 @@ } | ||
if (!this._registrations[dep]) { | ||
return errorCallback(new Error('Plugin ' + dependency.plugin + ' missing dependency ' + dep)); | ||
return nextTickCallback(new Error('Plugin ' + dependency.plugin + ' missing dependency ' + dep)); | ||
} | ||
@@ -218,0 +242,0 @@ } |
@@ -215,3 +215,4 @@ 'use strict'; | ||
let ranger = null; | ||
if (request.method === 'get' && | ||
if (request.route.settings.response.ranges && | ||
request.method === 'get' && | ||
response.statusCode === 200 && | ||
@@ -218,0 +219,0 @@ length > 0 && |
@@ -15,2 +15,15 @@ 'use strict'; | ||
exports.compile = function (rule) { | ||
// null, undefined, true - anything allowed | ||
// false - nothing allowed | ||
// {...} - ... allowed | ||
return (rule === false ? Joi.object({}).allow(null) | ||
: typeof rule === 'function' ? rule | ||
: !rule || rule === true ? null // false tested earlier | ||
: Joi.compile(rule)); | ||
}; | ||
exports.query = function (request, next) { | ||
@@ -17,0 +30,0 @@ |
{ | ||
"name": "hapi", | ||
"version": "13.0.0", | ||
"version": "13.1.0", | ||
"dependencies": { | ||
@@ -12,3 +12,3 @@ "accept": { | ||
"boom": { | ||
"version": "3.1.1" | ||
"version": "3.1.2" | ||
}, | ||
@@ -40,3 +40,3 @@ "call": { | ||
"joi": { | ||
"version": "7.1.0", | ||
"version": "8.0.4", | ||
"dependencies": { | ||
@@ -47,3 +47,3 @@ "isemail": { | ||
"moment": { | ||
"version": "2.11.0" | ||
"version": "2.12.0" | ||
} | ||
@@ -59,3 +59,3 @@ } | ||
"mime-db": { | ||
"version": "1.20.0" | ||
"version": "1.22.0" | ||
} | ||
@@ -68,3 +68,3 @@ } | ||
"shot": { | ||
"version": "3.0.0" | ||
"version": "3.0.1" | ||
}, | ||
@@ -97,3 +97,3 @@ "statehood": { | ||
"wreck": { | ||
"version": "7.0.0" | ||
"version": "7.0.2" | ||
} | ||
@@ -100,0 +100,0 @@ } |
@@ -5,3 +5,3 @@ { | ||
"homepage": "http://hapijs.com", | ||
"version": "13.0.0", | ||
"version": "13.1.0", | ||
"repository": { | ||
@@ -33,3 +33,3 @@ "type": "git", | ||
"items": "2.x.x", | ||
"joi": "7.x.x", | ||
"joi": "8.x.x", | ||
"kilt": "2.x.x", | ||
@@ -47,4 +47,4 @@ "mimos": "3.x.x", | ||
"inert": "3.x.x", | ||
"lab": "8.x.x", | ||
"vision": "2.x.x", | ||
"lab": "10.x.x", | ||
"vision": "4.x.x", | ||
"wreck": "7.x.x" | ||
@@ -51,0 +51,0 @@ }, |
@@ -186,3 +186,3 @@ 'use strict'; | ||
describe('prerequisites()', () => { | ||
describe('prerequisitesConfig()', () => { | ||
@@ -189,0 +189,0 @@ it('shows the complete prerequisite pipeline in the response', (done) => { |
@@ -60,3 +60,3 @@ 'use strict'; | ||
reply.state('test', '123'); | ||
reply.unstate('empty'); | ||
reply.unstate('empty', { path: '/path' }); | ||
return reply.continue(); | ||
@@ -74,3 +74,3 @@ }; | ||
expect(res.headers['content-type']).to.equal('text/plain; something=something, charset=ISO-8859-1'); | ||
expect(res.headers['set-cookie']).to.deep.equal(['abc=123', 'sid=YWJjZGVmZzEyMzQ1Ng==', 'other=something; Secure', 'x=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT', 'test=123', 'empty=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT', 'always=present']); | ||
expect(res.headers['set-cookie']).to.deep.equal(['abc=123', 'sid=YWJjZGVmZzEyMzQ1Ng==', 'other=something; Secure', 'x=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT', 'test=123', 'empty=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/path', 'always=present']); | ||
expect(res.headers.vary).to.equal('x-control'); | ||
@@ -874,2 +874,38 @@ expect(res.headers.combo).to.equal('o-k'); | ||
}); | ||
it('sets type inside marshal', (done) => { | ||
const handler = function (request, reply) { | ||
const marshal = (response, callback) => { | ||
if (!response.headers['content-type']) { | ||
response.type('text/html'); | ||
} | ||
return callback(null, response.source); | ||
}; | ||
return reply(request.generateResponse('text', { variety: 'test', marshal })); | ||
}; | ||
const onPreResponse = function (request, reply) { | ||
request.response.charset('abc'); | ||
return reply.continue(); | ||
}; | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.ext('onPreResponse', onPreResponse); | ||
server.route({ method: 'GET', path: '/', handler: handler }); | ||
server.inject('/', (res) => { | ||
expect(res.statusCode).to.equal(200); | ||
expect(res.headers['content-type']).to.equal('text/html; charset=abc'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
@@ -1194,7 +1230,7 @@ | ||
expect(err).to.exist(); | ||
expect(err.message).to.contain('View file not found'); | ||
expect(err.message).to.contain('The partial x could not be found: The partial x could not be found'); | ||
done(); | ||
}); | ||
server.route({ method: 'GET', path: '/{param}', handler: { view: 'noview' } }); | ||
server.route({ method: 'GET', path: '/{param}', handler: { view: 'templates/invalid' } }); | ||
@@ -1201,0 +1237,0 @@ server.inject('/hello', (res) => { |
@@ -195,2 +195,19 @@ 'use strict'; | ||
it('does not re-initialize the server', (done) => { | ||
const server = new Hapi.Server(); | ||
server.connection(); | ||
server.initialize((err) => { | ||
expect(err).to.not.exist(); | ||
server.initialize((err) => { | ||
expect(err).to.not.exist(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('returns connection start error', (done) => { | ||
@@ -197,0 +214,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
1317519
53
20492