aboutsummaryrefslogtreecommitdiff
path: root/node_modules/koa/lib/application.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/koa/lib/application.js')
-rw-r--r--node_modules/koa/lib/application.js244
1 files changed, 244 insertions, 0 deletions
diff --git a/node_modules/koa/lib/application.js b/node_modules/koa/lib/application.js
new file mode 100644
index 00000000..84107cb6
--- /dev/null
+++ b/node_modules/koa/lib/application.js
@@ -0,0 +1,244 @@
+
+'use strict';
+
+/**
+ * Module dependencies.
+ */
+
+const isGeneratorFunction = require('is-generator-function');
+const debug = require('debug')('koa:application');
+const onFinished = require('on-finished');
+const response = require('./response');
+const compose = require('koa-compose');
+const isJSON = require('koa-is-json');
+const context = require('./context');
+const request = require('./request');
+const statuses = require('statuses');
+const Emitter = require('events');
+const util = require('util');
+const Stream = require('stream');
+const http = require('http');
+const only = require('only');
+const convert = require('koa-convert');
+const deprecate = require('depd')('koa');
+
+/**
+ * Expose `Application` class.
+ * Inherits from `Emitter.prototype`.
+ */
+
+module.exports = class Application extends Emitter {
+ /**
+ * Initialize a new `Application`.
+ *
+ * @api public
+ */
+
+ constructor() {
+ super();
+
+ this.proxy = false;
+ this.middleware = [];
+ this.subdomainOffset = 2;
+ this.env = process.env.NODE_ENV || 'development';
+ this.context = Object.create(context);
+ this.request = Object.create(request);
+ this.response = Object.create(response);
+ if (util.inspect.custom) {
+ this[util.inspect.custom] = this.inspect;
+ }
+ }
+
+ /**
+ * Shorthand for:
+ *
+ * http.createServer(app.callback()).listen(...)
+ *
+ * @param {Mixed} ...
+ * @return {Server}
+ * @api public
+ */
+
+ listen(...args) {
+ debug('listen');
+ const server = http.createServer(this.callback());
+ return server.listen(...args);
+ }
+
+ /**
+ * Return JSON representation.
+ * We only bother showing settings.
+ *
+ * @return {Object}
+ * @api public
+ */
+
+ toJSON() {
+ return only(this, [
+ 'subdomainOffset',
+ 'proxy',
+ 'env'
+ ]);
+ }
+
+ /**
+ * Inspect implementation.
+ *
+ * @return {Object}
+ * @api public
+ */
+
+ inspect() {
+ return this.toJSON();
+ }
+
+ /**
+ * Use the given middleware `fn`.
+ *
+ * Old-style middleware will be converted.
+ *
+ * @param {Function} fn
+ * @return {Application} self
+ * @api public
+ */
+
+ use(fn) {
+ if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
+ if (isGeneratorFunction(fn)) {
+ deprecate('Support for generators will be removed in v3. ' +
+ 'See the documentation for examples of how to convert old middleware ' +
+ 'https://github.com/koajs/koa/blob/master/docs/migration.md');
+ fn = convert(fn);
+ }
+ debug('use %s', fn._name || fn.name || '-');
+ this.middleware.push(fn);
+ return this;
+ }
+
+ /**
+ * Return a request handler callback
+ * for node's native http server.
+ *
+ * @return {Function}
+ * @api public
+ */
+
+ callback() {
+ const fn = compose(this.middleware);
+
+ if (!this.listenerCount('error')) this.on('error', this.onerror);
+
+ const handleRequest = (req, res) => {
+ const ctx = this.createContext(req, res);
+ return this.handleRequest(ctx, fn);
+ };
+
+ return handleRequest;
+ }
+
+ /**
+ * Handle request in callback.
+ *
+ * @api private
+ */
+
+ handleRequest(ctx, fnMiddleware) {
+ const res = ctx.res;
+ res.statusCode = 404;
+ const onerror = err => ctx.onerror(err);
+ const handleResponse = () => respond(ctx);
+ onFinished(res, onerror);
+ return fnMiddleware(ctx).then(handleResponse).catch(onerror);
+ }
+
+ /**
+ * Initialize a new context.
+ *
+ * @api private
+ */
+
+ createContext(req, res) {
+ const context = Object.create(this.context);
+ const request = context.request = Object.create(this.request);
+ const response = context.response = Object.create(this.response);
+ context.app = request.app = response.app = this;
+ context.req = request.req = response.req = req;
+ context.res = request.res = response.res = res;
+ request.ctx = response.ctx = context;
+ request.response = response;
+ response.request = request;
+ context.originalUrl = request.originalUrl = req.url;
+ context.state = {};
+ return context;
+ }
+
+ /**
+ * Default error handler.
+ *
+ * @param {Error} err
+ * @api private
+ */
+
+ onerror(err) {
+ if (!(err instanceof Error)) throw new TypeError(util.format('non-error thrown: %j', err));
+
+ if (404 == err.status || err.expose) return;
+ if (this.silent) return;
+
+ const msg = err.stack || err.toString();
+ console.error();
+ console.error(msg.replace(/^/gm, ' '));
+ console.error();
+ }
+};
+
+/**
+ * Response helper.
+ */
+
+function respond(ctx) {
+ // allow bypassing koa
+ if (false === ctx.respond) return;
+
+ const res = ctx.res;
+ if (!ctx.writable) return;
+
+ let body = ctx.body;
+ const code = ctx.status;
+
+ // ignore body
+ if (statuses.empty[code]) {
+ // strip headers
+ ctx.body = null;
+ return res.end();
+ }
+
+ if ('HEAD' == ctx.method) {
+ if (!res.headersSent && isJSON(body)) {
+ ctx.length = Buffer.byteLength(JSON.stringify(body));
+ }
+ return res.end();
+ }
+
+ // status body
+ if (null == body) {
+ body = ctx.message || String(code);
+ if (!res.headersSent) {
+ ctx.type = 'text';
+ ctx.length = Buffer.byteLength(body);
+ }
+ return res.end(body);
+ }
+
+ // responses
+ if (Buffer.isBuffer(body)) return res.end(body);
+ if ('string' == typeof body) return res.end(body);
+ if (body instanceof Stream) return body.pipe(res);
+
+ // body: json
+ body = JSON.stringify(body);
+ if (!res.headersSent) {
+ ctx.length = Buffer.byteLength(body);
+ }
+ res.end(body);
+}