text: 'use strict';
  /**
   * Module dependencies.
   */
  const util = require("util");
  const createError = require("http-errors");
  const httpAssert = require("http-assert");
  const delegate = require("delegates");
  const statuses = require("statuses");
  const Cookies = require("cookies");
  const COOKIES = Symbol('context#cookies');
  /**
   * Context prototype.
   */
  const proto = {
      /**
       * util.inspect() implementation, which
       * just returns the JSON output.
       *
       * @return {Object}
       * @api public
       */
      inspect() {
          if (this === proto)
              return this;
          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 `status` (default 500) and
       * `msg`. Note that these are user-level
       * errors, and the message may be exposed to the client.
       *
       *    this.throw(403)
       *    this.throw(400, 'name required')
       *    this.throw('something exploded')
       *    this.throw(new Error('invalid'))
       *    this.throw(400, new Error('invalid'))
       *
       * See: https://github.com/jshttp/http-errors
       *
       * Note: `status` should only be passed as the first parameter.
       *
       * @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(util.format('non-error thrown: %j', 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
          /* istanbul ignore else */
          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);
          res.end(msg);
      },
      get cookies() {
          if (!this[COOKIES]) {
              this[COOKIES] = new Cookies(this.req, this.res, {
                  keys: this.app.keys,
                  secure: this.request.secure
              });
          }
          return this[COOKIES];
      },
      set cookies(_cookies) {
          this[COOKIES] = _cookies;
      }
  };
  /**
   * Custom inspection implementation for newer Node.js versions.
   *
   * @return {Object}
   * @api public
   */
  /* istanbul ignore else */
  if (util.inspect.custom) {
      module.exports[util.inspect.custom] = module.exports.inspect;
  }
  /**
   * 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')
      .access('accept')
      .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');
  module.exports = proto;
  