New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.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 14.2.0 to 15.0.1

lib/compression.js

124

lib/auth.js

@@ -90,8 +90,3 @@ 'use strict';

const transfer = (response, data) => {
return next(response, data && data.credentials);
};
const reply = request.server._replier.interface(request, strategy.realm, transfer);
const reply = request.server._replier.interface(request, strategy.realm, { data: true }, (response) => next(response, reply._data && reply._data.credentials));
strategy.methods.authenticate(request, reply);

@@ -138,3 +133,3 @@ };

const access = options.access[i];
access.scope = internals.scope(access);
access.scope = internals.setupScope(access);
}

@@ -164,3 +159,3 @@ }

internals.scope = function (access) {
internals.setupScope = function (access) {

@@ -209,2 +204,19 @@ if (!access.scope) {

internals.Auth.access = function (request, route) {
const auth = request.connection.auth;
const config = auth.lookup(route);
if (!config) {
return true;
}
const credentials = request.auth.credentials;
if (!credentials) {
return false;
}
return !internals.access(request, config, credentials, 'bypass');
};
internals.Auth.prototype._authenticate = function (request, next) {

@@ -257,3 +269,3 @@

const reply = request.server._replier.interface(request, strategy.realm, exit);
const reply = request.server._replier.interface(request, strategy.realm, {}, exit);
strategy.methods.payload(request, reply);

@@ -282,3 +294,3 @@ });

const reply = request.server._replier.interface(request, strategy.realm, exit);
const reply = request.server._replier.interface(request, strategy.realm, {}, exit);
strategy.methods.response(request, reply);

@@ -325,7 +337,7 @@ });

const name = config.strategies[this.current];
const after = (err, result) => this.validate(err, result, next);
const after = (err, data) => this.validate(err, data, next);
request._protect.run(after, (exit) => {
const strategy = this.manager._strategies[name];
const reply = request.server._replier.interface(request, strategy.realm, exit);
const reply = request.server._replier.interface(request, strategy.realm, { data: true }, (err) => exit(err, reply._data));
strategy.methods.authenticate(request, reply);

@@ -417,61 +429,71 @@ });

