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.2 to 17.1.0

26

lib/config.js

@@ -274,8 +274,15 @@ 'use strict';

internals.handler = Joi.alternatives([
Joi.func(),
Joi.object().length(1)
]);
internals.route = Joi.object({
method: Joi.string().regex(/^[a-zA-Z0-9!#\$%&'\*\+\-\.^_`\|~]+$/).required(),
path: Joi.string().required(),
rules: Joi.object(),
vhost: internals.vhost,
// Validated in routeConfig
// Validated in route construction

@@ -301,10 +308,5 @@ handler: Joi.any(),

internals.routeConfig = internals.routeBase.keys({
description: Joi.string(),
id: Joi.string(),
isInternal: Joi.boolean(),
pre: Joi.array().items(internals.pre.concat(Joi.array().items(internals.pre).min(1))),
handler: [
Joi.func(),
Joi.object().length(1)
],
description: Joi.string(),
notes: [

@@ -314,2 +316,3 @@ Joi.string(),

],
pre: Joi.array().items(internals.pre.concat(Joi.array().items(internals.pre).min(1))),
tags: [

@@ -389,1 +392,10 @@ Joi.string(),

.unknown();
internals.rules = Joi.object({
validate: Joi.object({
schema: Joi.alternatives(Joi.object(), Joi.array()).required(),
options: Joi.object()
.default({ allowUnknown: true })
})
});

@@ -65,6 +65,5 @@ 'use strict';

this.compression = new Compression();
this.decorations = { handler: [], request: [], server: [], toolkit: [] };
this.decorations = { handler: [], request: [], server: [], toolkit: [] }; // Public decoration names
this.dependencies = []; // Plugin dependencies
this.events = new Podium(internals.events);
this.handlers = {}; // Registered handlers
this.heavy = new Heavy(this.settings.load);

@@ -75,3 +74,2 @@ this.instances = new Set();

this.registrations = {}; // Tracks plugin for dependency validation { name -> { version } }
this.requestor = new Request();
this.onConnection = null; // Used to remove event listener on stop

@@ -84,3 +82,2 @@ this.plugins = {}; // Exposed plugin properties by name

this.phase = 'stopped'; // 'stopped', 'initializing', 'initialized', 'starting', 'started', 'stopping', 'invalid'
this.serverDecorations = {};
this.sockets = new Set(); // Track open sockets for graceful shutdown

@@ -111,2 +108,3 @@ this.started = false;

this._debug();
this._decorations = { handler: {}, request: {}, server: {}, toolkit: {}, requestApply: null };
this._initializeCache();

@@ -445,3 +443,3 @@

const request = this.requestor.request(this.root, req, res, options);
const request = Request.generate(this.root, req, res, options);

@@ -448,0 +446,0 @@ // Check load

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

const type = Object.keys(handler)[0];
const serverHandler = core.handlers[type];
const serverHandler = core._decorations.handler[type];

@@ -111,3 +111,3 @@ Hoek.assert(serverHandler, 'Unknown handler:', type);

const type = Object.keys(handler)[0];
const serverHandler = route._core.handlers[type];
const serverHandler = route._core._decorations.handler[type];

@@ -114,0 +114,0 @@ Hoek.assert(serverHandler, 'Unknown handler:', type);

@@ -20,44 +20,9 @@ 'use strict';

const internals = {
properties: ['server', 'url', 'query', 'path', 'method', 'mime', 'setUrl', 'setMethod', 'headers', 'id', 'app', 'plugins', 'route', 'auth', 'pre', 'preResponses', 'info', 'orig', 'params', 'paramsArray', 'payload', 'state', 'jsonp', 'response', 'raw', 'domain', 'log', 'logs', 'generateResponse'],
events: Podium.validate(['finish', { name: 'peek', spread: true }, 'disconnect'])
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', 'orig', 'params', 'paramsArray', 'payload', 'state', 'jsonp', 'response', 'raw', 'domain', 'log', 'logs', 'generateResponse']
};
exports = module.exports = internals.Generator = class {
exports = module.exports = internals.Request = class {
constructor() {
this._decorations = null;
}
request(server, req, res, options) {
const request = new internals.Request(server, req, res, options);
// Decorate
if (this._decorations) {
const properties = Object.keys(this._decorations);
for (let i = 0; i < properties.length; ++i) {
const property = properties[i];
const assignment = this._decorations[property];
request[property] = (assignment.apply ? assignment.method(request) : assignment.method);
}
}
return request;
}
decorate(property, method, options) {
Hoek.assert(internals.properties.indexOf(property) === -1, 'Cannot override built-in request interface decoration:', property);
this._decorations = this._decorations || {};
this._decorations[property] = { method, apply: options.apply };
}
};
internals.Request = class {
constructor(server, req, res, options) {

@@ -116,2 +81,20 @@

static generate(server, req, res, options) {
const request = new internals.Request(server, req, res, options);
// Decorate
if (server._core._decorations.requestApply) {
const properties = Object.keys(server._core._decorations.requestApply);
for (let i = 0; i < properties.length; ++i) {
const property = properties[i];
const assignment = server._core._decorations.requestApply[property];
request[property] = assignment(request);
}
}
return request;
}
get events() {

@@ -497,2 +480,5 @@

internals.Request.reserved = internals.reserved;
internals.info = function (core, req) {

@@ -499,0 +485,0 @@

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

const Hoek = require('hoek');
const Joi = require('joi');
const Subtext = require('subtext');

@@ -35,18 +36,18 @@

// Apply plugin environment (before schema validation)
// Routing information
if (realm.modifiers.route.vhost ||
realm.modifiers.route.prefix) {
const display = `${route.method} ${route.path}`;
Config.apply('route', route, display);
route = Hoek.cloneWithShallow(route, ['options']); // options is left unchanged
route.path = (realm.modifiers.route.prefix ? realm.modifiers.route.prefix + (route.path !== '/' ? route.path : '') : route.path);
route.vhost = realm.modifiers.route.vhost || route.vhost;
}
const method = route.method.toLowerCase();
Hoek.assert(method !== 'head', 'Method name not allowed:', display);
// Setup and validate route configuration
const path = (realm.modifiers.route.prefix ? realm.modifiers.route.prefix + (route.path !== '/' ? route.path : '') : route.path);
Hoek.assert(path === '/' || path[path.length - 1] !== '/' || !core.settings.router.stripTrailingSlash, 'Path cannot end with a trailing slash when configured to strip:', display);
Hoek.assert(route.path, 'Route missing path');
const routeDisplay = route.method + ' ' + route.path;
const vhost = (realm.modifiers.route.vhost || route.vhost);
let config = route.options || route.config;
// Prepare configuration
let config = route.options || route.config || {};
if (typeof config === 'function') {

@@ -56,32 +57,40 @@ config = config.call(realm.settings.bind, server);

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] !== '/' || !core.settings.router.stripTrailingSlash, 'Path cannot end with a trailing slash when configured to strip:', routeDisplay);
config = Config.enable(config); // Shallow clone
config = Config.enable(config);
route = Config.apply('route', route, routeDisplay);
// Rules
const handler = route.handler || config.handler;
const method = route.method.toLowerCase();
Hoek.assert(method !== 'head', 'Method name not allowed:', routeDisplay);
Hoek.assert(!route.rules || !config.rules, 'Route rules can only appear once:', display); // XOR
const rules = (route.rules || config.rules);
const rulesConfig = internals.rules(rules, { method, path, vhost }, server);
delete config.rules;
// Apply settings in order: {server} <- {handler} <- {realm} <- {route}
// Handler
Hoek.assert(route.handler || config.handler, 'Missing or undefined handler:', display);
Hoek.assert(!!route.handler ^ !!config.handler, 'Handler must only appear once:', display); // XOR
const handler = Config.apply('handler', route.handler || config.handler);
delete config.handler;
const handlerDefaults = Handler.defaults(method, handler, core);
let base = Hoek.applyToDefaultsWithShallow(core.settings.routes, handlerDefaults, ['bind']);
base = Hoek.applyToDefaultsWithShallow(base, realm.settings, ['bind']);
this.settings = Hoek.applyToDefaultsWithShallow(base, config, ['bind', 'validate.headers', 'validate.payload', 'validate.params', 'validate.query']);
this.settings.handler = handler;
this.settings = Config.apply('routeConfig', this.settings, routeDisplay);
// Apply settings in order: server <- handler <- realm <- route
const settings = internals.config([core.settings.routes, handlerDefaults, realm.settings, rulesConfig, config]);
this.settings = Config.apply('routeConfig', settings, display);
// Validate timeouts
const socketTimeout = (this.settings.timeout.socket === undefined ? 2 * 60 * 1000 : this.settings.timeout.socket);
Hoek.assert(!this.settings.timeout.server || !socketTimeout || this.settings.timeout.server < socketTimeout, 'Server timeout must be shorter than socket timeout:', routeDisplay);
Hoek.assert(!this.settings.payload.timeout || !socketTimeout || this.settings.payload.timeout < socketTimeout, 'Payload timeout must be shorter than socket timeout:', routeDisplay);
Hoek.assert(!this.settings.timeout.server || !socketTimeout || this.settings.timeout.server < socketTimeout, 'Server timeout must be shorter than socket timeout:', display);
Hoek.assert(!this.settings.payload.timeout || !socketTimeout || this.settings.payload.timeout < socketTimeout, 'Payload timeout must be shorter than socket timeout:', display);
// Route members
this._core = core;
this.path = route.path;
this.path = path;
this.method = method;
this.realm = realm;
this.settings.vhost = route.vhost;
this.settings.vhost = vhost;
this.settings.plugins = this.settings.plugins || {}; // Route-specific plugins settings, namespaced using plugin name

@@ -100,3 +109,3 @@ this.settings.app = this.settings.app || {}; // Route-specific application settings

path: this.path,
vhost: this.vhost,
vhost,
realm,

@@ -117,4 +126,4 @@ settings: this.settings,

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

@@ -124,3 +133,3 @@ validation.payload = null;

Hoek.assert(!validation.params || this.params.length, 'Cannot set path parameters validations without path parameters:', routeDisplay);
Hoek.assert(!validation.params || this.params.length, 'Cannot set path parameters validations without path parameters:', display);

@@ -164,8 +173,8 @@ ['headers', 'params', 'query', 'payload'].forEach((type) => {

Hoek.assert(!this.settings.validate.payload || this.settings.payload.parse, 'Route payload must be set to \'parse\' when payload validation enabled:', routeDisplay);
Hoek.assert(!this.settings.jsonp || typeof this.settings.jsonp === 'string', 'Bad route JSONP parameter name:', routeDisplay);
Hoek.assert(!this.settings.validate.payload || this.settings.payload.parse, 'Route payload must be set to \'parse\' when payload validation enabled:', display);
Hoek.assert(!this.settings.jsonp || typeof this.settings.jsonp === 'string', 'Bad route JSONP parameter name:', display);
// Authentication configuration
this.settings.auth = (this._special ? false : this._core.auth._setupRoute(this.settings.auth, route.path));
this.settings.auth = (this._special ? false : this._core.auth._setupRoute(this.settings.auth, path));

@@ -192,3 +201,3 @@ // Cache

this.settings.handler = Handler.configure(this.settings.handler, this);
this.settings.handler = Handler.configure(handler, this);
this._prerequisites = Handler.prerequisitesConfig(this.settings.pre);

@@ -454,1 +463,38 @@

};
internals.config = function (chain) {
if (!chain.length) {
return {};
}
let config = chain[0];
for (let i = 1; i < chain.length; ++i) {
config = Hoek.applyToDefaultsWithShallow(config, chain[i], ['bind', 'validate.headers', 'validate.payload', 'validate.params', 'validate.query']);
}
return config;
};
internals.rules = function (rules, info, server) {
const configs = [];
let realm = server.realm;
while (realm) {
if (realm._rules) {
const source = (!realm._rules.settings.validate ? rules : Joi.attempt(rules, realm._rules.settings.validate.schema, realm._rules.settings.validate.options));
const config = realm._rules.processor(source, info);
if (config) {
configs.unshift(config);
}
}
realm = realm.parent;
}
return internals.config(configs);
};

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

const Hoek = require('hoek');
const Joi = require('joi');
const Shot = require('shot');

@@ -14,2 +15,3 @@

const Package = require('../package.json');
const Request = require('./request');
const Route = require('./route');

@@ -72,2 +74,3 @@

plugins: {},
_rules: null,
settings: {

@@ -83,6 +86,5 @@ bind: undefined,

const methods = Object.keys(core.serverDecorations);
for (let i = 0; i < methods.length; ++i) {
const method = methods[i];
this[method] = core.serverDecorations[method];
for (let i = 0; i < core.decorations.server.length; ++i) {
const method = core.decorations.server[i];
this[method] = core._decorations.server[method];
}

@@ -115,4 +117,15 @@

Hoek.assert(property[0] !== '_', 'Property name cannot begin with an underscore:', property);
Hoek.assert(this._core.decorations[type].indexOf(property) === -1, `${type[0].toUpperCase() + type.slice(1)} decoration already defined: ${property}`);
const existing = this._core._decorations[type][property];
if (options.extend) {
Hoek.assert(type !== 'handler', 'Cannot extent handler decoration:', property);
Hoek.assert(existing, `Cannot extend missing ${type} decoration: ${property}`);
Hoek.assert(typeof method === 'function', `Extended ${type} decoration method must be a function: ${property}`);
method = method(existing);
}
else {
Hoek.assert(existing === undefined, `${type[0].toUpperCase() + type.slice(1)} decoration already defined: ${property}`);
}
if (type === 'handler') {

@@ -124,4 +137,3 @@

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;
Hoek.assert(!options.extend, 'Cannot extend handler decoration:', property);
}

@@ -132,3 +144,11 @@ else if (type === 'request') {

this._core.requestor.decorate(property, method, options);
Hoek.assert(Request.reserved.indexOf(property) === -1, 'Cannot override built-in request interface decoration:', property);
if (options.apply) {
this._core._decorations.requestApply = this._core._decorations.requestApply || {};
this._core._decorations.requestApply[property] = method;
}
else {
Request.prototype[property] = method;
}
}

@@ -139,3 +159,3 @@ else if (type === 'toolkit') {

this._core.toolkit.decorate(property, method);
Hoek.assert(this._core.toolkit.reserved.indexOf(property) === -1, 'Cannot override built-in toolkit decoration:', property);
}

@@ -146,5 +166,4 @@ else {

Hoek.assert(this[property] === undefined && this._core[property] === undefined, 'Cannot override the built-in server interface method:', property);
Hoek.assert(Object.getOwnPropertyNames(internals.Server.prototype).indexOf(property) === -1, 'Cannot override the built-in server interface method:', property);
this._core.serverDecorations[property] = method;
this._core.instances.forEach((server) => {

@@ -156,2 +175,3 @@

this._core._decorations[type][property] = method;
this._core.decorations[type].push(property);

@@ -348,3 +368,3 @@ }

const items = [].concat(plugins);
for (let i = 0; i < items.length; ++i){
for (let i = 0; i < items.length; ++i) {
let item = items[i];

@@ -460,2 +480,15 @@

rules(processor, options = {}) {
Hoek.assert(!this.realm._rules, 'Server realm rules already defined');
const settings = Config.apply('rules', options);
if (settings.validate) {
const schema = settings.validate.schema;
settings.validate.schema = Joi.compile(schema);
}
this.realm._rules = { processor, settings };
}
state(name, options) {

@@ -462,0 +495,0 @@

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

const internals = {};
const internals = {
reserved: ['abandon', 'authenticated', 'close', 'context', 'continue', 'entity', 'redirect', 'realm', 'request', 'response', 'state', 'unauthenticated', 'unstate']
};

@@ -22,17 +24,8 @@

this._decorations = null;
this.abandon = Symbol('abandon');
this.close = Symbol('close');
this.continue = Symbol('continue');
this.reserved = internals.reserved;
}
decorate(property, method) {
Hoek.assert(['abandon', 'authenticated', 'close', 'context', 'continue', 'entity', 'redirect', 'realm', 'request', 'response', 'state', 'unauthenticated', 'unstate'].indexOf(property) === -1, 'Cannot override built-in toolkit decoration:', property);
this._decorations = this._decorations || {};
this._decorations[property] = method;
}
async execute(method, request, options) {

@@ -61,3 +54,3 @@

if (response === undefined) {
response = Boom.badImplementation('Method did not return a value, a promise, or throw an error');
response = Boom.badImplementation(`${method.name} method did not return a value, a promise, or throw an error`);
}

@@ -135,3 +128,2 @@

this.abandon = manager.abandon;

@@ -149,8 +141,5 @@ this.close = manager.close;

if (manager._decorations) {
const methods = Object.keys(manager._decorations);
for (let i = 0; i < methods.length; ++i) {
const method = methods[i];
this[method] = manager._decorations[method];
}
for (let i = 0; i < request._core.decorations.toolkit.length; ++i) {
const method = request._core.decorations.toolkit[i];
this[method] = request._core._decorations.toolkit[method];
}

@@ -157,0 +146,0 @@ }

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

"homepage": "http://hapijs.com",
"version": "17.0.2",
"version": "17.1.0",
"repository": {

@@ -8,0 +8,0 @@ "type": "git",

@@ -11,3 +11,3 @@ <img src="https://raw.github.com/hapijs/hapi/master/images/17.png" align="right"/>

Development version: **17.0.x** ([release notes](https://github.com/hapijs/hapi/issues?labels=release+notes&page=1&state=closed))
Development version: **17.1.x** ([release notes](https://github.com/hapijs/hapi/issues?labels=release+notes&page=1&state=closed))
[![Build Status](https://secure.travis-ci.org/hapijs/hapi.svg?branch=master)](http://travis-ci.org/hapijs/hapi)

@@ -14,0 +14,0 @@

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