@eggjs/koa 2.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2019 Koa contributors
4
+ Copyright (c) 2023 EggJS contributors
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ 'Software'), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/Readme.md ADDED
@@ -0,0 +1,279 @@
1
+ # @eggjs/koa
2
+
3
+ @eggjs/koa is forked from [Koa v2.x](https://github.com/koajs/koa/tree/v2.x) for LTS and drop Node.js < 16.13.0 support.
4
+
5
+ <img src="/docs/logo.png" alt="Koa middleware framework for nodejs"/>
6
+
7
+ [![NPM version](https://img.shields.io/npm/v/@eggjs/koa.svg?style=flat-square)](https://npmjs.org/package/@eggjs/koa)
8
+ [![NPM quality](http://npm.packagequality.com/shield/@eggjs/koa.svg?style=flat-square)](http://packagequality.com/#?package=@eggjs/koa)
9
+ [![NPM download](https://img.shields.io/npm/dm/@eggjs/koa.svg?style=flat-square)](https://npmjs.org/package/@eggjs/koa)
10
+ [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Feggjs%2Fkoa.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Feggjs%2Fkoa?ref=badge_shield)
11
+ [![Continuous Integration](https://github.com/eggjs/koa/workflows/Continuous%20integration/badge.svg)](https://github.com/eggjs/koa/actions?query=branch%3Amaster)
12
+ [![Test coverage](https://img.shields.io/codecov/c/github/eggjs/koa.svg?style=flat-square)](https://codecov.io/gh/eggjs/koa)
13
+ [![Known Vulnerabilities](https://snyk.io/test/npm/@eggjs/koa/badge.svg?style=flat-square)](https://snyk.io/test/npm/@eggjs/koa)
14
+
15
+ Expressive HTTP middleware framework for node.js to make web applications and APIs more enjoyable to write. Koa's middleware stack flows in a stack-like manner, allowing you to perform actions downstream then filter and manipulate the response upstream.
16
+
17
+ Only methods that are common to nearly all HTTP servers are integrated directly into Koa's small ~570 SLOC codebase. This
18
+ includes things like content negotiation, normalization of node inconsistencies, redirection, and a few others.
19
+
20
+ Koa is not bundled with any middleware.
21
+
22
+ ## Installation
23
+
24
+ @eggjs/koa requires __node v16.3.0__ or higher for Node.js LTS support.
25
+
26
+ ```bash
27
+ npm install @eggjs/koa
28
+ ```
29
+
30
+ ## Hello Koa
31
+
32
+ ```js
33
+ const Koa = require('@eggjs/koa');
34
+ const app = new Koa();
35
+
36
+ // response
37
+ app.use(ctx => {
38
+ ctx.body = 'Hello Koa';
39
+ });
40
+
41
+ app.listen(3000);
42
+ ```
43
+
44
+ ## Getting started
45
+
46
+ - [Kick-Off-Koa](https://github.com/koajs/kick-off-koa) - An intro to Koa via a set of self-guided workshops.
47
+ - [Workshop](https://github.com/koajs/workshop) - A workshop to learn the basics of Koa, Express' spiritual successor.
48
+ - [Introduction Screencast](https://knowthen.com/episode-3-koajs-quickstart-guide/) - An introduction to installing and getting started with Koa
49
+
50
+ ## Middleware
51
+
52
+ Koa is a middleware framework that can take two different kinds of functions as middleware:
53
+
54
+ - async function
55
+ - common function
56
+
57
+ Here is an example of logger middleware with each of the different functions:
58
+
59
+ ### ___async___ functions (node v7.6+)
60
+
61
+ ```js
62
+ app.use(async (ctx, next) => {
63
+ const start = Date.now();
64
+ await next();
65
+ const ms = Date.now() - start;
66
+ console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
67
+ });
68
+ ```
69
+
70
+ ### Common function
71
+
72
+ ```js
73
+ // Middleware normally takes two parameters (ctx, next), ctx is the context for one request,
74
+ // next is a function that is invoked to execute the downstream middleware. It returns a Promise with a then function for running code after completion.
75
+
76
+ app.use((ctx, next) => {
77
+ const start = Date.now();
78
+ return next().then(() => {
79
+ const ms = Date.now() - start;
80
+ console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
81
+ });
82
+ });
83
+ ```
84
+
85
+ ### Koa v1.x Middleware Signature
86
+
87
+ The middleware signature changed between v1.x and v2.x. The older signature is deprecated.
88
+
89
+ __Old signature middleware support will be removed in v3__
90
+
91
+ Please see the [Migration Guide](docs/migration.md) for more information on upgrading from v1.x and
92
+ using v1.x middleware with v2.x.
93
+
94
+ ## Context, Request and Response
95
+
96
+ Each middleware receives a Koa `Context` object that encapsulates an incoming
97
+ http message and the corresponding response to that message. `ctx` is often used
98
+ as the parameter name for the context object.
99
+
100
+ ```js
101
+ app.use(async (ctx, next) => {
102
+ await next();
103
+ });
104
+ ```
105
+
106
+ Koa provides a `Request` object as the `request` property of the `Context`.
107
+ Koa's `Request` object provides helpful methods for working with
108
+ http requests which delegate to an [IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
109
+ from the node `http` module.
110
+
111
+ Here is an example of checking that a requesting client supports xml.
112
+
113
+ ```js
114
+ app.use(async (ctx, next) => {
115
+ ctx.assert(ctx.request.accepts('xml'), 406);
116
+ // equivalent to:
117
+ // if (!ctx.request.accepts('xml')) ctx.throw(406);
118
+ await next();
119
+ });
120
+ ```
121
+
122
+ Koa provides a `Response` object as the `response` property of the `Context`.
123
+ Koa's `Response` object provides helpful methods for working with
124
+ http responses which delegate to a [ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse)
125
+ .
126
+
127
+ Koa's pattern of delegating to Node's request and response objects rather than extending them
128
+ provides a cleaner interface and reduces conflicts between different middleware and with Node
129
+ itself as well as providing better support for stream handling. The `IncomingMessage` can still be
130
+ directly accessed as the `req` property on the `Context` and `ServerResponse` can be directly
131
+ accessed as the `res` property on the `Context`.
132
+
133
+ Here is an example using Koa's `Response` object to stream a file as the response body.
134
+
135
+ ```js
136
+ app.use(async (ctx, next) => {
137
+ await next();
138
+ ctx.response.type = 'xml';
139
+ ctx.response.body = fs.createReadStream('really_large.xml');
140
+ });
141
+ ```
142
+
143
+ The `Context` object also provides shortcuts for methods on its `request` and `response`. In the prior
144
+ examples, `ctx.type` can be used instead of `ctx.response.type` and `ctx.accepts` can be used
145
+ instead of `ctx.request.accepts`.
146
+
147
+ For more information on `Request`, `Response` and `Context`, see the [Request API Reference](docs/api/request.md),
148
+ [Response API Reference](docs/api/response.md) and [Context API Reference](docs/api/context.md).
149
+
150
+ ## Koa Application
151
+
152
+ The object created when executing `new Koa()` is known as the Koa application object.
153
+
154
+ The application object is Koa's interface with node's http server and handles the registration
155
+ of middleware, dispatching to the middleware from http, default error handling, as well as
156
+ configuration of the context, request and response objects.
157
+
158
+ Learn more about the application object in the [Application API Reference](docs/api/index.md).
159
+
160
+ ## Documentation
161
+
162
+ - [Usage Guide](docs/guide.md)
163
+ - [Error Handling](docs/error-handling.md)
164
+ - [Koa for Express Users](docs/koa-vs-express.md)
165
+ - [FAQ](docs/faq.md)
166
+ - [API documentation](docs/api/index.md)
167
+
168
+ ## Troubleshooting
169
+
170
+ Check the [Troubleshooting Guide](docs/troubleshooting.md) or [Debugging Koa](docs/guide.md#debugging-koa) in
171
+ the general Koa guide.
172
+
173
+ ## Running tests
174
+
175
+ ```bash
176
+ npm test
177
+ ```
178
+
179
+ ## Reporting vulnerabilities
180
+
181
+ To report a security vulnerability, please do not open an issue, as this notifies attackers of the vulnerability. Instead, please email [fengmk2](mailto:fengmk2+eggjs@gmail.com) to disclose.
182
+
183
+ ## Authors
184
+
185
+ See [AUTHORS](AUTHORS).
186
+
187
+ ## Community
188
+
189
+ - [Badgeboard](https://koajs.github.io/badgeboard) and list of official modules
190
+ - [Examples](https://github.com/koajs/examples)
191
+ - [Middleware](https://github.com/koajs/koa/wiki) list
192
+ - [Wiki](https://github.com/koajs/koa/wiki)
193
+ - [Reddit Community](https://www.reddit.com/r/koajs)
194
+ - [Mailing list](https://groups.google.com/forum/#!forum/koajs)
195
+ - [中文文档 v1.x](https://github.com/guo-yu/koa-guide)
196
+ - [中文文档 v2.x](https://github.com/demopark/koa-docs-Zh-CN)
197
+ - __[#koajs]__ on freenode
198
+
199
+ ## Job Board
200
+
201
+ Looking for a career upgrade?
202
+
203
+ <a href="https://astro.netlify.com/automattic"><img src="https://astro.netlify.com/static/automattic.png"></a>
204
+ <a href="https://astro.netlify.com/segment"><img src="https://astro.netlify.com/static/segment.png"></a>
205
+ <a href="https://astro.netlify.com/auth0"><img src="https://astro.netlify.com/static/auth0.png"/></a>
206
+
207
+ ## Backers
208
+
209
+ Support us with a monthly donation and help us continue our activities.
210
+
211
+ <a href="https://opencollective.com/koajs/backer/0/website" target="_blank"><img src="https://opencollective.com/koajs/backer/0/avatar.svg"></a>
212
+ <a href="https://opencollective.com/koajs/backer/1/website" target="_blank"><img src="https://opencollective.com/koajs/backer/1/avatar.svg"></a>
213
+ <a href="https://opencollective.com/koajs/backer/2/website" target="_blank"><img src="https://opencollective.com/koajs/backer/2/avatar.svg"></a>
214
+ <a href="https://opencollective.com/koajs/backer/3/website" target="_blank"><img src="https://opencollective.com/koajs/backer/3/avatar.svg"></a>
215
+ <a href="https://opencollective.com/koajs/backer/4/website" target="_blank"><img src="https://opencollective.com/koajs/backer/4/avatar.svg"></a>
216
+ <a href="https://opencollective.com/koajs/backer/5/website" target="_blank"><img src="https://opencollective.com/koajs/backer/5/avatar.svg"></a>
217
+ <a href="https://opencollective.com/koajs/backer/6/website" target="_blank"><img src="https://opencollective.com/koajs/backer/6/avatar.svg"></a>
218
+ <a href="https://opencollective.com/koajs/backer/7/website" target="_blank"><img src="https://opencollective.com/koajs/backer/7/avatar.svg"></a>
219
+ <a href="https://opencollective.com/koajs/backer/8/website" target="_blank"><img src="https://opencollective.com/koajs/backer/8/avatar.svg"></a>
220
+ <a href="https://opencollective.com/koajs/backer/9/website" target="_blank"><img src="https://opencollective.com/koajs/backer/9/avatar.svg"></a>
221
+ <a href="https://opencollective.com/koajs/backer/10/website" target="_blank"><img src="https://opencollective.com/koajs/backer/10/avatar.svg"></a>
222
+ <a href="https://opencollective.com/koajs/backer/11/website" target="_blank"><img src="https://opencollective.com/koajs/backer/11/avatar.svg"></a>
223
+ <a href="https://opencollective.com/koajs/backer/12/website" target="_blank"><img src="https://opencollective.com/koajs/backer/12/avatar.svg"></a>
224
+ <a href="https://opencollective.com/koajs/backer/13/website" target="_blank"><img src="https://opencollective.com/koajs/backer/13/avatar.svg"></a>
225
+ <a href="https://opencollective.com/koajs/backer/14/website" target="_blank"><img src="https://opencollective.com/koajs/backer/14/avatar.svg"></a>
226
+ <a href="https://opencollective.com/koajs/backer/15/website" target="_blank"><img src="https://opencollective.com/koajs/backer/15/avatar.svg"></a>
227
+ <a href="https://opencollective.com/koajs/backer/16/website" target="_blank"><img src="https://opencollective.com/koajs/backer/16/avatar.svg"></a>
228
+ <a href="https://opencollective.com/koajs/backer/17/website" target="_blank"><img src="https://opencollective.com/koajs/backer/17/avatar.svg"></a>
229
+ <a href="https://opencollective.com/koajs/backer/18/website" target="_blank"><img src="https://opencollective.com/koajs/backer/18/avatar.svg"></a>
230
+ <a href="https://opencollective.com/koajs/backer/19/website" target="_blank"><img src="https://opencollective.com/koajs/backer/19/avatar.svg"></a>
231
+ <a href="https://opencollective.com/koajs/backer/20/website" target="_blank"><img src="https://opencollective.com/koajs/backer/20/avatar.svg"></a>
232
+ <a href="https://opencollective.com/koajs/backer/21/website" target="_blank"><img src="https://opencollective.com/koajs/backer/21/avatar.svg"></a>
233
+ <a href="https://opencollective.com/koajs/backer/22/website" target="_blank"><img src="https://opencollective.com/koajs/backer/22/avatar.svg"></a>
234
+ <a href="https://opencollective.com/koajs/backer/23/website" target="_blank"><img src="https://opencollective.com/koajs/backer/23/avatar.svg"></a>
235
+ <a href="https://opencollective.com/koajs/backer/24/website" target="_blank"><img src="https://opencollective.com/koajs/backer/24/avatar.svg"></a>
236
+ <a href="https://opencollective.com/koajs/backer/25/website" target="_blank"><img src="https://opencollective.com/koajs/backer/25/avatar.svg"></a>
237
+ <a href="https://opencollective.com/koajs/backer/26/website" target="_blank"><img src="https://opencollective.com/koajs/backer/26/avatar.svg"></a>
238
+ <a href="https://opencollective.com/koajs/backer/27/website" target="_blank"><img src="https://opencollective.com/koajs/backer/27/avatar.svg"></a>
239
+ <a href="https://opencollective.com/koajs/backer/28/website" target="_blank"><img src="https://opencollective.com/koajs/backer/28/avatar.svg"></a>
240
+ <a href="https://opencollective.com/koajs/backer/29/website" target="_blank"><img src="https://opencollective.com/koajs/backer/29/avatar.svg"></a>
241
+
242
+ ## Sponsors
243
+
244
+ Become a sponsor and get your logo on our README on Github with a link to your site.
245
+
246
+ <a href="https://opencollective.com/koajs/sponsor/0/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/0/avatar.svg"></a>
247
+ <a href="https://opencollective.com/koajs/sponsor/1/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/1/avatar.svg"></a>
248
+ <a href="https://opencollective.com/koajs/sponsor/2/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/2/avatar.svg"></a>
249
+ <a href="https://opencollective.com/koajs/sponsor/3/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/3/avatar.svg"></a>
250
+ <a href="https://opencollective.com/koajs/sponsor/4/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/4/avatar.svg"></a>
251
+ <a href="https://opencollective.com/koajs/sponsor/5/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/5/avatar.svg"></a>
252
+ <a href="https://opencollective.com/koajs/sponsor/6/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/6/avatar.svg"></a>
253
+ <a href="https://opencollective.com/koajs/sponsor/7/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/7/avatar.svg"></a>
254
+ <a href="https://opencollective.com/koajs/sponsor/8/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/8/avatar.svg"></a>
255
+ <a href="https://opencollective.com/koajs/sponsor/9/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/9/avatar.svg"></a>
256
+ <a href="https://opencollective.com/koajs/sponsor/10/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/10/avatar.svg"></a>
257
+ <a href="https://opencollective.com/koajs/sponsor/11/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/11/avatar.svg"></a>
258
+ <a href="https://opencollective.com/koajs/sponsor/12/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/12/avatar.svg"></a>
259
+ <a href="https://opencollective.com/koajs/sponsor/13/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/13/avatar.svg"></a>
260
+ <a href="https://opencollective.com/koajs/sponsor/14/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/14/avatar.svg"></a>
261
+ <a href="https://opencollective.com/koajs/sponsor/15/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/15/avatar.svg"></a>
262
+ <a href="https://opencollective.com/koajs/sponsor/16/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/16/avatar.svg"></a>
263
+ <a href="https://opencollective.com/koajs/sponsor/17/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/17/avatar.svg"></a>
264
+ <a href="https://opencollective.com/koajs/sponsor/18/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/18/avatar.svg"></a>
265
+ <a href="https://opencollective.com/koajs/sponsor/19/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/19/avatar.svg"></a>
266
+ <a href="https://opencollective.com/koajs/sponsor/20/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/20/avatar.svg"></a>
267
+ <a href="https://opencollective.com/koajs/sponsor/21/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/21/avatar.svg"></a>
268
+ <a href="https://opencollective.com/koajs/sponsor/22/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/22/avatar.svg"></a>
269
+ <a href="https://opencollective.com/koajs/sponsor/23/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/23/avatar.svg"></a>
270
+ <a href="https://opencollective.com/koajs/sponsor/24/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/24/avatar.svg"></a>
271
+ <a href="https://opencollective.com/koajs/sponsor/25/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/25/avatar.svg"></a>
272
+ <a href="https://opencollective.com/koajs/sponsor/26/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/26/avatar.svg"></a>
273
+ <a href="https://opencollective.com/koajs/sponsor/27/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/27/avatar.svg"></a>
274
+ <a href="https://opencollective.com/koajs/sponsor/28/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/28/avatar.svg"></a>
275
+ <a href="https://opencollective.com/koajs/sponsor/29/website" target="_blank"><img src="https://opencollective.com/koajs/sponsor/29/avatar.svg"></a>
276
+
277
+ # License
278
+
279
+ [MIT](https://github.com/eggjs/koa/blob/master/LICENSE)
package/dist/koa.mjs ADDED
@@ -0,0 +1,4 @@
1
+ import mod from "../lib/application.js";
2
+
3
+ export default mod;
4
+ export const HttpError = mod.HttpError;
@@ -0,0 +1,318 @@
1
+
2
+ 'use strict';
3
+
4
+ /**
5
+ * Module dependencies.
6
+ */
7
+
8
+ const isGeneratorFunction = require('is-generator-function');
9
+ const debug = require('debug')('koa:application');
10
+ const onFinished = require('on-finished');
11
+ const assert = require('assert');
12
+ const response = require('./response');
13
+ const compose = require('koa-compose');
14
+ const context = require('./context');
15
+ const request = require('./request');
16
+ const statuses = require('statuses');
17
+ const Emitter = require('events');
18
+ const util = require('util');
19
+ const Stream = require('stream');
20
+ const http = require('http');
21
+ const only = require('only');
22
+ const convert = require('koa-convert');
23
+ const deprecate = require('depd')('koa');
24
+ const { HttpError } = require('http-errors');
25
+
26
+ /**
27
+ * Expose `Application` class.
28
+ * Inherits from `Emitter.prototype`.
29
+ */
30
+
31
+ module.exports = class Application extends Emitter {
32
+ /**
33
+ * Initialize a new `Application`.
34
+ *
35
+ * @api public
36
+ */
37
+
38
+ /**
39
+ *
40
+ * @param {object} [options] Application options
41
+ * @param {string} [options.env='development'] Environment
42
+ * @param {string[]} [options.keys] Signed cookie keys
43
+ * @param {boolean} [options.proxy] Trust proxy headers
44
+ * @param {number} [options.subdomainOffset] Subdomain offset
45
+ * @param {string} [options.proxyIpHeader] Proxy IP header, defaults to X-Forwarded-For
46
+ * @param {number} [options.maxIpsCount] Max IPs read from proxy IP header, default to 0 (means infinity)
47
+ *
48
+ */
49
+
50
+ constructor(options) {
51
+ super();
52
+ options = options || {};
53
+ this.proxy = options.proxy || false;
54
+ this.subdomainOffset = options.subdomainOffset || 2;
55
+ this.proxyIpHeader = options.proxyIpHeader || 'X-Forwarded-For';
56
+ this.maxIpsCount = options.maxIpsCount || 0;
57
+ this.env = options.env || process.env.NODE_ENV || 'development';
58
+ if (options.keys) this.keys = options.keys;
59
+ this.middleware = [];
60
+ this.context = Object.create(context);
61
+ this.request = Object.create(request);
62
+ this.response = Object.create(response);
63
+ // util.inspect.custom support for node 6+
64
+ /* istanbul ignore else */
65
+ if (util.inspect.custom) {
66
+ this[util.inspect.custom] = this.inspect;
67
+ }
68
+ if (options.asyncLocalStorage) {
69
+ const { AsyncLocalStorage } = require('async_hooks');
70
+ assert(AsyncLocalStorage, 'Requires node 12.17.0 or higher to enable asyncLocalStorage');
71
+ this.ctxStorage = new AsyncLocalStorage();
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Shorthand for:
77
+ *
78
+ * http.createServer(app.callback()).listen(...)
79
+ *
80
+ * @param {Mixed} ...
81
+ * @return {Server}
82
+ * @api public
83
+ */
84
+
85
+ listen(...args) {
86
+ debug('listen');
87
+ const server = http.createServer(this.callback());
88
+ return server.listen(...args);
89
+ }
90
+
91
+ /**
92
+ * Return JSON representation.
93
+ * We only bother showing settings.
94
+ *
95
+ * @return {Object}
96
+ * @api public
97
+ */
98
+
99
+ toJSON() {
100
+ return only(this, [
101
+ 'subdomainOffset',
102
+ 'proxy',
103
+ 'env'
104
+ ]);
105
+ }
106
+
107
+ /**
108
+ * Inspect implementation.
109
+ *
110
+ * @return {Object}
111
+ * @api public
112
+ */
113
+
114
+ inspect() {
115
+ return this.toJSON();
116
+ }
117
+
118
+ /**
119
+ * Use the given middleware `fn`.
120
+ *
121
+ * Old-style middleware will be converted.
122
+ *
123
+ * @param {Function} fn
124
+ * @return {Application} self
125
+ * @api public
126
+ */
127
+
128
+ use(fn) {
129
+ if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
130
+ if (isGeneratorFunction(fn)) {
131
+ deprecate('Support for generators will be removed in v3. ' +
132
+ 'See the documentation for examples of how to convert old middleware ' +
133
+ 'https://github.com/koajs/koa/blob/master/docs/migration.md');
134
+ fn = convert(fn);
135
+ }
136
+ debug('use %s', fn._name || fn.name || '-');
137
+ this.middleware.push(fn);
138
+ return this;
139
+ }
140
+
141
+ /**
142
+ * Return a request handler callback
143
+ * for node's native http server.
144
+ *
145
+ * @return {Function}
146
+ * @api public
147
+ */
148
+
149
+ callback() {
150
+ const fn = compose(this.middleware);
151
+
152
+ if (!this.listenerCount('error')) this.on('error', this.onerror);
153
+
154
+ const handleRequest = (req, res) => {
155
+ const ctx = this.createContext(req, res);
156
+ if (!this.ctxStorage) {
157
+ return this.handleRequest(ctx, fn);
158
+ }
159
+ return this.ctxStorage.run(ctx, async() => {
160
+ return await this.handleRequest(ctx, fn);
161
+ });
162
+ };
163
+
164
+ return handleRequest;
165
+ }
166
+
167
+ /**
168
+ * return currnect contenxt from async local storage
169
+ */
170
+ get currentContext() {
171
+ if (this.ctxStorage) return this.ctxStorage.getStore();
172
+ }
173
+
174
+ /**
175
+ * Handle request in callback.
176
+ *
177
+ * @api private
178
+ */
179
+
180
+ handleRequest(ctx, fnMiddleware) {
181
+ const res = ctx.res;
182
+ res.statusCode = 404;
183
+ const onerror = err => ctx.onerror(err);
184
+ const handleResponse = () => respond(ctx);
185
+ onFinished(res, onerror);
186
+ return fnMiddleware(ctx).then(handleResponse).catch(onerror);
187
+ }
188
+
189
+ /**
190
+ * Initialize a new context.
191
+ *
192
+ * @api private
193
+ */
194
+
195
+ createContext(req, res) {
196
+ const context = Object.create(this.context);
197
+ const request = context.request = Object.create(this.request);
198
+ const response = context.response = Object.create(this.response);
199
+ context.app = request.app = response.app = this;
200
+ context.req = request.req = response.req = req;
201
+ context.res = request.res = response.res = res;
202
+ request.ctx = response.ctx = context;
203
+ request.response = response;
204
+ response.request = request;
205
+ context.originalUrl = request.originalUrl = req.url;
206
+ context.state = {};
207
+ return context;
208
+ }
209
+
210
+ /**
211
+ * Default error handler.
212
+ *
213
+ * @param {Error} err
214
+ * @api private
215
+ */
216
+
217
+ onerror(err) {
218
+ // When dealing with cross-globals a normal `instanceof` check doesn't work properly.
219
+ // See https://github.com/koajs/koa/issues/1466
220
+ // We can probably remove it once jest fixes https://github.com/facebook/jest/issues/2549.
221
+ const isNativeError =
222
+ Object.prototype.toString.call(err) === '[object Error]' ||
223
+ err instanceof Error;
224
+ if (!isNativeError) throw new TypeError(util.format('non-error thrown: %j', err));
225
+
226
+ if (404 === err.status || err.expose) return;
227
+ if (this.silent) return;
228
+
229
+ const msg = err.stack || err.toString();
230
+ console.error(`\n${msg.replace(/^/gm, ' ')}\n`);
231
+ }
232
+
233
+ /**
234
+ * Help TS users comply to CommonJS, ESM, bundler mismatch.
235
+ * @see https://github.com/koajs/koa/issues/1513
236
+ */
237
+
238
+ static get default() {
239
+ return Application;
240
+ }
241
+
242
+ createAsyncCtxStorageMiddleware() {
243
+ const app = this;
244
+ return async function asyncCtxStorage(ctx, next) {
245
+ await app.ctxStorage.run(ctx, async() => {
246
+ return await next();
247
+ });
248
+ };
249
+ }
250
+ };
251
+
252
+ /**
253
+ * Response helper.
254
+ */
255
+
256
+ function respond(ctx) {
257
+ // allow bypassing koa
258
+ if (false === ctx.respond) return;
259
+
260
+ if (!ctx.writable) return;
261
+
262
+ const res = ctx.res;
263
+ let body = ctx.body;
264
+ const code = ctx.status;
265
+
266
+ // ignore body
267
+ if (statuses.empty[code]) {
268
+ // strip headers
269
+ ctx.body = null;
270
+ return res.end();
271
+ }
272
+
273
+ if ('HEAD' === ctx.method) {
274
+ if (!res.headersSent && !ctx.response.has('Content-Length')) {
275
+ const { length } = ctx.response;
276
+ if (Number.isInteger(length)) ctx.length = length;
277
+ }
278
+ return res.end();
279
+ }
280
+
281
+ // status body
282
+ if (null == body) {
283
+ if (ctx.response._explicitNullBody) {
284
+ ctx.response.remove('Content-Type');
285
+ ctx.response.remove('Transfer-Encoding');
286
+ return res.end();
287
+ }
288
+ if (ctx.req.httpVersionMajor >= 2) {
289
+ body = String(code);
290
+ } else {
291
+ body = ctx.message || String(code);
292
+ }
293
+ if (!res.headersSent) {
294
+ ctx.type = 'text';
295
+ ctx.length = Buffer.byteLength(body);
296
+ }
297
+ return res.end(body);
298
+ }
299
+
300
+ // responses
301
+ if (Buffer.isBuffer(body)) return res.end(body);
302
+ if ('string' === typeof body) return res.end(body);
303
+ if (body instanceof Stream) return body.pipe(res);
304
+
305
+ // body: json
306
+ body = JSON.stringify(body);
307
+ if (!res.headersSent) {
308
+ ctx.length = Buffer.byteLength(body);
309
+ }
310
+ res.end(body);
311
+ }
312
+
313
+ /**
314
+ * Make HttpError available to consumers of the library so that consumers don't
315
+ * have a direct dependency upon `http-errors`
316
+ */
317
+
318
+ module.exports.HttpError = HttpError;