if (!config.access) {
const error = internals.access(request, config, credentials, name);
if (!error) {
return authenticated();
}
const requestEntity = (credentials.user ? 'user' : 'app');
request._log(error.tags, error.data);
return next(error.err);
}
};
const scopeErrors = [];
for (let i = 0; i < config.access.length; ++i) {
const access = config.access[i];
// Check entity
internals.access = function (request, config, credentials, name) {
const entity = access.entity;
if (entity &&
entity !== 'any' &&
entity !== requestEntity) {
if (!config.access) {
return null;
}
continue;
}
const requestEntity = (credentials.user ? 'user' : 'app');
// Check scope
const scopeErrors = [];
for (let i = 0; i < config.access.length; ++i) {
const access = config.access[i];
let scope = access.scope;
if (scope) {
if (!credentials.scope) {
scopeErrors.push(scope);
continue;
}
// Check entity
scope = internals.expandScope(request, scope);
if (!internals.validateScope(credentials, scope, 'required') ||
!internals.validateScope(credentials, scope, 'selection') ||
!internals.validateScope(credentials, scope, 'forbidden')) {
const entity = access.entity;
if (entity &&
entity !== 'any' &&
entity !== requestEntity) {
scopeErrors.push(scope);
continue;
}
continue;
}
// Check scope
let scope = access.scope;
if (scope) {
if (!credentials.scope) {
scopeErrors.push(scope);
continue;
}
return authenticated();
scope = internals.expandScope(request, scope);
if (!internals.validateScope(credentials, scope, 'required') ||
!internals.validateScope(credentials, scope, 'selection') ||
!internals.validateScope(credentials, scope, 'forbidden')) {
scopeErrors.push(scope);
continue;
}
}
// Scope error
return null;
}
if (scopeErrors.length) {
request._log(['auth', 'scope', 'error', name], { got: credentials.scope, need: scopeErrors });
return next(Boom.forbidden('Insufficient scope'));
}
// Scope error
// Entity error
if (scopeErrors.length) {
const data = { got: credentials.scope, need: scopeErrors };
return { err: Boom.forbidden('Insufficient scope', data), tags: ['auth', 'scope', 'error', name], data };
}
if (requestEntity === 'app') {
request._log(['auth', 'entity', 'user', 'error', name]);
return next(Boom.forbidden('Application credentials cannot be used on a user endpoint'));
}
// Entity error
request._log(['auth', 'entity', 'app', 'error', name]);
return next(Boom.forbidden('User credentials cannot be used on an application endpoint'));
if (requestEntity === 'app') {
return { err: Boom.forbidden('Application credentials cannot be used on a user endpoint'), tags: ['auth', 'entity', 'user', 'error', name] };
}
return { err: Boom.forbidden('User credentials cannot be used on an application endpoint'), tags: ['auth', 'entity', 'app', 'error', name] };
};

@@ -478,0 +500,0 @@

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

const Events = require('events');
const Http = require('http');

@@ -14,5 +13,7 @@ const Https = require('https');

const Hoek = require('hoek');
const Podium = require('podium');
const Shot = require('shot');
const Statehood = require('statehood');
const Auth = require('./auth');
const Compression = require('./compression');
const Cors = require('./cors');

@@ -38,3 +39,3 @@ const Ext = require('./ext');

Events.EventEmitter.call(this);
Podium.call(this, internals.Connection._events);

@@ -71,8 +72,8 @@ this.settings = options; // options cloned in server.connection()

this._extensions = {
onRequest: new Ext(this.server),
onPreAuth: new Ext(this.server),
onPostAuth: new Ext(this.server),
onPreHandler: new Ext(this.server),
onPostHandler: new Ext(this.server),
onPreResponse: new Ext(this.server)
onRequest: new Ext('onRequest', this.server),
onPreAuth: new Ext('onPreAuth', this.server),
onPostAuth: new Ext('onPostAuth', this.server),
onPreHandler: new Ext('onPreHandler', this.server),
onPostHandler: new Ext('onPostHandler', this.server),
onPreResponse: new Ext('onPreResponse', this.server)
};

@@ -82,2 +83,3 @@

this._load = server._heavy.policy(this.settings.load);
this._compression = new Compression();
this.states = new Statehood.Definitions(this.settings.state);

@@ -118,5 +120,16 @@ this.auth = new Auth(this);

Hoek.inherits(internals.Connection, Events.EventEmitter);
Hoek.inherits(internals.Connection, Podium);
internals.Connection._events = [
{ name: 'route', spread: true },
{ name: 'request-internal', spread: true, tags: true },
{ name: 'request', spread: true, tags: true },
{ name: 'request-error', spread: true },
'response',
'tail'
];
internals.Connection.prototype._init = function () {

@@ -361,2 +374,14 @@

internals.Connection.prototype.decoder = function (encoding, decoder) {
return this._compression.addDecoder(encoding, decoder);
};
internals.Connection.prototype.encoder = function (encoding, encoder) {
return this._compression.addEncoder(encoding, encoder);
};
internals.Connection.prototype._ext = function (event) {

@@ -399,3 +424,3 @@

const vhost = vhosts[i];
const record = this._router.add({ method: route.method, path: route.path, vhost: vhost, analysis: route._analysis, id: route.settings.id }, route);
const record = this._router.add({ method: route.method, path: route.path, vhost, analysis: route._analysis, id: route.settings.id }, route);
route.fingerprint = record.fingerprint;

@@ -405,3 +430,3 @@ route.params = record.params;

this.emit('route', route.public, this, plugin);
this.emit('route', [route.public, this, plugin]);
};

@@ -408,0 +433,0 @@

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

},
compression: {},
cors: false, // CORS headers

@@ -47,2 +48,3 @@ files: {

},
log: false, // Enables request level log collection
payload: {

@@ -55,3 +57,4 @@ failAction: 'error',

uploads: Os.tmpDir(),
defaultContentType: 'application/json'
defaultContentType: 'application/json',
compression: {}
},

@@ -58,0 +61,0 @@ response: {

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

exports = module.exports = internals.Ext = function (server) {
exports = module.exports = internals.Ext = function (type, server) {

@@ -20,2 +20,3 @@ this._topo = new Topo();

this.type = type;
this.nodes = null;

@@ -22,0 +23,0 @@ };

@@ -71,7 +71,7 @@ 'use strict';

const timer = new Hoek.Bench();
const finalize = (response, data) => {
const finalize = (response) => {
if (response === null) { // reply.continue()
response = Response.wrap(null, request);
return response._prepare(null, finalize);
return response._prepare(finalize);
}

@@ -92,3 +92,3 @@

const reply = request.server._replier.interface(request, request.route.realm, finalize);
const reply = request.server._replier.interface(request, request.route.realm, {}, finalize);
const bind = request.route.settings.bind;

@@ -210,3 +210,3 @@

const result = { name: name };
const result = { name };
const argsNotation = !!methodParts[2];

@@ -259,7 +259,7 @@ const methodArgs = (argsNotation ? (methodParts[3] || '').split(/\s*\,\s*/) : null);

const timer = new Hoek.Bench();
const finalize = (response, data) => {
const finalize = (response) => {
if (response === null) { // reply.continue()
response = Response.wrap(null, request);
return response._prepare(null, finalize);
return response._prepare(finalize);
}

@@ -290,3 +290,3 @@

const reply = request.server._replier.interface(request, request.route.realm, finalize);
const reply = request.server._replier.interface(request, request.route.realm, {}, finalize);
const bind = request.route.settings.bind;

@@ -293,0 +293,0 @@

@@ -99,12 +99,4 @@ 'use strict';

const onFulfilled = (outcome) => {
return methodNext(null, outcome);
};
const onRejected = (err) => {
return methodNext(err);
};
const onFulfilled = (outcome) => methodNext(null, outcome);
const onRejected = (err) => methodNext(err);
result.then(onFulfilled, onRejected);

@@ -146,6 +138,6 @@ };

return Hoek.nextTick(methodNext)(Boom.badImplementation('Invalid method key when invoking: ' + name, { name: name, args: args }));
return Hoek.nextTick(methodNext)(Boom.badImplementation('Invalid method key when invoking: ' + name, { name, args }));
}
cache.get({ id: key, args: args }, methodNext);
cache.get({ id: key, args }, methodNext);
};

@@ -152,0 +144,0 @@

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

const Items = require('items');
const Kilt = require('kilt');
const Podium = require('podium');
const Connection = require('./connection');

@@ -24,3 +24,3 @@ const Ext = require('./ext');

Kilt.call(this, connections, server._events);
Podium.call(this, [connections && connections.length ? connections : Connection._events, server._events]);

@@ -43,7 +43,7 @@ this._parent = parent;

_extensions: {
onPreAuth: new Ext(this.root),
onPostAuth: new Ext(this.root),
onPreHandler: new Ext(this.root),
onPostHandler: new Ext(this.root),
onPreResponse: new Ext(this.root)
onPreAuth: new Ext('onPreAuth', this.root),
onPostAuth: new Ext('onPostAuth', this.root),
onPreHandler: new Ext('onPreHandler', this.root),
onPostHandler: new Ext('onPostHandler', this.root),
onPreResponse: new Ext('onPreResponse', this.root)
},

@@ -91,3 +91,3 @@ modifiers: {

Hoek.inherits(internals.Plugin, Kilt);
Hoek.inherits(internals.Plugin, Podium);

@@ -327,3 +327,3 @@

this.root._registring = false;
return callback(err);
return Hoek.nextTick(callback)(err);
});

@@ -357,2 +357,8 @@ };

internals.Plugin.prototype.decoder = function (encoding, decoder) {
this._apply('decoder', Connection.prototype.decoder, [encoding, decoder]);
};
internals.Plugin.prototype.decorate = function (type, property, method, options) {

@@ -409,2 +415,20 @@

internals.Plugin.prototype.emit = function (criteria, data, callback) {
this.root._events.emit(criteria, data, callback);
};
internals.Plugin.prototype.encoder = function (encoding, encoder) {
this._apply('encoder', Connection.prototype.encoder, [encoding, encoder]);
};
internals.Plugin.prototype.event = function (event) {
this.root._events.registerEvent(event);
};
internals.Plugin.prototype.expose = function (key, value) {

@@ -487,21 +511,12 @@

tags = (Array.isArray(tags) ? tags : [tags]);
const now = (timestamp ? (timestamp instanceof Date ? timestamp.getTime() : timestamp) : Date.now());
tags = [].concat(tags);
timestamp = (timestamp ? (timestamp instanceof Date ? timestamp.getTime() : timestamp) : Date.now());
const internal = !!_internal;
const event = {
timestamp: now,
tags: tags,
data: data,
internal: !!_internal
};
const update = (typeof data !== 'function' ? { timestamp, tags, data, internal } : () => {
const tagsMap = Hoek.mapToObject(event.tags);
this.root._events.emit('log', event, tagsMap);
return { timestamp, tags, data: data(), internal };
});
if (this.root._settings.debug &&
this.root._settings.debug.log &&
Hoek.intersect(tagsMap, this.root._settings.debug.log, true)) {
console.error('Debug:', event.tags.join(', '), (data ? '\n ' + (data.stack || (typeof data === 'object' ? Hoek.stringify(data) : data)) : ''));
}
this.root._events.emit({ name: 'log', tags }, update);
};

@@ -508,0 +523,0 @@

@@ -55,12 +55,10 @@ 'use strict';

if (!this.domain) {
return enter(finish);
if (this.domain) {
this._error = (err) => {
return finish(Boom.badImplementation('Uncaught error', err));
};
}
this._error = (err) => {
return finish(Boom.badImplementation('Uncaught error', err));
};
enter(finish);
return enter(finish);
};

@@ -67,0 +65,0 @@

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

reply(error, result, data); -> error || result (respond) + data
reply(...).takeover(); -> ... (respond) + data
reply(..., data).takeover(); -> ... (respond) + data

@@ -66,6 +66,8 @@ reply.continue(data); -> (continue) + data

internals.Reply.prototype.interface = function (request, realm, next) { // next(err || response, data);
internals.Reply.prototype.interface = function (request, realm, options, next) { // next(err || response, data);
const reply = (err, response, data) => {
Hoek.assert(data === undefined || options.data, 'Reply interface does not allow a third argument');
reply._data = data; // Held for later

@@ -75,2 +77,3 @@ return reply.response(err !== null && err !== undefined ? err : response);

reply._settings = options;
reply._replied = false;

@@ -111,3 +114,17 @@ reply._next = Hoek.once(next);

this._next(null, data);
if (data !== undefined) {
if (this._settings.data) {
this._data = data;
}
else if (this._settings.postHandler) {
const next = this._next;
this._next = (result) => next(null, result); // Shift argument to signal not to stop processing other extensions
return this.response(data);
}
else {
throw new Error('reply.continue() does not allow any arguments');
}
}
this._next(null);
this._next = null;

@@ -142,3 +159,3 @@ };

if (response.isBoom) {
this._next(response, this._data);
this._next(response);
this._next = null;

@@ -157,3 +174,3 @@ return response;

response._prepare(this._data, this._next);
response._prepare(this._next);
this._next = null;

@@ -175,3 +192,3 @@ }

this.send = undefined;
this._prepare(reply._data, reply._next);
this._prepare(reply._next);
this._next = null;

@@ -178,0 +195,0 @@ };

@@ -5,9 +5,7 @@ 'use strict';

const Events = require('events');
const Url = require('url');
const Accept = require('accept');
const Boom = require('boom');
const Hoek = require('hoek');
const Items = require('items');
const Peekaboo = require('peekaboo');
const Podium = require('podium');
const Cors = require('./cors');

@@ -65,3 +63,3 @@ const Protect = require('./protect');

Events.EventEmitter.call(this);
Podium.call(this, ['finish', { name: 'peek', spread: true }, 'disconnect']);

@@ -121,3 +119,3 @@ // Take measurement as soon as possible

host: req.headers.host ? req.headers.host.replace(/\s/g, '') : '',
acceptEncoding: Accept.encoding(this.headers['accept-encoding'], ['identity', 'gzip', 'deflate'])
acceptEncoding: this.connection._compression.accept(this)
};

@@ -140,4 +138,4 @@

this.raw = {
req: req,
res: res
req,
res
};

@@ -199,3 +197,3 @@

Hoek.inherits(internals.Request, Events.EventEmitter);
Hoek.inherits(internals.Request, Podium);

@@ -230,26 +228,20 @@

tags = (Array.isArray(tags) ? tags : [tags]);
const now = (timestamp ? (timestamp instanceof Date ? timestamp.getTime() : timestamp) : Date.now());
tags = [].concat(tags);
timestamp = (timestamp ? (timestamp instanceof Date ? timestamp.getTime() : timestamp) : Date.now());
const internal = !!_internal;
const event = {
request: this.id,
timestamp: now,
tags: tags,
data: data,
internal: !!_internal
};
let update = (typeof data !== 'function' ? [this, { request: this.id, timestamp, tags, data, internal }] : () => {
const tagsMap = Hoek.mapToObject(event.tags);
return [this, { request: this.id, timestamp, tags, data: data(), internal }];
});
// Add to request array
if (this.route.settings.log) {
if (typeof data === 'function') {
update = update();
}
this._logger.push(event);
this.connection.emit(_internal ? 'request-internal' : 'request', this, event, tagsMap);
this._logger.push(update[1]); // Add to request array
}
if (this.server._settings.debug &&
this.server._settings.debug.request &&
Hoek.intersect(tagsMap, this.server._settings.debug.request, true)) {
console.error('Debug:', event.tags.join(', '), (data ? '\n ' + (data.stack || (typeof data === 'object' ? Hoek.stringify(data) : data)) : ''));
}
this.connection.emit({ name: internal ? 'request-internal' : 'request', tags }, update);
};

@@ -266,2 +258,4 @@

Hoek.assert(this.route.settings.log, 'Request logging is disabled');
if (typeof tags === 'boolean') {

@@ -360,3 +354,3 @@ internal = tags;

this.raw.req.socket.setTimeout(this.route.settings.timeout.socket || 0); // Value can be false or positive
this.raw.req.socket.setTimeout(this.route.settings.timeout.socket || 0); // Value can be false or positive
}

@@ -366,7 +360,7 @@

if (serverTimeout) {
serverTimeout = Math.floor(serverTimeout - this._bench.elapsed()); // Calculate the timeout from when the request was constructed
serverTimeout = Math.floor(serverTimeout - this._bench.elapsed()); // Calculate the timeout from when the request was constructed
const timeoutReply = () => {
this._log(['request', 'server', 'timeout', 'error'], { timeout: serverTimeout, elapsed: this._bench.elapsed() });
this._reply(Boom.serverTimeout());
this._reply(Boom.serverUnavailable());
};

@@ -381,2 +375,4 @@

// Execute lifecycle steps
const each = (func, next) => {

@@ -391,3 +387,3 @@

if (typeof func !== 'function') { // Extension point
return this._invoke(func, next);
return this._invoke(func, next); // next() called with response object which ends processing (treated like error)
}

@@ -398,6 +394,3 @@

Items.serial(this._route._cycle, each, (err) => {
return this._reply(err);
});
return Items.serial(this._route._cycle, each, (err) => this._reply(err));
};

@@ -410,9 +403,21 @@

Items.serial(event.nodes, (ext, next) => {
const each = (ext, next) => {
const reply = this.server._replier.interface(this, ext.plugin.realm, next);
const options = { postHandler: (event.type === 'onPostHandler' || event.type === 'onPreResponse') };
const finalize = (result, override) => {
if (override) {
this._setResponse(override);
}
return next(result); // next() called with response object which ends processing (treated like error)
};
const reply = this.server._replier.interface(this, ext.plugin.realm, options, finalize);
const bind = (ext.bind || ext.plugin.realm.settings.bind);
ext.func.call(bind, this, reply);
}, exit);
};
Items.serial(event.nodes, each, exit);
});

@@ -446,3 +451,3 @@ };

if (exit) {
if (exit) { // Can be a valid response or error (if returned from an ext, already handled because this.response is also set)
this._setResponse(Response.wrap(exit, this));

@@ -455,10 +460,7 @@ }

if (err) { // err can be valid response or error
if (err) { // Can be valid response or error
this._setResponse(Response.wrap(err, this));
}
Transmit.send(this, () => {
return this._finalize();
});
return Transmit.send(this, () => this._finalize());
};

@@ -470,3 +472,3 @@

this._invoke(this._route._extensions.onPreResponse, transmit);
return this._invoke(this._route._extensions.onPreResponse, transmit);
};

@@ -483,3 +485,3 @@

this.connection.emit('request-error', this, this.response._error);
this.connection.emit('request-error', [this, this.response._error]);
this._log(this.response._error.isDeveloperError ? ['internal', 'implementation', 'error'] : ['internal', 'error'], this.response._error);

@@ -541,3 +543,3 @@ }

