Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

hapi

Package Overview
Dependencies
Maintainers
1
Versions
295
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hapi - npm Package Compare versions

Comparing version 17.0.0-rc6 to 17.0.0-rc8

11

lib/auth.js

@@ -41,9 +41,6 @@ 'use strict';

_strategy(server, name, scheme, ...args /*, mode, options */) {
_strategy(server, name, scheme, options) {
const hasMode = (typeof args[0] === 'string' || typeof args[0] === 'boolean');
const mode = (hasMode ? args[0] : false);
const options = (hasMode ? args[1] : args[0]) || null;
Hoek.assert(name, 'Authentication strategy must have a name');
Hoek.assert(!options || typeof options === 'object', 'options must be an object');
Hoek.assert(name !== 'bypass', 'Cannot use reserved strategy name: bypass');

@@ -72,6 +69,2 @@ Hoek.assert(!this._strategies[name], 'Authentication strategy name already exists');

}
if (mode) {
this.default({ strategies: [name], mode: mode === true ? 'required' : mode });
}
}

@@ -78,0 +71,0 @@

65

lib/config.js

@@ -81,2 +81,9 @@ 'use strict';

internals.failAction = Joi.alternatives([
Joi.string().valid('error', 'log', 'ignore'),
Joi.func()
])
.default('error');
internals.routeBase = Joi.object({

@@ -144,7 +151,3 @@ app: Joi.object().allow(null),

uploads: Joi.string().default(Os.tmpdir()),
failAction: Joi.alternatives([
Joi.string().valid('error', 'log', 'ignore'),
Joi.func()
])
.default('error'),
failAction: internals.failAction,
timeout: Joi.number().integer().positive().allow(false).default(10 * 1000),

@@ -160,6 +163,3 @@ defaultContentType: Joi.string().default('application/json'),

emptyStatusCode: Joi.number().valid(200, 204).default(200),
failAction: [
Joi.string().valid('error', 'log'),
Joi.func()
],
failAction: internals.failAction,
modify: Joi.boolean(),

@@ -204,3 +204,3 @@ options: Joi.object().default(),

parse: Joi.boolean().default(true),
failAction: Joi.string().valid('error', 'log', 'ignore').default('error')
failAction: internals.failAction
})

@@ -214,10 +214,7 @@ .default(),

validate: Joi.object({
headers: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(null, false, true),
params: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(null, false, true),
headers: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(null, true),
params: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(null, true),
query: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(null, false, true),
payload: Joi.alternatives(Joi.object(), Joi.array(), Joi.func()).allow(null, false, true),
failAction: [
Joi.string().valid('error', 'log', 'ignore'),
Joi.func()
],
failAction: internals.failAction,
errorFields: Joi.object(),

@@ -300,3 +297,3 @@ options: Joi.object().default()

mode: Joi.string().valid('serial', 'parallel'),
failAction: Joi.string().valid('error', 'log', 'ignore')
failAction: internals.failAction
})

@@ -364,3 +361,3 @@ ];

