@hapi/hapi
Advanced tools
Comparing version 20.2.2 to 21.0.0-beta.0
@@ -70,3 +70,3 @@ 'use strict'; | ||
Hoek.assert(!strategy.response || typeof strategy.response === 'function', 'Invalid scheme:', name, 'invalid response() method'); | ||
strategy.options = strategy.options || {}; | ||
strategy.options = strategy.options ?? {}; | ||
Hoek.assert(strategy.payload || !strategy.options.payload, 'Cannot require payload validation without a payload method'); | ||
@@ -175,6 +175,6 @@ | ||
path = path || 'default strategy'; | ||
Hoek.assert(options.strategies && options.strategies.length, 'Missing authentication strategy:', path); | ||
path = path ?? 'default strategy'; | ||
Hoek.assert(options.strategies?.length, 'Missing authentication strategy:', path); | ||
options.mode = options.mode || 'required'; | ||
options.mode = options.mode ?? 'required'; | ||
@@ -309,5 +309,3 @@ if (options.entity !== undefined || // Backwards compatibility with <= 11.x.x | ||
const config = this.lookup(route || request.route); | ||
if (!config || | ||
!config.access) { | ||
if (!config?.access) { | ||
return true; | ||
@@ -395,3 +393,3 @@ } | ||
const config = auth.lookup(request.route); | ||
const setting = config.payload || (strategy.methods.options.payload ? 'required' : false); | ||
const setting = config.payload ?? (strategy.methods.options.payload ? 'required' : false); | ||
if (!setting) { | ||
@@ -458,9 +456,9 @@ return; | ||
const clean = type === 'selection' ? value : value.slice(1); | ||
scope[type] = scope[type] || []; | ||
scope[type] = scope[type] ?? []; | ||
scope[type].push(clean); | ||
if ((!scope._hasParameters || !scope._hasParameters[type]) && | ||
if ((!scope._hasParameters?.[type]) && | ||
/{([^}]+)}/.test(clean)) { | ||
scope._hasParameters = scope._hasParameters || {}; | ||
scope._hasParameters = scope._hasParameters ?? {}; | ||
scope._hasParameters[type] = true; | ||
@@ -476,3 +474,3 @@ } | ||
result = result || {}; | ||
result = result ?? {}; | ||
request.auth.isAuthenticated = !err; | ||
@@ -479,0 +477,0 @@ |
@@ -112,3 +112,4 @@ 'use strict'; | ||
additionalExposedHeaders: Validate.array().items(Validate.string()).default([]), | ||
credentials: Validate.boolean().when('origin', { is: 'ignore', then: false }).default(false) | ||
credentials: Validate.boolean().when('origin', { is: 'ignore', then: false }).default(false), | ||
preflightStatusCode: Validate.valid(200, 204).default(200) | ||
}) | ||
@@ -138,3 +139,2 @@ .allow(false, true) | ||
.default(), | ||
jsonp: Validate.string(), | ||
log: Validate.object({ | ||
@@ -199,3 +199,3 @@ collect: Validate.boolean().default(false) | ||
.default('deny'), | ||
xss: Validate.boolean().default(true), | ||
xss: Validate.valid('enabled', 'disabled', false).default('disabled'), | ||
noOpen: Validate.boolean().default(true), | ||
@@ -202,0 +202,0 @@ noSniff: Validate.boolean().default(true), |
@@ -12,4 +12,4 @@ 'use strict'; | ||
const Catbox = require('@hapi/catbox'); | ||
const CatboxMemory = require('@hapi/catbox-memory'); | ||
const Heavy = require('@hapi/heavy'); | ||
const { Engine: CatboxMemory } = require('@hapi/catbox-memory'); | ||
const { Heavy } = require('@hapi/heavy'); | ||
const Hoek = require('@hapi/hoek'); | ||
@@ -62,3 +62,3 @@ const { Mimos } = require('@hapi/mimos'); | ||
dependencies = []; // Plugin dependencies | ||
events = new Podium(internals.events); | ||
events = new Podium.Podium(internals.events); | ||
heavy = null; | ||
@@ -153,4 +153,4 @@ info = null; | ||
const data = event.error || event.data; | ||
console.error('Debug:', event.tags.join(', '), data ? '\n ' + (data.stack || (typeof data === 'object' ? Hoek.stringify(data) : data)) : ''); | ||
const data = event.error ?? event.data; | ||
console.error('Debug:', event.tags.join(', '), data ? '\n ' + (data.stack ?? (typeof data === 'object' ? Hoek.stringify(data) : data)) : ''); | ||
}; | ||
@@ -194,3 +194,3 @@ | ||
id: Os.hostname() + ':' + process.pid + ':' + now.toString(36), | ||
uri: this.settings.uri || (protocol + ':' + (this.type === 'tcp' ? '//' + host + (port ? ':' + port : '') : port)) | ||
uri: this.settings.uri ?? (protocol + ':' + (this.type === 'tcp' ? '//' + host + (port ? ':' + port : '') : port)) | ||
}; | ||
@@ -230,3 +230,3 @@ | ||
const name = config.name || '_default'; | ||
const name = config.name ?? '_default'; | ||
Hoek.assert(!this.caches.has(name), 'Cannot configure the same cache more than once: ', name === '_default' ? 'default cache' : name); | ||
@@ -242,3 +242,3 @@ | ||
client = new Catbox.Client(provider.constructor, provider.options || { partition: 'hapi-cache' }); | ||
client = new Catbox.Client(provider.constructor, provider.options ?? { partition: 'hapi-cache' }); | ||
} | ||
@@ -249,3 +249,3 @@ else { | ||
this.caches.set(name, { client, segments: {}, shared: config.shared || false }); | ||
this.caches.set(name, { client, segments: {}, shared: config.shared ?? false }); | ||
added.push(client); | ||
@@ -303,3 +303,3 @@ } | ||
this.phase = 'started'; | ||
await this.events.emit('start'); | ||
this.events.emit('start'); | ||
@@ -347,3 +347,4 @@ try { | ||
else { | ||
const address = this.settings.address || this.settings.host || '0.0.0.0'; | ||
// Default is the unspecified address, :: if IPv6 is available or otherwise the IPv4 address 0.0.0.0 | ||
const address = this.settings.address || this.settings.host || null; | ||
this.listener.listen(this.settings.port, address, finalize); | ||
@@ -404,3 +405,3 @@ } | ||
options.timeout = options.timeout || 5000; // Default timeout to 5 seconds | ||
options.timeout = options.timeout ?? 5000; // Default timeout to 5 seconds | ||
@@ -427,3 +428,3 @@ if (['stopped', 'initialized', 'started', 'invalid'].indexOf(this.phase) === -1) { | ||
await this.events.emit('stop'); | ||
this.events.emit('stop'); | ||
this.heavy.stop(); | ||
@@ -500,3 +501,3 @@ | ||
for (const ext of exts.nodes) { | ||
const bind = ext.bind || ext.realm.settings.bind; | ||
const bind = ext.bind ?? ext.realm.settings.bind; | ||
const operation = ext.func.call(bind, ext.server, bind); | ||
@@ -555,3 +556,3 @@ await Toolkit.timed(operation, { timeout: ext.timeout, name: type }); | ||
const listener = this.settings.listener || (this.settings.tls ? Https.createServer(this.settings.tls) : Http.createServer()); | ||
const listener = this.settings.listener ?? (this.settings.tls ? Https.createServer(this.settings.tls) : Http.createServer()); | ||
listener.on('request', this._dispatch()); | ||
@@ -593,3 +594,3 @@ listener.on('checkContinue', this._dispatch({ expectContinue: true })); | ||
this.info.port = address.port; | ||
this.info.uri = this.settings.uri || this.info.protocol + '://' + this.info.host + ':' + this.info.port; | ||
this.info.uri = this.settings.uri ?? this.info.protocol + '://' + this.info.host + ':' + this.info.port; | ||
} | ||
@@ -621,7 +622,7 @@ | ||
const plugin = realm && realm.plugin; | ||
const segment = options.segment || _segment || (plugin ? `!${plugin}` : ''); | ||
const plugin = realm?.plugin; | ||
const segment = options.segment ?? _segment ?? (plugin ? `!${plugin}` : ''); | ||
Hoek.assert(segment, 'Missing cache segment name'); | ||
const cacheName = options.cache || '_default'; | ||
const cacheName = options.cache ?? '_default'; | ||
const cache = this.caches.get(cacheName); | ||
@@ -670,3 +671,3 @@ Hoek.assert(cache, 'Unknown cache', cacheName); | ||
let settings = Hoek.clone(options, { shallow: ['cache', 'listener', 'routes.bind'] }); | ||
settings.app = settings.app || {}; | ||
settings.app = settings.app ?? {}; | ||
settings.routes = Config.enable(settings.routes); | ||
@@ -673,0 +674,0 @@ settings = Config.apply('server', settings); |
@@ -140,2 +140,3 @@ 'use strict'; | ||
const response = h.response(); | ||
response.code(settings.preflightStatusCode); | ||
response._header('access-control-allow-origin', settings._origin ? origin : '*'); | ||
@@ -142,0 +143,0 @@ response._header('access-control-allow-methods', method); |
@@ -96,3 +96,3 @@ 'use strict'; | ||
return defaults || {}; | ||
return defaults ?? {}; | ||
}; | ||
@@ -156,3 +156,3 @@ | ||
assign: pre.assign, | ||
failAction: pre.failAction || 'error' | ||
failAction: pre.failAction ?? 'error' | ||
}; | ||
@@ -159,0 +159,0 @@ |
@@ -26,3 +26,3 @@ 'use strict'; | ||
const ttl = response.settings.ttl !== null ? response.settings.ttl : request._route._cache.ttl(); | ||
const privacy = request.auth.isAuthenticated || response.headers['set-cookie'] ? 'private' : settings.privacy || 'default'; | ||
const privacy = request.auth.isAuthenticated || response.headers['set-cookie'] ? 'private' : settings.privacy ?? 'default'; | ||
response._header('cache-control', 'max-age=' + Math.floor(ttl / 1000) + ', must-revalidate' + (privacy !== 'default' ? ', ' + privacy : '')); | ||
@@ -44,13 +44,3 @@ } | ||
if (request.jsonp && | ||
response._payload.jsonp) { | ||
response._header('content-type', 'text/javascript' + (response.settings.charset ? '; charset=' + response.settings.charset : '')); | ||
response._header('x-content-type-options', 'nosniff'); | ||
response._payload.jsonp(request.jsonp); | ||
} | ||
if (response._payload.size && | ||
typeof response._payload.size === 'function') { | ||
if (typeof response._payload.size === 'function') { | ||
response._header('content-length', response._payload.size(), { override: false }); | ||
@@ -57,0 +47,0 @@ } |
@@ -36,3 +36,3 @@ 'use strict'; | ||
item = Config.apply('methodObject', item); | ||
this._add(item.name, item.method, item.options || {}, realm); | ||
this._add(item.name, item.method, item.options ?? {}, realm); | ||
} | ||
@@ -51,5 +51,5 @@ } | ||
const settings = Hoek.clone(options, { shallow: ['bind'] }); | ||
settings.generateKey = settings.generateKey || internals.generateKey; | ||
settings.generateKey = settings.generateKey ?? internals.generateKey; | ||
const bind = settings.bind || realm.settings.bind || null; | ||
const bind = settings.bind ?? realm.settings.bind ?? null; | ||
const bound = !bind ? method : (...args) => method.apply(bind, args); | ||
@@ -56,0 +56,0 @@ |
@@ -18,3 +18,3 @@ 'use strict'; | ||
events: Podium.validate(['finish', { name: 'peek', spread: true }, 'disconnect']), | ||
reserved: ['server', 'url', 'query', 'path', 'method', 'mime', 'setUrl', 'setMethod', 'headers', 'id', 'app', 'plugins', 'route', 'auth', 'pre', 'preResponses', 'info', 'isInjected', 'orig', 'params', 'paramsArray', 'payload', 'state', 'jsonp', 'response', 'raw', 'domain', 'log', 'logs', 'generateResponse'] | ||
reserved: ['server', 'url', 'query', 'path', 'method', 'mime', 'setUrl', 'setMethod', 'headers', 'id', 'app', 'plugins', 'route', 'auth', 'pre', 'preResponses', 'info', 'isInjected', 'orig', 'params', 'paramsArray', 'payload', 'state', 'response', 'raw', 'domain', 'log', 'logs', 'generateResponse'] | ||
}; | ||
@@ -45,3 +45,2 @@ | ||
this.headers = req.headers; | ||
this.jsonp = null; | ||
this.logs = []; | ||
@@ -71,6 +70,6 @@ this.method = req.method.toLowerCase(); | ||
isInjected: options.auth ? true : false, | ||
[internals.Request.symbols.authPayload]: options.auth && options.auth.payload !== undefined ? options.auth.payload : true, | ||
credentials: options.auth ? options.auth.credentials : null, // Special keys: 'app', 'user', 'scope' | ||
artifacts: options.auth && options.auth.artifacts || null, // Scheme-specific artifacts | ||
strategy: options.auth ? options.auth.strategy : null, | ||
[internals.Request.symbols.authPayload]: options.auth?.payload ?? true, | ||
credentials: options.auth?.credentials ?? null, // Special keys: 'app', 'user', 'scope' | ||
artifacts: options.auth?.artifacts ?? null, // Scheme-specific artifacts | ||
strategy: options.auth?.strategy ?? null, | ||
mode: null, | ||
@@ -104,3 +103,3 @@ error: null | ||
if (!this._events) { | ||
this._events = new Podium(internals.events); | ||
this._events = new Podium.Podium(internals.events); | ||
} | ||
@@ -333,4 +332,4 @@ | ||
this.params = match.params || {}; | ||
this.paramsArray = match.paramsArray || []; | ||
this.params = match.params ?? {}; | ||
this.paramsArray = match.paramsArray ?? []; | ||
@@ -402,3 +401,3 @@ if (this.route.settings.cors) { | ||
const realm = ext.realm; | ||
const bind = ext.bind || realm.settings.bind; | ||
const bind = ext.bind ?? realm.settings.bind; | ||
const response = await this._core.toolkit.execute(ext.func, this, { bind, realm, timeout: ext.timeout, name: event.type, ignoreResponse: options.ignoreResponse }); | ||
@@ -666,3 +665,11 @@ | ||
if (!this._remoteAddress) { | ||
this._remoteAddress = this._request.raw.req.connection.remoteAddress; | ||
const ipv6Prefix = '::ffff:'; | ||
const socketAddress = this._request.raw.req.socket.remoteAddress; | ||
if (socketAddress.startsWith(ipv6Prefix) && socketAddress.includes('.', ipv6Prefix.length)) { | ||
// Normalize IPv4-mapped IPv6 address, e.g. ::ffff:127.0.0.1 -> 127.0.0.1 | ||
this._remoteAddress = socketAddress.slice(ipv6Prefix.length); | ||
} | ||
else { | ||
this._remoteAddress = socketAddress; | ||
} | ||
} | ||
@@ -676,3 +683,3 @@ | ||
if (this._remotePort === null) { | ||
this._remotePort = this._request.raw.req.connection.remotePort || ''; | ||
this._remotePort = this._request.raw.req.socket.remotePort || ''; | ||
} | ||
@@ -716,3 +723,3 @@ | ||
if (event === 'close' && | ||
request.raw.res.finished) { | ||
request.raw.res.writableEnded) { | ||
@@ -719,0 +726,0 @@ return; |
@@ -58,3 +58,3 @@ 'use strict'; | ||
this._payload = null; // Readable stream | ||
this._error = options.error || null; // The boom object when created from an error (used for logging) | ||
this._error = options.error ?? null; // The boom object when created from an error (used for logging) | ||
this._contentType = null; // Used if no explicit content-type is set and type is known | ||
@@ -93,3 +93,3 @@ this._takeover = false; | ||
this.variety = variety || 'plain'; | ||
this.variety = variety ?? 'plain'; | ||
@@ -122,3 +122,3 @@ if (source === null || | ||
if (!this._events) { | ||
this._events = new Podium(internals.events); | ||
this._events = new Podium.Podium(internals.events); | ||
} | ||
@@ -157,3 +157,3 @@ | ||
const append = options.append || false; | ||
const append = options.append ?? false; | ||
const separator = options.separator || ','; | ||
@@ -352,3 +352,3 @@ const override = options.override !== false; | ||
this.settings.stringify = this.settings.stringify || {}; | ||
this.settings.stringify = this.settings.stringify ?? {}; | ||
this.settings.stringify.replacer = method; | ||
@@ -360,3 +360,3 @@ return this; | ||
this.settings.stringify = this.settings.stringify || {}; | ||
this.settings.stringify = this.settings.stringify ?? {}; | ||
this.settings.stringify.space = count; | ||
@@ -368,3 +368,3 @@ return this; | ||
this.settings.stringify = this.settings.stringify || {}; | ||
this.settings.stringify = this.settings.stringify ?? {}; | ||
this.settings.stringify.suffix = suffix; | ||
@@ -376,3 +376,3 @@ return this; | ||
this.settings.stringify = this.settings.stringify || {}; | ||
this.settings.stringify = this.settings.stringify ?? {}; | ||
this.settings.stringify.escape = escape; | ||
@@ -477,3 +477,3 @@ return this; | ||
this.settings.charset = charset || null; | ||
this.settings.charset = charset ?? null; | ||
return this; | ||
@@ -570,3 +570,3 @@ } | ||
this.statusCode = this.statusCode || 200; | ||
this.statusCode = this.statusCode ?? 200; | ||
} | ||
@@ -613,7 +613,7 @@ | ||
if (jsonify) { | ||
const options = this.settings.stringify || {}; | ||
const space = options.space || this.request.route.settings.json.space; | ||
const replacer = options.replacer || this.request.route.settings.json.replacer; | ||
const suffix = options.suffix || this.request.route.settings.json.suffix || ''; | ||
const escape = this.request.route.settings.json.escape || false; | ||
const options = this.settings.stringify ?? {}; | ||
const space = options.space ?? this.request.route.settings.json.space; | ||
const replacer = options.replacer ?? this.request.route.settings.json.replacer; | ||
const suffix = options.suffix ?? this.request.route.settings.json.suffix ?? ''; | ||
const escape = this.request.route.settings.json.escape; | ||
@@ -690,14 +690,3 @@ try { | ||
if (stream.destroy) { | ||
stream.destroy(); | ||
return; | ||
} | ||
// Fallback for old-style streams | ||
stream.unpipe(); | ||
if (stream.close) { | ||
stream.close(); | ||
} | ||
stream.destroy(); | ||
} | ||
@@ -726,5 +715,2 @@ }; | ||
this._data = payload; | ||
this._prefix = null; | ||
this._suffix = null; | ||
this._sizeOffset = 0; | ||
this._encoding = options.encoding; | ||
@@ -735,6 +721,2 @@ } | ||
if (this._prefix) { | ||
this.push(this._prefix, this._encoding); | ||
} | ||
if (this._data) { | ||
@@ -744,6 +726,2 @@ this.push(this._data, this._encoding); | ||
if (this._suffix) { | ||
this.push(this._suffix, this._encoding); | ||
} | ||
this.push(null); | ||
@@ -755,30 +733,10 @@ } | ||
if (!this._data) { | ||
return this._sizeOffset; | ||
return 0; | ||
} | ||
return (Buffer.isBuffer(this._data) ? this._data.length : Buffer.byteLength(this._data, this._encoding)) + this._sizeOffset; | ||
return Buffer.isBuffer(this._data) ? this._data.length : Buffer.byteLength(this._data, this._encoding); | ||
} | ||
jsonp(variable) { | ||
this._sizeOffset = this._sizeOffset + variable.length + 7; | ||
this._prefix = '/**/' + variable + '('; // '/**/' prefix prevents CVE-2014-4671 security exploit | ||
if (this._data !== null && | ||
!Buffer.isBuffer(this._data)) { | ||
this._data = this._data | ||
.replace(/\u2028/g, '\\u2028') | ||
.replace(/\u2029/g, '\\u2029'); | ||
} | ||
this._suffix = ');'; | ||
} | ||
writeToStream(stream) { | ||
if (this._prefix) { | ||
stream.write(this._prefix, this._encoding); | ||
} | ||
if (this._data) { | ||
@@ -788,6 +746,2 @@ stream.write(this._data, this._encoding); | ||
if (this._suffix) { | ||
stream.write(this._suffix, this._encoding); | ||
} | ||
stream.end(); | ||
@@ -794,0 +748,0 @@ } |
@@ -5,3 +5,2 @@ 'use strict'; | ||
const Boom = require('@hapi/boom'); | ||
const Bounce = require('@hapi/bounce'); | ||
@@ -44,3 +43,3 @@ const Catbox = require('@hapi/catbox'); | ||
const vhost = realm.modifiers.route.vhost || route.vhost; | ||
const vhost = realm.modifiers.route.vhost ?? route.vhost; | ||
@@ -54,3 +53,3 @@ // Set identifying members (assert) | ||
let config = route.options || route.config || {}; | ||
let config = route.options ?? route.config ?? {}; | ||
if (typeof config === 'function') { | ||
@@ -65,3 +64,3 @@ config = config.call(realm.settings.bind, server); | ||
this._assert(method !== 'get' || !config.payload, 'Cannot set payload settings on HEAD or GET request'); | ||
this._assert(method !== 'get' || !config.validate || !config.validate.payload, 'Cannot validate HEAD or GET request payload'); | ||
this._assert(method !== 'get' || !config.validate?.payload, 'Cannot validate HEAD or GET request payload'); | ||
@@ -71,3 +70,3 @@ // Rules | ||
this._assert(!route.rules || !config.rules, 'Route rules can only appear once'); // XOR | ||
const rules = route.rules || config.rules; | ||
const rules = route.rules ?? config.rules; | ||
const rulesConfig = internals.rules(rules, { method, path, vhost }, server); | ||
@@ -81,3 +80,3 @@ delete config.rules; | ||
const handler = Config.apply('handler', route.handler || config.handler); | ||
const handler = Config.apply('handler', route.handler ?? config.handler); | ||
delete config.handler; | ||
@@ -99,4 +98,4 @@ | ||
this.settings.vhost = vhost; | ||
this.settings.plugins = this.settings.plugins || {}; // Route-specific plugins settings, namespaced using plugin name | ||
this.settings.app = this.settings.app || {}; // Route-specific application settings | ||
this.settings.plugins = this.settings.plugins ?? {}; // Route-specific plugins settings, namespaced using plugin name | ||
this.settings.app = this.settings.app ?? {}; // Route-specific application settings | ||
@@ -137,3 +136,2 @@ // Path parsing | ||
this._assert(!this.settings.validate.state || this.settings.state.parse, 'Route state must be set to \'parse\' when state validation enabled'); | ||
this._assert(!this.settings.jsonp || typeof this.settings.jsonp === 'string', 'Bad route JSONP parameter name'); | ||
@@ -208,3 +206,3 @@ // Authentication configuration | ||
const rule = this.settings.response.schema; | ||
this.settings.response.status = this.settings.response.status || {}; | ||
this.settings.response.status = this.settings.response.status ?? {}; | ||
const statuses = Object.keys(this.settings.response.status); | ||
@@ -244,6 +242,2 @@ | ||
if (this.settings.jsonp) { | ||
this._cycle.push(internals.parseJSONP); | ||
} | ||
if (this.settings.state.parse) { | ||
@@ -291,6 +285,2 @@ this._cycle.push(internals.state); | ||
if (this.settings.jsonp) { | ||
this._cycle.push(internals.cleanupJSONP); | ||
} | ||
if (this.settings.validate.query) { | ||
@@ -403,4 +393,4 @@ this._cycle.push(Validation.query); | ||
const { states, failed = [] } = result || parseError; | ||
request.state = states || {}; | ||
const { states, failed = [] } = result ?? parseError; | ||
request.state = states ?? {}; | ||
@@ -444,3 +434,3 @@ // Clear cookies | ||
request._isPayloadPending = !!(payload && payload._readableState); | ||
request._isPayloadPending = !!payload?._readableState; | ||
request.mime = mime; | ||
@@ -473,26 +463,2 @@ request.payload = payload; | ||
internals.jsonpRegex = /^[\w\$\[\]\.]+$/; | ||
internals.parseJSONP = function (request) { | ||
const jsonp = request.query[request.route.settings.jsonp]; | ||
if (jsonp) { | ||
if (internals.jsonpRegex.test(jsonp) === false) { | ||
throw Boom.badRequest('Invalid JSONP parameter value'); | ||
} | ||
request.jsonp = jsonp; | ||
} | ||
}; | ||
internals.cleanupJSONP = function (request) { | ||
if (request.jsonp) { | ||
delete request.query[request.route.settings.jsonp]; | ||
} | ||
}; | ||
internals.config = function (chain) { | ||
@@ -499,0 +465,0 @@ |
@@ -21,3 +21,3 @@ 'use strict'; | ||
else { | ||
security._hsts = 'max-age=' + (security.hsts.maxAge || 15768000); | ||
security._hsts = 'max-age=' + (security.hsts.maxAge ?? 15768000); | ||
if (security.hsts.includeSubdomains || security.hsts.includeSubDomains) { | ||
@@ -69,5 +69,8 @@ security._hsts = security._hsts + '; includeSubDomains'; | ||
if (security.xss) { | ||
if (security.xss === 'enabled') { | ||
response._header('x-xss-protection', '1; mode=block', { override: false }); | ||
} | ||
else if (security.xss === 'disabled') { | ||
response._header('x-xss-protection', '0', { override: false }); | ||
} | ||
@@ -74,0 +77,0 @@ if (security.noOpen) { |
@@ -104,3 +104,3 @@ 'use strict'; | ||
this._core.controlled = this._core.controlled || []; | ||
this._core.controlled = this._core.controlled ?? []; | ||
this._core.controlled.push(server); | ||
@@ -150,3 +150,3 @@ } | ||
if (options.apply) { | ||
this._core.decorations.requestApply = this._core.decorations.requestApply || new Map(); | ||
this._core.decorations.requestApply = this._core.decorations.requestApply ?? new Map(); | ||
this._core.decorations.requestApply.set(property, method); | ||
@@ -243,3 +243,3 @@ } | ||
this._core.plugins[plugin] = this._core.plugins[plugin] || {}; | ||
this._core.plugins[plugin] = this._core.plugins[plugin] ?? {}; | ||
@@ -329,3 +329,3 @@ if (typeof key === 'string') { | ||
settings.authority = settings.authority || this._core.info.host + ':' + this._core.info.port; | ||
settings.authority = settings.authority ?? this._core.info.host + ':' + this._core.info.port; | ||
} | ||
@@ -421,6 +421,6 @@ | ||
options = Hoek.clone(options); | ||
options.routes = options.routes || {}; | ||
options.routes = options.routes ?? {}; | ||
options.routes.prefix = (this.realm.modifiers.route.prefix || '') + (options.routes.prefix || '') || undefined; | ||
options.routes.vhost = this.realm.modifiers.route.vhost || options.routes.vhost; | ||
options.routes.prefix = (this.realm.modifiers.route.prefix ?? '') + (options.routes.prefix ?? '') || undefined; | ||
options.routes.vhost = this.realm.modifiers.route.vhost ?? options.routes.vhost; | ||
} | ||
@@ -461,8 +461,8 @@ | ||
const name = item.plugin.name || item.plugin.pkg.name; | ||
const name = item.plugin.name ?? item.plugin.pkg.name; | ||
const clone = this._clone(name); | ||
clone.realm.modifiers.route.prefix = item.routes.prefix || options.routes.prefix; | ||
clone.realm.modifiers.route.vhost = item.routes.vhost || options.routes.vhost; | ||
clone.realm.pluginOptions = item.options || {}; | ||
clone.realm.modifiers.route.prefix = item.routes.prefix ?? options.routes.prefix; | ||
clone.realm.modifiers.route.vhost = item.routes.vhost ?? options.routes.vhost; | ||
clone.realm.pluginOptions = item.options ?? {}; | ||
@@ -489,3 +489,3 @@ // Validate requirements | ||
this._core.registrations[name] = { | ||
version: item.plugin.version || item.plugin.pkg.version, | ||
version: item.plugin.version ?? item.plugin.pkg.version, | ||
name, | ||
@@ -502,3 +502,3 @@ options: item.options | ||
await item.plugin.register(clone, item.options || {}); | ||
await item.plugin.register(clone, item.options ?? {}); | ||
} | ||
@@ -533,3 +533,3 @@ } | ||
const route = new Route(config, server); // Do no use config beyond this point, use route members | ||
const vhosts = [].concat(route.settings.vhost || '*'); | ||
const vhosts = [].concat(route.settings.vhost ?? '*'); | ||
@@ -536,0 +536,0 @@ for (const vhost of vhosts) { |
'use strict'; | ||
const Stream = require('stream'); | ||
const Boom = require('@hapi/boom'); | ||
const Teamwork = require('@hapi/teamwork'); | ||
const internals = { | ||
@@ -14,14 +15,14 @@ team: Symbol('team') | ||
if (!stream || | ||
typeof stream !== 'object' || | ||
typeof stream.pipe !== 'function') { | ||
const isReadableStream = stream instanceof Stream.Readable; | ||
return false; | ||
if (!isReadableStream && | ||
typeof stream?.pipe === 'function') { | ||
throw Boom.badImplementation('Cannot reply with a stream-like object that is not an instance of Stream.Readable'); | ||
} | ||
if (typeof stream._read !== 'function') { | ||
throw Boom.badImplementation('Stream must have a readable interface'); | ||
if (!isReadableStream) { | ||
return false; | ||
} | ||
if (stream._readableState.objectMode) { | ||
if (stream.readableObjectMode) { | ||
throw Boom.badImplementation('Cannot reply with stream in object mode'); | ||
@@ -28,0 +29,0 @@ } |
@@ -45,3 +45,3 @@ 'use strict'; | ||
const h = new this._toolkit(request, options); | ||
const bind = options.bind || null; | ||
const bind = options.bind ?? null; | ||
@@ -106,3 +106,3 @@ try { | ||
if (!response.isBoom && response._state === 'init') { | ||
response = await response._prepare(); | ||
await response._prepare(); | ||
} | ||
@@ -135,3 +135,3 @@ } | ||
return this.execute(failAction, request, { realm: request.route.realm, args: [options.details || err] }); | ||
return this.execute(failAction, request, { realm: request.route.realm, args: [options.details ?? err] }); | ||
} | ||
@@ -231,3 +231,3 @@ }; | ||
Hoek.assert(this._auth, 'Method not supported outside of authentication'); | ||
Hoek.assert(data && data.credentials, 'Authentication data missing credentials information'); | ||
Hoek.assert(data?.credentials, 'Authentication data missing credentials information'); | ||
@@ -234,0 +234,0 @@ return new internals.Auth(null, data); |
@@ -286,3 +286,3 @@ 'use strict'; | ||
if (request.raw.res.finished) { | ||
if (request.raw.res.writableEnded) { | ||
if (!event) { | ||
@@ -289,0 +289,0 @@ request.info.responded = Date.now(); |
@@ -22,3 +22,3 @@ 'use strict'; | ||
validator = validator || internals.validator(realm, core); | ||
validator = validator ?? internals.validator(realm, core); | ||
@@ -150,3 +150,3 @@ // false - nothing allowed | ||
const defaultError = validationError.isBoom ? validationError : Boom.badRequest(`Invalid request ${source} input`); | ||
const detailedError = Boom.boomify(validationError, { statusCode: 400, override: false }); | ||
const detailedError = Boom.boomify(validationError, { statusCode: 400, override: false, data: { defaultError } }); | ||
detailedError.output.payload.validation = { source, keys: [] }; | ||
@@ -153,0 +153,0 @@ if (validationError.details) { |
@@ -5,3 +5,3 @@ { | ||
"homepage": "https://hapi.dev", | ||
"version": "20.2.2", | ||
"version": "21.0.0-beta.0", | ||
"repository": "git://github.com/hapijs/hapi", | ||
@@ -27,29 +27,29 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"@hapi/accept": "^5.0.1", | ||
"@hapi/ammo": "^5.0.1", | ||
"@hapi/boom": "^9.1.0", | ||
"@hapi/bounce": "^2.0.0", | ||
"@hapi/call": "^8.0.0", | ||
"@hapi/catbox": "^11.1.1", | ||
"@hapi/catbox-memory": "^5.0.0", | ||
"@hapi/heavy": "^7.0.1", | ||
"@hapi/hoek": "^9.0.4", | ||
"@hapi/mimos": "^6.0.0", | ||
"@hapi/podium": "^4.1.1", | ||
"@hapi/shot": "^5.0.5", | ||
"@hapi/somever": "^3.0.0", | ||
"@hapi/statehood": "^7.0.4", | ||
"@hapi/subtext": "^7.0.3", | ||
"@hapi/teamwork": "^5.1.1", | ||
"@hapi/topo": "^5.0.0", | ||
"@hapi/validate": "^1.1.1" | ||
"@hapi/accept": "^6.0.0", | ||
"@hapi/ammo": "^6.0.0", | ||
"@hapi/boom": "^10.0.0", | ||
"@hapi/bounce": "^3.0.0", | ||
"@hapi/call": "^9.0.0", | ||
"@hapi/catbox": "^12.0.0", | ||
"@hapi/catbox-memory": "^6.0.0", | ||
"@hapi/heavy": "^8.0.0", | ||
"@hapi/hoek": "^10.0.0", | ||
"@hapi/mimos": "^7.0.0", | ||
"@hapi/podium": "^5.0.0", | ||
"@hapi/shot": "^6.0.0", | ||
"@hapi/somever": "^4.0.0", | ||
"@hapi/statehood": "^8.0.0", | ||
"@hapi/subtext": "^8.0.0", | ||
"@hapi/teamwork": "^6.0.0", | ||
"@hapi/topo": "^6.0.0", | ||
"@hapi/validate": "^2.0.0" | ||
}, | ||
"devDependencies": { | ||
"@hapi/code": "^8.0.0", | ||
"@hapi/eslint-plugin": "*", | ||
"@hapi/code": "^9.0.0", | ||
"@hapi/eslint-plugin": "^6.0.0", | ||
"@hapi/inert": "^6.0.2", | ||
"@hapi/joi-legacy-test": "npm:@hapi/joi@^15.0.0", | ||
"@hapi/lab": "^24.4.0", | ||
"@hapi/lab": "^25.0.1", | ||
"@hapi/vision": "^6.0.1", | ||
"@hapi/wreck": "^17.0.0", | ||
"@hapi/wreck": "^18.0.0", | ||
"handlebars": "^4.7.4", | ||
@@ -56,0 +56,0 @@ "joi": "^17.0.0", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
182086
4562
1
+ Added@hapi/accept@6.0.3(transitive)
+ Added@hapi/ammo@6.0.1(transitive)
+ Added@hapi/b64@6.0.1(transitive)
+ Added@hapi/boom@10.0.1(transitive)
+ Added@hapi/bounce@3.0.2(transitive)
+ Added@hapi/bourne@3.0.0(transitive)
+ Added@hapi/call@9.0.1(transitive)
+ Added@hapi/catbox@12.1.1(transitive)
+ Added@hapi/content@6.0.0(transitive)
+ Added@hapi/cryptiles@6.0.1(transitive)
+ Added@hapi/file@3.0.0(transitive)
+ Added@hapi/heavy@8.0.1(transitive)
+ Added@hapi/hoek@10.0.111.0.6(transitive)
+ Added@hapi/iron@7.0.1(transitive)
+ Added@hapi/mimos@7.0.1(transitive)
+ Added@hapi/nigel@5.0.1(transitive)
+ Added@hapi/pez@6.1.0(transitive)
+ Added@hapi/podium@5.0.1(transitive)
+ Added@hapi/shot@6.0.1(transitive)
+ Added@hapi/somever@4.1.1(transitive)
+ Added@hapi/statehood@8.1.1(transitive)
+ Added@hapi/subtext@8.1.0(transitive)
+ Added@hapi/teamwork@6.0.0(transitive)
+ Added@hapi/topo@6.0.2(transitive)
+ Added@hapi/validate@2.0.1(transitive)
+ Added@hapi/vise@5.0.1(transitive)
- Removed@hapi/accept@5.0.2(transitive)
- Removed@hapi/ammo@5.0.1(transitive)
- Removed@hapi/b64@5.0.0(transitive)
- Removed@hapi/boom@9.1.4(transitive)
- Removed@hapi/bounce@2.0.0(transitive)
- Removed@hapi/bourne@2.1.0(transitive)
- Removed@hapi/call@8.0.1(transitive)
- Removed@hapi/catbox@11.1.1(transitive)
- Removed@hapi/content@5.0.2(transitive)
- Removed@hapi/cryptiles@5.1.0(transitive)
- Removed@hapi/file@2.0.0(transitive)
- Removed@hapi/heavy@7.0.1(transitive)
- Removed@hapi/hoek@9.3.0(transitive)
- Removed@hapi/iron@6.0.0(transitive)
- Removed@hapi/mimos@6.0.0(transitive)
- Removed@hapi/nigel@4.0.2(transitive)
- Removed@hapi/pez@5.1.0(transitive)
- Removed@hapi/podium@4.1.3(transitive)
- Removed@hapi/shot@5.0.5(transitive)
- Removed@hapi/somever@3.0.1(transitive)
- Removed@hapi/statehood@7.0.4(transitive)
- Removed@hapi/subtext@7.1.0(transitive)
- Removed@hapi/teamwork@5.1.1(transitive)
- Removed@hapi/topo@5.1.0(transitive)
- Removed@hapi/validate@1.1.3(transitive)
- Removed@hapi/vise@4.0.0(transitive)
Updated@hapi/accept@^6.0.0
Updated@hapi/ammo@^6.0.0
Updated@hapi/boom@^10.0.0
Updated@hapi/bounce@^3.0.0
Updated@hapi/call@^9.0.0
Updated@hapi/catbox@^12.0.0
Updated@hapi/catbox-memory@^6.0.0
Updated@hapi/heavy@^8.0.0
Updated@hapi/hoek@^10.0.0
Updated@hapi/mimos@^7.0.0
Updated@hapi/podium@^5.0.0
Updated@hapi/shot@^6.0.0
Updated@hapi/somever@^4.0.0
Updated@hapi/statehood@^8.0.0
Updated@hapi/subtext@^8.0.0
Updated@hapi/teamwork@^6.0.0
Updated@hapi/topo@^6.0.0
Updated@hapi/validate@^2.0.0