this._tails[tailId] = name;
this._log(['tail', 'add'], { name: name, id: tailId });
this._log(['tail', 'add'], { name, id: tailId });

@@ -547,3 +549,3 @@ const drop = () => {

if (!this._tails[tailId]) {
this._log(['tail', 'remove', 'error'], { name: name, id: tailId }); // Already removed
this._log(['tail', 'remove', 'error'], { name, id: tailId }); // Already removed
return;

@@ -557,7 +559,7 @@ }

this._log(['tail', 'remove', 'last'], { name: name, id: tailId });
this._log(['tail', 'remove', 'last'], { name, id: tailId });
this.connection.emit('tail', this);
}
else {
this._log(['tail', 'remove'], { name: name, id: tailId });
this._log(['tail', 'remove'], { name, id: tailId });
}

@@ -572,7 +574,3 @@ };

const state = {
name: name,
value: value
};
const state = { name, value };
if (options) {

@@ -589,5 +587,3 @@ Hoek.assert(!options.autoValue, 'Cannot set autoValue directly in a response');

const state = {
name: name
};
const state = { name };

@@ -603,3 +599,3 @@ state.options = Hoek.clone(options || {});

return (this.listeners('finish').length || this.listeners('peek').length ? new Peekaboo(this) : null);
return (this.hasListeners('finish') || this.hasListeners('peek') ? new Response.Peek(this) : null);
};

@@ -606,0 +602,0 @@

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

const Stream = require('stream');
const Events = require('events');
const Boom = require('boom');
const Hoek = require('hoek');
const Peekaboo = require('peekaboo');
const Podium = require('podium');

@@ -20,3 +19,3 @@

Events.EventEmitter.call(this);
Podium.call(this, ['finish', { name: 'peek', spread: true }]);

@@ -41,3 +40,4 @@ options = options || {};

passThrough: true,
varyEtag: false
varyEtag: false,
message: null
};

@@ -60,3 +60,3 @@

Hoek.inherits(internals.Response, Events.EventEmitter);
Hoek.inherits(internals.Response, Podium);

@@ -116,2 +116,9 @@

internals.Response.prototype.message = function (httpMessage) {
this.settings.message = httpMessage;
return this;
};
internals.Response.prototype.header = function (key, value, options) {

@@ -136,17 +143,2 @@

// Ensure key and values do not include non-ascii text
if (value !== undefined &&
value !== null) {
const headerValues = [key].concat(value);
for (let i = 0; i < headerValues.length; ++i) {
const header = headerValues[i];
const buffer = Buffer.isBuffer(header) ? header : new Buffer(header.toString());
for (let j = 0; j < buffer.length; ++j) {
Hoek.assert((buffer[j] & 0x7f) === buffer[j], 'Header value cannot contain or convert into non-ascii characters:', key);
}
}
}
if ((!append && override) ||

@@ -229,6 +221,7 @@ !this.headers[key]) {

const etagBase = options.etag.slice(0, -1);
if (etag === etagBase + '-gzip"' ||
etag === etagBase + '-deflate"') {
return true;
const encoders = request.connection._compression.encodings;
for (let j = 0; j < encoders.length; ++j) {
if (etag === etagBase + `-${encoders[j]}"`) {
return true;
}
}

@@ -462,3 +455,3 @@ }

internals.Response.prototype._prepare = function (data, next) {
internals.Response.prototype._prepare = function (next) {

@@ -468,3 +461,3 @@ this._passThrough();

if (this.variety !== 'promise') {
return this._processPrepare(data, next);
return this._processPrepare(next);
}

@@ -475,7 +468,7 @@

if (source instanceof Error) {
return next(Boom.wrap(source), data);
return next(Boom.wrap(source));
}
if (source instanceof internals.Response) {
return source._processPrepare(data, next);
return source._processPrepare(next);
}

@@ -485,6 +478,17 @@

this._passThrough();
this._processPrepare(data, next);
this._processPrepare(next);
};
this.source.then(onDone, onDone);
const onError = (source) => {
if (!(source instanceof Error)) {
const err = new Error('Rejected promise');
err.data = source;
return next(Boom.wrap(err));
}
return next(Boom.wrap(source));
};
this.source.then(onDone, onError);
};

@@ -529,12 +533,9 @@

internals.Response.prototype._processPrepare = function (data, next) {
internals.Response.prototype._processPrepare = function (next) {
if (!this._processors.prepare) {
return next(this, data);
return next(this);
}
this._processors.prepare(this, (prepared) => {
return next(prepared, data);
});
return this._processors.prepare(this, next);
};

@@ -611,3 +612,3 @@

return (this.listeners('finish').length || this.listeners('peek').length ? new Peekaboo(this) : null);
return (this.hasListeners('finish') || this.hasListeners('peek') ? new internals.Peek(this) : null);
};

@@ -705,1 +706,22 @@

};
internals.Response.Peek = internals.Peek = function (podium) {
Stream.Transform.call(this);
this._podium = podium;
this.once('finish', () => {
podium.emit('finish');
});
};
Hoek.inherits(internals.Peek, Stream.Transform);
internals.Peek.prototype._transform = function (chunk, encoding, callback) {
this._podium.emit('peek', [chunk, encoding]);
this.push(chunk, encoding);
callback();
};

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

base = Hoek.applyToDefaultsWithShallow(base, realm.settings, ['bind']);
this.settings = Hoek.applyToDefaultsWithShallow(base, config || {}, ['bind']);
this.settings = Hoek.applyToDefaultsWithShallow(base, config || {}, ['bind', 'validate.headers', 'validate.payload', 'validate.params', 'validate.query']);
this.settings.handler = handler;

@@ -95,3 +95,6 @@ this.settings = Schema.apply('routeConfig', this.settings, routeDisplay);

settings: this.settings,
fingerprint: this.fingerprint
fingerprint: this.fingerprint,
auth: {
access: (request) => Auth.access(request, this.public)
}
};