internals.register = Joi.object({
once: Joi.boolean(),
once: Joi.boolean().valid(true),
routes: Joi.object({

@@ -375,26 +372,20 @@ prefix: Joi.string().regex(/^\/.+/),

internals.plugin = internals.register.keys({
register: Joi.func().keys({
attributes: Joi.object({
pkg: Joi.object({
name: Joi.string(),
version: Joi.string().default('0.0.0')
})
.unknown()
.default({
version: '0.0.0'
}),
name: Joi.string()
.when('pkg.name', { is: Joi.exist(), otherwise: Joi.required() }),
version: Joi.string(),
multiple: Joi.boolean().default(false),
dependencies: Joi.array().items(Joi.string()).single(),
once: Joi.boolean().valid(true)
options: Joi.any(),
plugin: Joi.object({
register: Joi.func().required(),
name: Joi.string().when('pkg.name', { is: Joi.exist(), otherwise: Joi.required() }),
version: Joi.string(),
multiple: Joi.boolean().default(false),
dependencies: Joi.array().items(Joi.string()).single(),
once: Joi.boolean().valid(true),
pkg: Joi.object({
name: Joi.string(),
version: Joi.string().default('0.0.0')
})
.required()
.unknown()
.default({})
})
.required(),
options: Joi.any()
.unknown()
})
.without('once', 'options')
.unknown();

@@ -68,3 +68,3 @@ 'use strict';

this.compression = new Compression();
this.decorations = { request: [], toolkit: [], server: [] };
this.decorations = { handler: [], request: [], server: [], toolkit: [] };
this.dependencies = []; // Plugin dependencies

@@ -82,3 +82,3 @@ this.events = new Podium(internals.events);

this.app = {};
this.registring = false; // true while register() is waiting for plugin callbacks
this.registring = 0; // > 0 while register() is waiting for plugin callbacks
this.requestCounter = { value: internals.counter.min, min: internals.counter.min, max: internals.counter.max };

@@ -221,3 +221,2 @@ this.router = new Call.Router(this.settings.router);

this.instances.add(server);
server.root = this.root.realm;
}

@@ -224,0 +223,0 @@

@@ -38,3 +38,5 @@ 'use strict';

const result = await internals.handler(request, request.route.settings.handler);
if (result._takeover) {
if (result._takeover ||
typeof result === 'symbol') {
return result;

@@ -51,3 +53,3 @@ }

const realm = request.route.realm;
const response = await request._core.toolkit.execute(method, request, { bind, realm, continue: 'null' });
let response = await request._core.toolkit.execute(method, request, { bind, realm, continue: 'null' });

@@ -68,9 +70,3 @@ // Handler

if (response.isBoom) {
if (pre.failAction !== 'ignore') {
request._log(['pre', 'error'], { assign: pre.assign, error: response });
}
if (pre.failAction === 'error') {
throw response;
}
response = await request._core.toolkit.failAction(request, pre.failAction, response, { tags: ['pre', 'error'], log: { assign: pre.assign, error: response }, retain: true });
}

@@ -83,3 +79,3 @@

if (pre.assign) {
request.pre[pre.assign] = (response instanceof Error ? response : response.source);
request.pre[pre.assign] = (response.isBoom ? response : response.source);
request.preResponses[pre.assign] = response;

@@ -86,0 +82,0 @@ }

@@ -192,11 +192,8 @@ 'use strict';

if (this._core.extensions.route.onRequest.nodes) {
let response;
try {
response = await this._invoke(this._core.extensions.route.onRequest);
}
catch (err) {
response = err;
}
const response = await this._invoke(this._core.extensions.route.onRequest);
if (response) {
if (!internals.skip(response)) {
throw Boom.badImplementation('onRequest extension methods must return an error, a takeover response, or a continue signal');
}
if (response) {
throw response;

@@ -295,13 +292,21 @@ }

if (response &&
response !== this._core.toolkit.continue) {
if (!response ||
response === this._core.toolkit.continue) { // Continue
continue;
}
if (internals.skip(response) &&
(!postCycle || !response._takeover)) {
this._setResponse(response);
return;
}
if (!postCycle ||
typeof response === 'symbol') {
if (this.response === null) {
this._setResponse(Boom.badImplementation('Lifecycle methods called before the handler can only return an error, a takeover response, or a continue signal'));
return;
}
return;
}
}
this._setResponse(response);
}

@@ -318,26 +323,12 @@ }

// Process response
if (typeof response === 'symbol') {
if (response === this._core.toolkit.continue) {
continue;
}
return response;
if (response === this._core.toolkit.continue) {
continue;
}
if (response.isBoom) { // response can be replaced by prepare()
throw response;
}
if (internals.skip(response) ||
this.response === null) {
if (response._takeover) {
return response;
}
if (event.type !== 'onPostHandler' &&
event.type !== 'onPreResponse') {
throw Boom.badImplementation(`${event.type} extension methods must return an error, a takeover response, or a continue signal`);
}
this._setResponse(response);

@@ -368,3 +359,3 @@ }

if (typeof this.response === 'symbol') { // close or abort
if (typeof this.response === 'symbol') { // close or abandon
this._abort();

@@ -376,3 +367,3 @@ return;

if (typeof this.response === 'symbol') { // close or abort
if (typeof this.response === 'symbol') { // close or abandon
this._abort();

@@ -609,1 +600,7 @@ return;

};
internals.skip = function (response) {
return (response.isBoom || response._takeover || typeof response === 'symbol');
};

@@ -58,2 +58,6 @@ 'use strict';

this.temporary = null;
this.permanent = null;
this.rewritable = null;
this._setSource(source, options.variety);

@@ -64,5 +68,11 @@ }

return (result instanceof Error) ?
Boom.boomify(result) :
(result instanceof internals.Response ? result : new internals.Response(result, request));
if (result instanceof internals.Response) {
return result;
}
if (result instanceof Error) {
return Boom.boomify(result);
}
return new internals.Response(result, request);
}

@@ -469,3 +479,6 @@

const key = headerKeys[i];
this.header(key.toLowerCase(), Hoek.clone(this.source.headers[key])); // Clone arrays
const lower = key.toLowerCase();
if (lower !== 'connection'){ // Do not copy per-hop connection options
this.header(lower, Hoek.clone(this.source.headers[key])); // Clone arrays
}
}

@@ -472,0 +485,0 @@

@@ -117,2 +117,4 @@ 'use strict';

Hoek.assert(!validation.params || this.params.length, 'Cannot set path parameters validations without path parameters:', routeDisplay);
['headers', 'params', 'query', 'payload'].forEach((type) => {

@@ -354,14 +356,7 @@

// failAction: 'error', 'log', 'ignore'
if (!parseError ||
request.route.settings.state.failAction === 'ignore') {
if (!parseError) {
return;
}
request._log(['state', 'error'], { header: cookies, errors: parseError.data });
if (request.route.settings.state.failAction === 'error') {
return parseError;
}
return request._core.toolkit.failAction(request, request.route.settings.state.failAction, parseError, { tags: ['state', 'error'], log: { header: cookies, errors: parseError.data } });
};

@@ -401,26 +396,3 @@

// failAction: 'error', 'log', 'ignore', function (request, h, error)
const failAction = request.route.settings.payload.failAction;
if (failAction === 'ignore') {
return;
}
request._log(['payload', 'error'], err);
// Log only
if (failAction === 'log') {
return;
}
// Return error
if (typeof failAction !== 'function') {
throw err;
}
// Custom handler
return await request._core.toolkit.execute(failAction, request, { realm: request.route.realm, args: [err] });
return request._core.toolkit.failAction(request, request.route.settings.payload.failAction, err, { tags: ['payload', 'error'] });
}

@@ -427,0 +399,0 @@ };

@@ -29,3 +29,3 @@ 'use strict';

constructor(core, name) {
constructor(core, name, parent) {

@@ -49,3 +49,2 @@ this._core = core;

this.registrations = core.registrations;
this.root = null; // The root server realm (set by core)
this.settings = core.settings;

@@ -67,2 +66,3 @@ this.states = core.states;

},
parent: (parent ? parent.realm : null),
plugin: name,

@@ -92,123 +92,5 @@ pluginOptions: {},

return new internals.Server(this._core, name);
return new internals.Server(this._core, name, this);
}
async register(plugins, options = {}) {
if (this.realm.modifiers.route.prefix ||
this.realm.modifiers.route.vhost) {
options = Hoek.clone(options);
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 = Config.apply('register', options);
/*
const register = async function (server, options) { };
register.attributes = {
pkg: require('../package.json'),
name: 'plugin',
version: '1.1.1',
multiple: false,
dependencies: [],
once: true
};
const item = {
register: register,
options: options // -optional--
};
- OR -
const item = function () {}
item.register = register;
item.options = options;
const plugins = register, items, [register, item]
*/
const registrations = [];
plugins = [].concat(plugins);
for (let i = 0; i < plugins.length; ++i) {
let plugin = plugins[i];
if (typeof plugin === 'function') {
if (!plugin.register) { // plugin is register() function
plugin = { register: plugin };
}
else {
plugin = Hoek.shallow(plugin); // Convert function to object
}
}
if (plugin.register.register) { // Required plugin
plugin.register = plugin.register.register;
}
plugin = Config.apply('plugin', plugin);
const attributes = plugin.register.attributes;
const registration = {
register: plugin.register,
name: attributes.name || attributes.pkg.name,
version: attributes.version || attributes.pkg.version,
multiple: attributes.multiple,
pluginOptions: plugin.options,
dependencies: attributes.dependencies,
options: {
once: attributes.once || (plugin.once !== undefined ? plugin.once : options.once),
routes: {
prefix: plugin.routes.prefix || options.routes.prefix,
vhost: plugin.routes.vhost || options.routes.vhost
}
}
};
registrations.push(registration);
}
this._core.registring = true;
for (let i = 0; i < registrations.length; ++i) {
const item = registrations[i];
const clone = new internals.Server(this._core, item.name);
clone.realm.modifiers.route.prefix = item.options.routes.prefix;
clone.realm.modifiers.route.vhost = item.options.routes.vhost;
clone.realm.pluginOptions = item.pluginOptions || {};
// Protect against multiple registrations
if (this._core.registrations[item.name]) {
if (item.options.once) {
continue;
}
Hoek.assert(item.multiple, 'Plugin', item.name, 'already registered');
}
else {
this._core.registrations[item.name] = {
version: item.version,
name: item.name,
options: item.pluginOptions,
attributes: item.register.attributes
};
}
if (item.dependencies) {
clone.dependency(item.dependencies);
}
// Register
await item.register(clone, item.pluginOptions || {});
};
this._core.registring = false;
}
bind(context) {

@@ -231,3 +113,15 @@

Hoek.assert(property[0] !== '_', 'Property name cannot begin with an underscore:', property);
Hoek.assert(!options || type === 'request', 'Cannot specify options for non-request decoration');
// Handler
if (type === 'handler') {
Hoek.assert(!this._core.handlers[property], 'Handler name already exists:', property);
Hoek.assert(typeof method === 'function', 'Handler must be a function:', property);
Hoek.assert(!method.defaults || typeof method.defaults === 'object' || typeof method.defaults === 'function', 'Handler defaults property must be an object or function');
this._core.handlers[property] = method;
this._core.decorations.handler.push(property);
}
// Request

@@ -241,6 +135,4 @@

Hoek.assert(!options, 'Cannot specify options for non-request decoration');
// Toolkit
// Responder
if (type === 'toolkit') {

@@ -346,11 +238,2 @@ this._core.toolkit.decorate(property, method);

handler(name, method) {
Hoek.assert(typeof name === 'string', 'Invalid handler name');
Hoek.assert(!this._core.handlers[name], 'Handler name already exists:', name);
Hoek.assert(typeof method === 'function', 'Handler must be a function:', name);
Hoek.assert(!method.defaults || typeof method.defaults === 'object' || typeof method.defaults === 'function', 'Handler defaults property must be an object or function');
this._core.handlers[name] = method;
}
async inject(options) {

@@ -445,2 +328,92 @@

async register(plugins, options = {}) {
if (this.realm.modifiers.route.prefix ||
this.realm.modifiers.route.vhost) {
options = Hoek.clone(options);
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 = Config.apply('register', options);
++this._core.registring;
try {
const items = [].concat(plugins);
for (let i = 0; i < items.length; ++i){
let item = items[i];
/*
{ register, ...attributes }
{ plugin: { register, ...attributes }, options, once, routes }
{ plugin: { plugin: { register, ...attributes } }, options, once, routes } // Required module
*/
if (!item.plugin) {
item = {
plugin: item
};
}
else if (!item.plugin.register) {
item = {
options: item.options,
once: item.once,
routes: item.routes,
plugin: item.plugin.plugin
};
}
else if (typeof item === 'function') {
item = Hoek.shallow(item);
}
item = Config.apply('plugin', item);
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 || {};
// Protect against multiple registrations
if (this._core.registrations[name]) {
if (item.plugin.once ||
item.once ||
options.once) {
continue;
}
Hoek.assert(item.plugin.multiple, 'Plugin', name, 'already registered');
}
else {
this._core.registrations[name] = {
version: item.plugin.version || item.plugin.pkg.version,
name,
options: item.options
};
}
if (item.plugin.dependencies) {
clone.dependency(item.plugin.dependencies);
}
// Register
await item.plugin.register(clone, item.options || {});
}
}
catch (err) {
throw err;
}
finally {
--this._core.registring;
}
}
route(options) {

@@ -491,3 +464,3 @@

return [{ info: this._core.info, table: this._core.router.table(host) }];
return this._core.router.table(host);
}

@@ -494,0 +467,0 @@

@@ -82,2 +82,21 @@ 'use strict';

}
failAction(request, failAction, err, options) {
const retain = options.retain ? err : undefined;
if (failAction === 'ignore') {
return retain;
}
if (failAction === 'log') {
request._log(options.tags, options.log || err);
return retain;
}
if (failAction === 'error') {
throw err;
}
return this.execute(failAction, request, { realm: request.route.realm, args: [options.details || err] });
}
};

@@ -89,3 +108,3 @@

result / h.response(result) -> result // Not allowed in auth or in ext before handler
result / h.response(result) -> result // Not allowed before handler
h.response(result).takeover() -> result (respond)

@@ -108,4 +127,2 @@ h.continue -> null // Defaults to null only in handler and pre, not allowed in auth

this.realm = options.realm;
this.request = request;

@@ -116,2 +133,4 @@ this.abandon = manager.abandon;

this.context = options.bind;
this.realm = options.realm;
this.request = request;

@@ -135,2 +154,5 @@ if (options.auth) {

Hoek.assert(!result || typeof result !== 'object' || typeof result.then !== 'function', 'Cannot wrap a promise');
Hoek.assert(result instanceof Error === false, 'Cannot wrap an error');
Hoek.assert(typeof result !== 'symbol', 'Cannot wrap a symbol');
return Response.wrap(result, this.request);

@@ -155,4 +177,2 @@ }

}
return null;
}

@@ -159,0 +179,0 @@

@@ -225,3 +225,10 @@ 'use strict';

response._header('content-encoding', encoding);
return request._core.compression.encoder(request, encoding);
const compressor = request._core.compression.encoder(request, encoding);
if (response.variety === 'stream' &&
typeof response._payload.setCompressor === 'function') {
response._payload.setCompressor(compressor);
}
return compressor;
};

@@ -228,0 +235,0 @@

@@ -30,11 +30,15 @@ 'use strict';

// TODO: Remove async and await from lifecycle methods
exports.headers = function (request) {
exports.query = async function (request) {
return internals.input('headers', request);
};
return await internals.input('query', request);
exports.params = function (request) {
return internals.input('params', request);
};
exports.payload = async function (request) {
exports.payload = function (request) {

@@ -47,18 +51,12 @@ if (request.method === 'get' ||

return await internals.input('payload', request);
return internals.input('payload', request);
};
exports.params = async function (request) {
exports.query = function (request) {
return await internals.input('params', request);
return internals.input('query', request);
};
exports.headers = async function (request) {
return await internals.input('headers', request);
};
internals.input = async function (source, request) {

@@ -98,3 +96,3 @@

catch (err) {
validationError = (err.isJoi ? err : Boom.boomify(err));
validationError = err;
}

@@ -108,4 +106,2 @@ finally {

// failAction: 'error', 'log', 'ignore', function (source, err)
if (request.route.settings.validate.failAction === 'ignore') {

@@ -117,8 +113,9 @@ return;

const error = (validationError.isBoom ? validationError : Boom.badRequest(validationError.message, validationError));
error.output.payload.validation = { source, keys: [] };
const defaultError = validationError.isBoom ? validationError : Boom.badRequest(`Invalid request ${source} input`);
const detailedError = Boom.boomify(validationError, { statusCode: 400, override: false });
detailedError.output.payload.validation = { source, keys: [] };
if (validationError.details) {
for (let i = 0; i < validationError.details.length; ++i) {
const path = validationError.details[i].path;
error.output.payload.validation.keys.push(Hoek.escapeHtml(path.join('.')));
detailedError.output.payload.validation.keys.push(Hoek.escapeHtml(path.join('.')));
}

@@ -131,23 +128,7 @@ }

const field = fields[i];
error.output.payload[field] = request.route.settings.validate.errorFields[field];
detailedError.output.payload[field] = request.route.settings.validate.errorFields[field];
}
}
request._log(['validation', 'error', source], error);
// Log only
if (request.route.settings.validate.failAction === 'log') {
return;
}
// Return error
if (typeof request.route.settings.validate.failAction !== 'function') {
throw error;
}
// Custom handler
return request._core.toolkit.execute(request.route.settings.validate.failAction, request, { realm: request.route.realm, args: [source, error] });
return request._core.toolkit.failAction(request, request.route.settings.validate.failAction, defaultError, { details: detailedError, tags: ['validation', 'error', source] });
};

@@ -228,19 +209,4 @@

// failAction: 'error', 'log'
if (request.route.settings.response.failAction === 'log') {
request._log(['validation', 'response', 'error'], err.message);
return;
}
// Return error
if (typeof request.route.settings.response.failAction !== 'function') {
throw Boom.badImplementation(err.message);
}
// Custom handler
return request._core.toolkit.execute(request.route.settings.response.failAction, request, { realm: request.route.realm, args: [err] });
return request._core.toolkit.failAction(request, request.route.settings.response.failAction, err, { tags: ['validation', 'response', 'error'] });
}
};

@@ -5,3 +5,3 @@ {

"homepage": "http://hapijs.com",
"version": "17.0.0-rc6",
"version": "17.0.0-rc8",
"repository": {

@@ -26,7 +26,7 @@ "type": "git",

"call": "5.x.x",
"catbox": "8.x.x",
"catbox": "9.x.x",
"catbox-memory": "3.x.x",
"heavy": "5.x.x",
"hoek": "5.x.x",
"joi": "11.x.x",
"joi": "13.x.x",
"mimos": "4.x.x",

@@ -43,5 +43,6 @@ "podium": "3.x.x",

"handlebars": "4.x.x",
"inert": "^5.0.0-rc5",
"hapitoc": "1.x.x",
"inert": "5.0.0-rc8",
"lab": "14.x.x",
"vision": "^5.0.0-rc5",
"vision": "5.0.0-rc8",
"wreck": "13.x.x"

@@ -52,5 +53,6 @@ },

"test-tap": "lab -a code -r tap -o tests.tap -m 3000",
"test-cov-html": "lab -a code -r html -o coverage.html -m 3000"
"test-cov-html": "lab -a code -r html -o coverage.html -m 3000",
"toc": "hapitoc"
},
"license": "BSD-3-Clause"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc