123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- 'use strict';
- /**
- * Module dependencies.
- */
- const createError = require('http-errors');
- const httpAssert = require('http-assert');
- const delegate = require('delegates');
- const statuses = require('statuses');
- /**
- * Context prototype.
- */
- const proto = module.exports = {
- /**
- * util.inspect() implementation, which
- * just returns the JSON output.
- *
- * @return {Object}
- * @api public
- */
- inspect() {
- return this.toJSON();
- },
- /**
- * Return JSON representation.
- *
- * Here we explicitly invoke .toJSON() on each
- * object, as iteration will otherwise fail due
- * to the getters and cause utilities such as
- * clone() to fail.
- *
- * @return {Object}
- * @api public
- */
- toJSON() {
- return {
- request: this.request.toJSON(),
- response: this.response.toJSON(),
- app: this.app.toJSON(),
- originalUrl: this.originalUrl,
- req: '<original node req>',
- res: '<original node res>',
- socket: '<original node socket>'
- };
- },
- /**
- * Similar to .throw(), adds assertion.
- *
- * this.assert(this.user, 401, 'Please login!');
- *
- * See: https://github.com/jshttp/http-assert
- *
- * @param {Mixed} test
- * @param {Number} status
- * @param {String} message
- * @api public
- */
- assert: httpAssert,
- /**
- * Throw an error with `msg` and optional `status`
- * defaulting to 500. Note that these are user-level
- * errors, and the message may be exposed to the client.
- *
- * this.throw(403)
- * this.throw('name required', 400)
- * this.throw(400, 'name required')
- * this.throw('something exploded')
- * this.throw(new Error('invalid'), 400);
- * this.throw(400, new Error('invalid'));
- *
- * See: https://github.com/jshttp/http-errors
- *
- * @param {String|Number|Error} err, msg or status
- * @param {String|Number|Error} [err, msg or status]
- * @param {Object} [props]
- * @api public
- */
- throw(...args) {
- throw createError(...args);
- },
- /**
- * Default error handling.
- *
- * @param {Error} err
- * @api private
- */
- onerror(err) {
- // don't do anything if there is no error.
- // this allows you to pass `this.onerror`
- // to node-style callbacks.
- if (null == err) return;
- if (!(err instanceof Error)) err = new Error(`non-error thrown: ${err}`);
- let headerSent = false;
- if (this.headerSent || !this.writable) {
- headerSent = err.headerSent = true;
- }
- // delegate
- this.app.emit('error', err, this);
- // nothing we can do here other
- // than delegate to the app-level
- // handler and log.
- if (headerSent) {
- return;
- }
- const { res } = this;
- // first unset all headers
- if (typeof res.getHeaderNames === 'function') {
- res.getHeaderNames().forEach(name => res.removeHeader(name));
- } else {
- res._headers = {}; // Node < 7.7
- }
- // then set those specified
- this.set(err.headers);
- // force text/plain
- this.type = 'text';
- // ENOENT support
- if ('ENOENT' == err.code) err.status = 404;
- // default to 500
- if ('number' != typeof err.status || !statuses[err.status]) err.status = 500;
- // respond
- const code = statuses[err.status];
- const msg = err.expose ? err.message : code;
- this.status = err.status;
- this.length = Buffer.byteLength(msg);
- this.res.end(msg);
- }
- };
- /**
- * Response delegation.
- */
- delegate(proto, 'response')
- .method('attachment')
- .method('redirect')
- .method('remove')
- .method('vary')
- .method('set')
- .method('append')
- .method('flushHeaders')
- .access('status')
- .access('message')
- .access('body')
- .access('length')
- .access('type')
- .access('lastModified')
- .access('etag')
- .getter('headerSent')
- .getter('writable');
- /**
- * Request delegation.
- */
- delegate(proto, 'request')
- .method('acceptsLanguages')
- .method('acceptsEncodings')
- .method('acceptsCharsets')
- .method('accepts')
- .method('get')
- .method('is')
- .access('querystring')
- .access('idempotent')
- .access('socket')
- .access('search')
- .access('method')
- .access('query')
- .access('path')
- .access('url')
- .getter('origin')
- .getter('href')
- .getter('subdomains')
- .getter('protocol')
- .getter('host')
- .getter('hostname')
- .getter('URL')
- .getter('header')
- .getter('headers')
- .getter('secure')
- .getter('stale')
- .getter('fresh')
- .getter('ips')
- .getter('ip');
|