@@ -149,2 +152,4 @@

}
this.settings.payload.decoders = this.connection._compression._decoders; // Reference the shared object to keep up to date
}

@@ -245,3 +250,3 @@

const ext = new Ext(this.server);
const ext = new Ext(type, this.server);

@@ -248,0 +253,0 @@ const events = this.settings.ext[type];

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

.allow(false),
compression: Joi.object().pattern(/.+/, Joi.object()),
cors: Joi.object({

@@ -100,2 +101,3 @@ origin: Joi.array().min(1),

jsonp: Joi.string(),
log: Joi.boolean(),
payload: Joi.object({

@@ -113,3 +115,4 @@ output: Joi.string().valid('data', 'stream', 'file'),

timeout: Joi.number().integer().positive().allow(false),
defaultContentType: Joi.string()
defaultContentType: Joi.string(),
compression: Joi.object().pattern(/.+/, Joi.object())
}),

@@ -119,3 +122,6 @@ plugins: Joi.object(),

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

@@ -196,4 +202,4 @@ options: Joi.object(),

debug: Joi.object({
request: Joi.array().allow(false),
log: Joi.array().allow(false)
request: Joi.array().items(Joi.string()).single().allow(false),
log: Joi.array().items(Joi.string()).single().allow(false)
}).allow(false),

@@ -200,0 +206,0 @@ load: Joi.object(),

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

const Events = require('events');
const Catbox = require('catbox');

@@ -18,2 +17,3 @@ const CatboxMemory = require('catbox-memory');

const Plugin = require('./plugin');
const Podium = require('podium');
const Promises = require('./promises');

@@ -41,9 +41,9 @@ const Reply = require('./reply');

this._caches = {}; // Cache clients
this._handlers = {}; // Registered handlers
this._methods = new Methods(this); // Server methods
this._caches = {}; // Cache clients
this._handlers = {}; // Registered handlers
this._methods = new Methods(this); // Server methods
this._events = new Events.EventEmitter(); // Server-only events
this._dependencies = []; // Plugin dependencies
this._registrations = {}; // Tracks plugins registered before connection added
this._events = new Podium([{ name: 'log', tags: true }, 'start', 'stop']); // Server-only events
this._dependencies = []; // Plugin dependencies
this._registrations = {}; // Tracks plugins registered before connection added
this._heavy = new Heavy(this._settings.load);

@@ -54,13 +54,13 @@ this._mime = new Mimos(this._settings.mime);

this._decorations = {};
this._plugins = {}; // Exposed plugin properties by name
this._plugins = {}; // Exposed plugin properties by name
this._app = {};
this._registring = false; // true while register() is waiting for plugin callbacks
this._state = 'stopped'; // 'stopped', 'initializing', 'initialized', 'starting', 'started', 'stopping', 'invalid'
this._registring = false; // true while register() is waiting for plugin callbacks
this._state = 'stopped'; // 'stopped', 'initializing', 'initialized', 'starting', 'started', 'stopping', 'invalid'
this._extensionsSeq = 0; // Used to keep absolute order of extensions based on the order added across locations
this._extensionsSeq = 0; // Used to keep absolute order of extensions based on the order added across locations
this._extensions = {
onPreStart: new Ext(this),
onPostStart: new Ext(this),
onPreStop: new Ext(this),
onPostStop: new Ext(this)
onPreStart: new Ext('onPreStart', this),
onPostStart: new Ext('onPostStart', this),
onPreStop: new Ext('onPreStop', this),
onPostStop: new Ext('onPostStop', this)
};

@@ -73,6 +73,25 @@

if (!this._caches._default) {
this._createCache([{ engine: CatboxMemory }]); // Defaults to memory-based
this._createCache([{ engine: CatboxMemory }]); // Defaults to memory-based
}
Plugin.call(this, this, [], '', null);
// Subscribe to server log events
if (this._settings.debug) {
const debug = (request, event) => {
const data = event.data;
console.error('Debug:', event.tags.join(', '), (data ? '\n ' + (data.stack || (typeof data === 'object' ? Hoek.stringify(data) : data)) : ''));
};
if (this._settings.debug.log) {
this._events.on({ name: 'log', filter: this._settings.debug.log }, (event) => debug(null, event));
}
if (this._settings.debug.request) {
this.on({ name: 'request', filter: this._settings.debug.request }, debug);
this.on({ name: 'request-internal', filter: this._settings.debug.request }, debug);
}
}
};

@@ -114,3 +133,3 @@

this._caches[name] = {
client: client,
client,
segments: {},

@@ -150,3 +169,3 @@ shared: config.shared || false

root.connections.push(connection);
root.addEmitter(connection);
root.registerPodium(connection);
root._single();

@@ -177,8 +196,4 @@

if (this._state === 'started') {
Items.serial(this.connections, (connectionItem, next) => {
connectionItem._start(next);
}, callback);
return;
const each = (connectionItem, next) => connectionItem._start(next);
return Items.parallel(this.connections, each, callback);
}

@@ -292,9 +307,5 @@

const each = (connectionItem, next) => {
const each = (connectionItem, next) => connectionItem._start(next);
Items.parallel(this.connections, each, (err) => {
connectionItem._start(next);
};
Items.serial(this.connections, each, (err) => {
if (err) {

@@ -305,12 +316,14 @@ this._state = 'invalid';

this._events.emit('start');
this._invoke('onPostStart', (err) => {
this._events.emit('start', null, () => {
if (err) {
this._state = 'invalid';
return callback(err);
}
this._invoke('onPostStart', (err) => {
this._state = 'started';
return callback();
if (err) {
this._state = 'invalid';
return callback(err);
}
this._state = 'started';
return callback();
});
});

@@ -347,9 +360,5 @@ });

const each = (connection, next) => {
const each = (connection, next) => connection._stop(options, next);
Items.parallel(this.connections, each, (err) => {
connection._stop(options, next);
};
Items.serial(this.connections, each, (err) => {
if (err) {

@@ -365,13 +374,15 @@ this._state = 'invalid';

this._events.emit('stop');
this._heavy.stop();
this._invoke('onPostStop', (err) => {
this._events.emit('stop', null, () => {
if (err) {
this._state = 'invalid';
return callback(err);
}
this._heavy.stop();
this._invoke('onPostStop', (err) => {
this._state = 'stopped';
return callback();
if (err) {
this._state = 'invalid';
return callback(err);
}
this._state = 'stopped';
return callback();
});
});

@@ -378,0 +389,0 @@ });

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

const Stream = require('stream');
const Zlib = require('zlib');
const Ammo = require('ammo');

@@ -70,16 +69,11 @@ const Boom = require('boom');

if (!response._isPayloadSupported()) {
if (!response._isPayloadSupported() &&
request.method !== 'head') {
// Close unused file streams
response._close();
// Set empty stream
response._close(); // Close unused file streams
response._payload = new internals.Empty();
if (request.method !== 'head') {
delete response.headers['content-length'];
}
return Auth.response(request, next); // Must be last in case requires access to headers
delete response.headers['content-length'];
return Auth.response(request, next); // Must be last in case requires access to headers
}

@@ -107,2 +101,7 @@

if (!response._isPayloadSupported()) {
response._close(); // Close unused file streams
response._payload = new internals.Empty(); // Set empty stream
}
internals.content(response, true);

@@ -164,5 +163,3 @@ return Auth.response(request, next); // Must be last in case requires access to headers

const mime = request.server.mime.type(response.headers['content-type'] || 'application/octet-stream');
let encoding = (request.connection.settings.compression && mime.compressible && !response.headers['content-encoding'] ? request.info.acceptEncoding : null);
encoding = (encoding === 'identity' ? null : encoding);
const encoding = request.connection._compression.encoding(response);

@@ -211,9 +208,6 @@ // Range

if (request.headers['accept-encoding']) {
response.vary('accept-encoding');
}
let compressor = null;
if (encoding &&
length !== 0 &&
response.statusCode !== 206 &&
response._isPayloadSupported()) {

@@ -224,3 +218,3 @@

compressor = (encoding === 'gzip' ? Zlib.createGzip() : Zlib.createDeflate());
compressor = request.connection._compression.encoder(request, encoding);
}

@@ -315,5 +309,3 @@

if (isInjection) {
request.raw.res._hapi = {
request: request
};
request.raw.res._hapi = { request };

@@ -358,2 +350,6 @@ if (response.variety === 'plain') {

if (response.settings.message) {
res.statusMessage = response.settings.message;
}
return null;

@@ -433,3 +429,3 @@ };

const type = response.headers['content-type'];
let type = response.headers['content-type'];
if (!type) {

@@ -441,11 +437,12 @@ if (response._contentType) {

}
else if ((!response._contentType || !postMarshal) &&
else {
type = type.trim();
if ((!response._contentType || !postMarshal) &&
response.settings.charset &&
type.match(/^(?:text\/)|(?:application\/(?:json)|(?:javascript))/)) {
const hasParams = (type.indexOf(';') !== -1);
if (!hasParams ||
!type.match(/[; ]charset=/)) {
response.type(type + (hasParams ? ', ' : '; ') + 'charset=' + (response.settings.charset));
if (!type.match(/; *charset=/)) {
const semi = (type[type.length - 1] === ';');
response.type(type + (semi ? ' ' : '; ') + 'charset=' + (response.settings.charset));
}
}

@@ -480,3 +477,3 @@ }

if (typeof autoValue !== 'function') {
states.push({ name: name, value: autoValue });
states.push({ name, value: autoValue });
return nextKey();

@@ -491,3 +488,3 @@ }

states.push({ name: name, value: value });
states.push({ name, value });
return nextKey();

@@ -494,0 +491,0 @@ });

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

const error = (err.isBoom ? err : Boom.badRequest(err.message, err));
error.output.payload.validation = { source: source, keys: [] };
error.output.payload.validation = { source, keys: [] };
if (err.details) {

@@ -118,3 +118,3 @@ for (let i = 0; i < err.details.length; ++i) {

const reply = request.server._replier.interface(request, request.route.realm, exit);
const reply = request.server._replier.interface(request, request.route.realm, {}, exit);
request.route.settings.validate.failAction(request, reply, source, error);

@@ -144,3 +144,4 @@ });

return schema(request[source], localOptions, exit);
const bind = request.route.settings.bind;
return schema.call(bind, request[source], localOptions, exit);
});

@@ -204,3 +205,15 @@ };

return next(Boom.badImplementation(err.message));
// Return error
if (typeof request.route.settings.response.failAction !== 'function') {
return next(Boom.badImplementation(err.message));
}
// Custom handler
request._protect.run(next, (exit) => {
const reply = request.server._replier.interface(request, request.route.realm, {}, exit);
request.route.settings.response.failAction(request, reply, err);
});
};

@@ -207,0 +220,0 @@

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

"homepage": "http://hapijs.com",
"version": "14.2.0",
"version": "15.0.1",
"repository": {

@@ -19,3 +19,3 @@ "type": "git",

"engines": {
"node": ">=4.0.0"
"node": ">=4.5.0"
},

@@ -25,3 +25,3 @@ "dependencies": {

"ammo": "2.x.x",
"boom": "3.x.x",
"boom": "4.x.x",
"call": "3.x.x",

@@ -36,8 +36,7 @@ "catbox": "7.x.x",

"joi": "9.x.x",
"kilt": "2.x.x",
"mimos": "3.x.x",
"peekaboo": "2.x.x",
"podium": "^1.2.x",
"shot": "3.x.x",
"statehood": "4.x.x",
"subtext": "4.x.x",
"statehood": "5.x.x",
"subtext": "^4.2.x",
"topo": "2.x.x"

@@ -49,3 +48,3 @@ },

"inert": "4.x.x",
"lab": "10.x.x",
"lab": "11.x.x",
"vision": "4.x.x",

@@ -55,7 +54,7 @@ "wreck": "8.x.x"

"scripts": {
"test": "lab -a code -t 100 -L",
"test-tap": "lab -a code -r tap -o tests.tap",
"test-cov-html": "lab -a code -r html -o coverage.html"
"test": "lab -a code -t 100 -L -m 3000",
"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"
},
"license": "BSD-3-Clause"
}

@@ -5,7 +5,5 @@ <img src="https://raw.github.com/hapijs/hapi/master/images/hapi.png" />

<a href="https://sideway.com"><img src="https://www.sideway.com/sideway.png" align="right" /></a>
Lead Maintainer: [Eran Hammer](https://github.com/hueniverse)
**hapi** is sponsored by [Sideway](https://sideway.com).
**hapi** is sponsored by Benjamin Flesch and (StriveWire)[https://strivewire.com/]. StriveWire is currently hiring full stack developers in Hamburg, Germany.

@@ -16,3 +14,3 @@ **hapi** is a simple to use configuration-centric framework with built-in support for input validation, caching,

Development version: **14.2.x** ([release notes](https://github.com/hapijs/hapi/issues?labels=release+notes&page=1&state=closed))
Development version: **15.0.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)

@@ -19,0 +17,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