koa 2.14.0 → 3.0.0-alpha.0
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/Readme.md +6 -7
- package/lib/application.js +143 -132
- package/lib/context.js +45 -45
- package/lib/request.js +153 -153
- package/lib/response.js +154 -148
- package/package.json +7 -16
- package/History.md +0 -690
package/Readme.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[![gitter][gitter-image]][gitter-url]
|
|
4
4
|
[![NPM version][npm-image]][npm-url]
|
|
5
|
-
[![build status][
|
|
5
|
+
[![build status][github-action-image]][github-action-url]
|
|
6
6
|
[![Test coverage][coveralls-image]][coveralls-url]
|
|
7
7
|
[![OpenCollective Backers][backers-image]](#backers)
|
|
8
8
|
[![OpenCollective Sponsors][sponsors-image]](#sponsors)
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
## Installation
|
|
19
19
|
|
|
20
|
-
Koa requires __node
|
|
20
|
+
Koa requires __node v12.17.0__ or higher for ES2015 and async function support.
|
|
21
21
|
|
|
22
22
|
```
|
|
23
23
|
$ npm install koa
|
|
@@ -40,9 +40,7 @@ app.listen(3000);
|
|
|
40
40
|
## Getting started
|
|
41
41
|
|
|
42
42
|
- [Kick-Off-Koa](https://github.com/koajs/kick-off-koa) - An intro to Koa via a set of self-guided workshops.
|
|
43
|
-
- [
|
|
44
|
-
- [Introduction Screencast](https://knowthen.com/episode-3-koajs-quickstart-guide/) - An introduction to installing and getting started with Koa
|
|
45
|
-
|
|
43
|
+
- [Guide](docs/guide.md) - Go straight to the docs.
|
|
46
44
|
|
|
47
45
|
## Middleware
|
|
48
46
|
|
|
@@ -181,6 +179,7 @@ See [AUTHORS](AUTHORS).
|
|
|
181
179
|
|
|
182
180
|
## Community
|
|
183
181
|
|
|
182
|
+
- [KoaJS Slack Group](https://join.slack.com/t/koa-js/shared_invite/zt-5pjgthmb-1JeKDbByqqcARtlPbtf~vQ)
|
|
184
183
|
- [Badgeboard](https://koajs.github.io/badgeboard) and list of official modules
|
|
185
184
|
- [Examples](https://github.com/koajs/examples)
|
|
186
185
|
- [Middleware](https://github.com/koajs/koa/wiki) list
|
|
@@ -276,8 +275,8 @@ Become a sponsor and get your logo on our README on Github with a link to your s
|
|
|
276
275
|
|
|
277
276
|
[npm-image]: https://img.shields.io/npm/v/koa.svg?style=flat-square
|
|
278
277
|
[npm-url]: https://www.npmjs.com/package/koa
|
|
279
|
-
[
|
|
280
|
-
[
|
|
278
|
+
[github-action-image]: https://github.com/koajs/koa/actions/workflows/node.js.yml/badge.svg
|
|
279
|
+
[github-action-url]: https://github.com/koajs/koa/actions/workflows/node.js.yml
|
|
281
280
|
[coveralls-image]: https://img.shields.io/codecov/c/github/koajs/koa.svg?style=flat-square
|
|
282
281
|
[coveralls-url]: https://codecov.io/github/koajs/koa?branch=master
|
|
283
282
|
[backers-image]: https://opencollective.com/koajs/backers/badge.svg?style=flat-square
|
package/lib/application.js
CHANGED
|
@@ -1,27 +1,38 @@
|
|
|
1
1
|
|
|
2
|
-
'use strict'
|
|
2
|
+
'use strict'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Module dependencies.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const onFinished = require('on-finished')
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
8
|
+
const debug = require('debug')('koa:application')
|
|
9
|
+
const assert = require('assert')
|
|
10
|
+
const onFinished = require('on-finished')
|
|
11
|
+
const response = require('./response')
|
|
12
|
+
const compose = require('koa-compose')
|
|
13
|
+
const context = require('./context')
|
|
14
|
+
const request = require('./request')
|
|
15
|
+
const statuses = require('statuses')
|
|
16
|
+
const Emitter = require('events')
|
|
17
|
+
const util = require('util')
|
|
18
|
+
const Stream = require('stream')
|
|
19
|
+
const http = require('http')
|
|
20
|
+
const only = require('only')
|
|
21
|
+
const { HttpError } = require('http-errors')
|
|
22
|
+
|
|
23
|
+
/** @typedef {typeof import ('./context') & {
|
|
24
|
+
* app: Application
|
|
25
|
+
* req: import('http').IncomingMessage
|
|
26
|
+
* res: import('http').ServerResponse
|
|
27
|
+
* request: KoaRequest
|
|
28
|
+
* response: KoaResponse
|
|
29
|
+
* state: any
|
|
30
|
+
* originalUrl: string
|
|
31
|
+
* }} Context */
|
|
32
|
+
|
|
33
|
+
/** @typedef {typeof import('./request')} KoaRequest */
|
|
34
|
+
|
|
35
|
+
/** @typedef {typeof import('./response')} KoaResponse */
|
|
25
36
|
|
|
26
37
|
/**
|
|
27
38
|
* Expose `Application` class.
|
|
@@ -47,29 +58,30 @@ module.exports = class Application extends Emitter {
|
|
|
47
58
|
*
|
|
48
59
|
*/
|
|
49
60
|
|
|
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
|
-
|
|
59
|
-
this.
|
|
60
|
-
this.
|
|
61
|
-
this.
|
|
62
|
-
this.
|
|
61
|
+
constructor (options) {
|
|
62
|
+
super()
|
|
63
|
+
options = options || {}
|
|
64
|
+
this.proxy = options.proxy || false
|
|
65
|
+
this.subdomainOffset = options.subdomainOffset || 2
|
|
66
|
+
this.proxyIpHeader = options.proxyIpHeader || 'X-Forwarded-For'
|
|
67
|
+
this.maxIpsCount = options.maxIpsCount || 0
|
|
68
|
+
this.env = options.env || process.env.NODE_ENV || 'development'
|
|
69
|
+
this.compose = options.compose || compose
|
|
70
|
+
if (options.keys) this.keys = options.keys
|
|
71
|
+
this.middleware = []
|
|
72
|
+
this.context = Object.create(context)
|
|
73
|
+
this.request = Object.create(request)
|
|
74
|
+
this.response = Object.create(response)
|
|
63
75
|
// util.inspect.custom support for node 6+
|
|
64
76
|
/* istanbul ignore else */
|
|
65
77
|
if (util.inspect.custom) {
|
|
66
|
-
this[util.inspect.custom] = this.inspect
|
|
78
|
+
this[util.inspect.custom] = this.inspect
|
|
67
79
|
}
|
|
68
80
|
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
|
-
this.use(
|
|
81
|
+
const { AsyncLocalStorage } = require('async_hooks')
|
|
82
|
+
assert(AsyncLocalStorage, 'Requires node 12.17.0 or higher to enable asyncLocalStorage')
|
|
83
|
+
this.ctxStorage = new AsyncLocalStorage()
|
|
84
|
+
this.use(this.createAsyncCtxStorageMiddleware())
|
|
73
85
|
}
|
|
74
86
|
}
|
|
75
87
|
|
|
@@ -79,14 +91,14 @@ module.exports = class Application extends Emitter {
|
|
|
79
91
|
* http.createServer(app.callback()).listen(...)
|
|
80
92
|
*
|
|
81
93
|
* @param {Mixed} ...
|
|
82
|
-
* @return {Server}
|
|
94
|
+
* @return {import('http').Server}
|
|
83
95
|
* @api public
|
|
84
96
|
*/
|
|
85
97
|
|
|
86
|
-
listen(...args) {
|
|
87
|
-
debug('listen')
|
|
88
|
-
const server = http.createServer(this.callback())
|
|
89
|
-
return server.listen(...args)
|
|
98
|
+
listen (...args) {
|
|
99
|
+
debug('listen')
|
|
100
|
+
const server = http.createServer(this.callback())
|
|
101
|
+
return server.listen(...args)
|
|
90
102
|
}
|
|
91
103
|
|
|
92
104
|
/**
|
|
@@ -97,12 +109,12 @@ module.exports = class Application extends Emitter {
|
|
|
97
109
|
* @api public
|
|
98
110
|
*/
|
|
99
111
|
|
|
100
|
-
toJSON() {
|
|
112
|
+
toJSON () {
|
|
101
113
|
return only(this, [
|
|
102
114
|
'subdomainOffset',
|
|
103
115
|
'proxy',
|
|
104
116
|
'env'
|
|
105
|
-
])
|
|
117
|
+
])
|
|
106
118
|
}
|
|
107
119
|
|
|
108
120
|
/**
|
|
@@ -112,8 +124,8 @@ module.exports = class Application extends Emitter {
|
|
|
112
124
|
* @api public
|
|
113
125
|
*/
|
|
114
126
|
|
|
115
|
-
inspect() {
|
|
116
|
-
return this.toJSON()
|
|
127
|
+
inspect () {
|
|
128
|
+
return this.toJSON()
|
|
117
129
|
}
|
|
118
130
|
|
|
119
131
|
/**
|
|
@@ -121,22 +133,16 @@ module.exports = class Application extends Emitter {
|
|
|
121
133
|
*
|
|
122
134
|
* Old-style middleware will be converted.
|
|
123
135
|
*
|
|
124
|
-
* @param {
|
|
136
|
+
* @param {(context: Context) => Promise<any | void>} fn
|
|
125
137
|
* @return {Application} self
|
|
126
138
|
* @api public
|
|
127
139
|
*/
|
|
128
140
|
|
|
129
|
-
use(fn) {
|
|
130
|
-
if (typeof fn !== 'function') throw new TypeError('middleware must be a function!')
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
'https://github.com/koajs/koa/blob/master/docs/migration.md');
|
|
135
|
-
fn = convert(fn);
|
|
136
|
-
}
|
|
137
|
-
debug('use %s', fn._name || fn.name || '-');
|
|
138
|
-
this.middleware.push(fn);
|
|
139
|
-
return this;
|
|
141
|
+
use (fn) {
|
|
142
|
+
if (typeof fn !== 'function') throw new TypeError('middleware must be a function!')
|
|
143
|
+
debug('use %s', fn._name || fn.name || '-')
|
|
144
|
+
this.middleware.push(fn)
|
|
145
|
+
return this
|
|
140
146
|
}
|
|
141
147
|
|
|
142
148
|
/**
|
|
@@ -147,24 +153,24 @@ module.exports = class Application extends Emitter {
|
|
|
147
153
|
* @api public
|
|
148
154
|
*/
|
|
149
155
|
|
|
150
|
-
callback() {
|
|
151
|
-
const fn = compose(this.middleware)
|
|
156
|
+
callback () {
|
|
157
|
+
const fn = this.compose(this.middleware)
|
|
152
158
|
|
|
153
|
-
if (!this.listenerCount('error')) this.on('error', this.onerror)
|
|
159
|
+
if (!this.listenerCount('error')) this.on('error', this.onerror)
|
|
154
160
|
|
|
155
161
|
const handleRequest = (req, res) => {
|
|
156
|
-
const ctx = this.createContext(req, res)
|
|
157
|
-
return this.handleRequest(ctx, fn)
|
|
158
|
-
}
|
|
162
|
+
const ctx = this.createContext(req, res)
|
|
163
|
+
return this.handleRequest(ctx, fn)
|
|
164
|
+
}
|
|
159
165
|
|
|
160
|
-
return handleRequest
|
|
166
|
+
return handleRequest
|
|
161
167
|
}
|
|
162
168
|
|
|
163
169
|
/**
|
|
164
|
-
* return
|
|
170
|
+
* return current context from async local storage
|
|
165
171
|
*/
|
|
166
|
-
get currentContext() {
|
|
167
|
-
if (this.ctxStorage) return this.ctxStorage.getStore()
|
|
172
|
+
get currentContext () {
|
|
173
|
+
if (this.ctxStorage) return this.ctxStorage.getStore()
|
|
168
174
|
}
|
|
169
175
|
|
|
170
176
|
/**
|
|
@@ -173,13 +179,13 @@ module.exports = class Application extends Emitter {
|
|
|
173
179
|
* @api private
|
|
174
180
|
*/
|
|
175
181
|
|
|
176
|
-
handleRequest(ctx, fnMiddleware) {
|
|
177
|
-
const res = ctx.res
|
|
178
|
-
res.statusCode = 404
|
|
179
|
-
const onerror = err => ctx.onerror(err)
|
|
180
|
-
const handleResponse = () => respond(ctx)
|
|
181
|
-
onFinished(res, onerror)
|
|
182
|
-
return fnMiddleware(ctx).then(handleResponse).catch(onerror)
|
|
182
|
+
handleRequest (ctx, fnMiddleware) {
|
|
183
|
+
const res = ctx.res
|
|
184
|
+
res.statusCode = 404
|
|
185
|
+
const onerror = err => ctx.onerror(err)
|
|
186
|
+
const handleResponse = () => respond(ctx)
|
|
187
|
+
onFinished(res, onerror)
|
|
188
|
+
return fnMiddleware(ctx).then(handleResponse).catch(onerror)
|
|
183
189
|
}
|
|
184
190
|
|
|
185
191
|
/**
|
|
@@ -188,19 +194,22 @@ module.exports = class Application extends Emitter {
|
|
|
188
194
|
* @api private
|
|
189
195
|
*/
|
|
190
196
|
|
|
191
|
-
createContext(req, res) {
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
request.
|
|
199
|
-
request.response =
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
197
|
+
createContext (req, res) {
|
|
198
|
+
/** @type {Context} */
|
|
199
|
+
const context = Object.create(this.context)
|
|
200
|
+
/** @type {KoaRequest} */
|
|
201
|
+
const request = context.request = Object.create(this.request)
|
|
202
|
+
/** @type {KoaResponse} */
|
|
203
|
+
const response = context.response = Object.create(this.response)
|
|
204
|
+
context.app = request.app = response.app = this
|
|
205
|
+
context.req = request.req = response.req = req
|
|
206
|
+
context.res = request.res = response.res = res
|
|
207
|
+
request.ctx = response.ctx = context
|
|
208
|
+
request.response = response
|
|
209
|
+
response.request = request
|
|
210
|
+
context.originalUrl = request.originalUrl = req.url
|
|
211
|
+
context.state = {}
|
|
212
|
+
return context
|
|
204
213
|
}
|
|
205
214
|
|
|
206
215
|
/**
|
|
@@ -210,20 +219,20 @@ module.exports = class Application extends Emitter {
|
|
|
210
219
|
* @api private
|
|
211
220
|
*/
|
|
212
221
|
|
|
213
|
-
onerror(err) {
|
|
222
|
+
onerror (err) {
|
|
214
223
|
// When dealing with cross-globals a normal `instanceof` check doesn't work properly.
|
|
215
224
|
// See https://github.com/koajs/koa/issues/1466
|
|
216
225
|
// We can probably remove it once jest fixes https://github.com/facebook/jest/issues/2549.
|
|
217
226
|
const isNativeError =
|
|
218
227
|
Object.prototype.toString.call(err) === '[object Error]' ||
|
|
219
|
-
err instanceof Error
|
|
220
|
-
if (!isNativeError) throw new TypeError(util.format('non-error thrown: %j', err))
|
|
228
|
+
err instanceof Error
|
|
229
|
+
if (!isNativeError) throw new TypeError(util.format('non-error thrown: %j', err))
|
|
221
230
|
|
|
222
|
-
if (
|
|
223
|
-
if (this.silent) return
|
|
231
|
+
if (err.status === 404 || err.expose) return
|
|
232
|
+
if (this.silent) return
|
|
224
233
|
|
|
225
|
-
const msg = err.stack || err.toString()
|
|
226
|
-
console.error(`\n${msg.replace(/^/gm, ' ')}\n`)
|
|
234
|
+
const msg = err.stack || err.toString()
|
|
235
|
+
console.error(`\n${msg.replace(/^/gm, ' ')}\n`)
|
|
227
236
|
}
|
|
228
237
|
|
|
229
238
|
/**
|
|
@@ -231,78 +240,80 @@ module.exports = class Application extends Emitter {
|
|
|
231
240
|
* @see https://github.com/koajs/koa/issues/1513
|
|
232
241
|
*/
|
|
233
242
|
|
|
234
|
-
static get default() {
|
|
235
|
-
return Application
|
|
243
|
+
static get default () {
|
|
244
|
+
return Application
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
createAsyncCtxStorageMiddleware () {
|
|
248
|
+
const app = this
|
|
249
|
+
return async function asyncCtxStorage (ctx, next) {
|
|
250
|
+
await app.ctxStorage.run(ctx, async () => {
|
|
251
|
+
return await next()
|
|
252
|
+
})
|
|
253
|
+
}
|
|
236
254
|
}
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
function createAsyncCtxStorage(app) {
|
|
240
|
-
return async function asyncCtxStorage(ctx, next) {
|
|
241
|
-
await app.ctxStorage.run(ctx, async() => {
|
|
242
|
-
return await next();
|
|
243
|
-
});
|
|
244
|
-
};
|
|
245
255
|
}
|
|
246
256
|
|
|
247
257
|
/**
|
|
248
258
|
* Response helper.
|
|
249
259
|
*/
|
|
250
260
|
|
|
251
|
-
function respond(ctx) {
|
|
261
|
+
function respond (ctx) {
|
|
252
262
|
// allow bypassing koa
|
|
253
|
-
if (
|
|
263
|
+
if (ctx.respond === false) return
|
|
254
264
|
|
|
255
|
-
if (!ctx.writable) return
|
|
265
|
+
if (!ctx.writable) return
|
|
256
266
|
|
|
257
|
-
const res = ctx.res
|
|
258
|
-
let body = ctx.body
|
|
259
|
-
const code = ctx.status
|
|
267
|
+
const res = ctx.res
|
|
268
|
+
let body = ctx.body
|
|
269
|
+
const code = ctx.status
|
|
260
270
|
|
|
261
271
|
// ignore body
|
|
262
272
|
if (statuses.empty[code]) {
|
|
263
273
|
// strip headers
|
|
264
|
-
ctx.body = null
|
|
265
|
-
return res.end()
|
|
274
|
+
ctx.body = null
|
|
275
|
+
return res.end()
|
|
266
276
|
}
|
|
267
277
|
|
|
268
|
-
if ('HEAD'
|
|
278
|
+
if (ctx.method === 'HEAD') {
|
|
269
279
|
if (!res.headersSent && !ctx.response.has('Content-Length')) {
|
|
270
|
-
const { length } = ctx.response
|
|
271
|
-
if (Number.isInteger(length)) ctx.length = length
|
|
280
|
+
const { length } = ctx.response
|
|
281
|
+
if (Number.isInteger(length)) ctx.length = length
|
|
272
282
|
}
|
|
273
|
-
return res.end()
|
|
283
|
+
return res.end()
|
|
274
284
|
}
|
|
275
285
|
|
|
276
286
|
// status body
|
|
277
|
-
if (
|
|
287
|
+
if (body == null) {
|
|
278
288
|
if (ctx.response._explicitNullBody) {
|
|
279
|
-
ctx.response.remove('Content-Type')
|
|
280
|
-
ctx.response.remove('Transfer-Encoding')
|
|
281
|
-
|
|
289
|
+
ctx.response.remove('Content-Type')
|
|
290
|
+
ctx.response.remove('Transfer-Encoding')
|
|
291
|
+
ctx.length = 0
|
|
292
|
+
return res.end()
|
|
282
293
|
}
|
|
283
294
|
if (ctx.req.httpVersionMajor >= 2) {
|
|
284
|
-
body = String(code)
|
|
295
|
+
body = String(code)
|
|
285
296
|
} else {
|
|
286
|
-
body = ctx.message || String(code)
|
|
297
|
+
body = ctx.message || String(code)
|
|
287
298
|
}
|
|
288
299
|
if (!res.headersSent) {
|
|
289
|
-
ctx.type = 'text'
|
|
290
|
-
ctx.length = Buffer.byteLength(body)
|
|
300
|
+
ctx.type = 'text'
|
|
301
|
+
ctx.length = Buffer.byteLength(body)
|
|
291
302
|
}
|
|
292
|
-
return res.end(body)
|
|
303
|
+
return res.end(body)
|
|
293
304
|
}
|
|
294
305
|
|
|
295
306
|
// responses
|
|
296
|
-
if (Buffer.isBuffer(body)) return res.end(body)
|
|
297
|
-
if ('string'
|
|
298
|
-
if (body instanceof Stream) return body.pipe(res)
|
|
307
|
+
if (Buffer.isBuffer(body)) return res.end(body)
|
|
308
|
+
if (typeof body === 'string') return res.end(body)
|
|
309
|
+
if (body instanceof Stream) return body.pipe(res)
|
|
299
310
|
|
|
300
311
|
// body: json
|
|
301
|
-
body = JSON.stringify(body)
|
|
312
|
+
body = JSON.stringify(body)
|
|
302
313
|
if (!res.headersSent) {
|
|
303
|
-
ctx.length = Buffer.byteLength(body)
|
|
314
|
+
ctx.length = Buffer.byteLength(body)
|
|
304
315
|
}
|
|
305
|
-
res.end(body)
|
|
316
|
+
res.end(body)
|
|
306
317
|
}
|
|
307
318
|
|
|
308
319
|
/**
|
|
@@ -310,4 +321,4 @@ function respond(ctx) {
|
|
|
310
321
|
* have a direct dependency upon `http-errors`
|
|
311
322
|
*/
|
|
312
323
|
|
|
313
|
-
module.exports.HttpError = HttpError
|
|
324
|
+
module.exports.HttpError = HttpError
|
package/lib/context.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
|
|
2
|
-
'use strict'
|
|
2
|
+
'use strict'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Module dependencies.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
const util = require('util')
|
|
9
|
-
const createError = require('http-errors')
|
|
10
|
-
const httpAssert = require('http-assert')
|
|
11
|
-
const delegate = require('delegates')
|
|
12
|
-
const statuses = require('statuses')
|
|
13
|
-
const Cookies = require('cookies')
|
|
8
|
+
const util = require('util')
|
|
9
|
+
const createError = require('http-errors')
|
|
10
|
+
const httpAssert = require('http-assert')
|
|
11
|
+
const delegate = require('delegates')
|
|
12
|
+
const statuses = require('statuses')
|
|
13
|
+
const Cookies = require('cookies')
|
|
14
14
|
|
|
15
|
-
const COOKIES = Symbol('context#cookies')
|
|
15
|
+
const COOKIES = Symbol('context#cookies')
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Context prototype.
|
|
@@ -28,9 +28,9 @@ const proto = module.exports = {
|
|
|
28
28
|
* @api public
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
-
inspect() {
|
|
32
|
-
if (this === proto) return this
|
|
33
|
-
return this.toJSON()
|
|
31
|
+
inspect () {
|
|
32
|
+
if (this === proto) return this
|
|
33
|
+
return this.toJSON()
|
|
34
34
|
},
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -45,7 +45,7 @@ const proto = module.exports = {
|
|
|
45
45
|
* @api public
|
|
46
46
|
*/
|
|
47
47
|
|
|
48
|
-
toJSON() {
|
|
48
|
+
toJSON () {
|
|
49
49
|
return {
|
|
50
50
|
request: this.request.toJSON(),
|
|
51
51
|
response: this.response.toJSON(),
|
|
@@ -54,7 +54,7 @@ const proto = module.exports = {
|
|
|
54
54
|
req: '<original node req>',
|
|
55
55
|
res: '<original node res>',
|
|
56
56
|
socket: '<original node socket>'
|
|
57
|
-
}
|
|
57
|
+
}
|
|
58
58
|
},
|
|
59
59
|
|
|
60
60
|
/**
|
|
@@ -93,8 +93,8 @@ const proto = module.exports = {
|
|
|
93
93
|
* @api public
|
|
94
94
|
*/
|
|
95
95
|
|
|
96
|
-
throw(...args) {
|
|
97
|
-
throw createError(...args)
|
|
96
|
+
throw (...args) {
|
|
97
|
+
throw createError(...args)
|
|
98
98
|
},
|
|
99
99
|
|
|
100
100
|
/**
|
|
@@ -104,81 +104,81 @@ const proto = module.exports = {
|
|
|
104
104
|
* @api private
|
|
105
105
|
*/
|
|
106
106
|
|
|
107
|
-
onerror(err) {
|
|
107
|
+
onerror (err) {
|
|
108
108
|
// don't do anything if there is no error.
|
|
109
109
|
// this allows you to pass `this.onerror`
|
|
110
110
|
// to node-style callbacks.
|
|
111
|
-
if (
|
|
111
|
+
if (err == null) return
|
|
112
112
|
|
|
113
113
|
// When dealing with cross-globals a normal `instanceof` check doesn't work properly.
|
|
114
114
|
// See https://github.com/koajs/koa/issues/1466
|
|
115
115
|
// We can probably remove it once jest fixes https://github.com/facebook/jest/issues/2549.
|
|
116
116
|
const isNativeError =
|
|
117
117
|
Object.prototype.toString.call(err) === '[object Error]' ||
|
|
118
|
-
err instanceof Error
|
|
119
|
-
if (!isNativeError) err = new Error(util.format('non-error thrown: %j', err))
|
|
118
|
+
err instanceof Error
|
|
119
|
+
if (!isNativeError) err = new Error(util.format('non-error thrown: %j', err))
|
|
120
120
|
|
|
121
|
-
let headerSent = false
|
|
121
|
+
let headerSent = false
|
|
122
122
|
if (this.headerSent || !this.writable) {
|
|
123
|
-
headerSent = err.headerSent = true
|
|
123
|
+
headerSent = err.headerSent = true
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// delegate
|
|
127
|
-
this.app.emit('error', err, this)
|
|
127
|
+
this.app.emit('error', err, this)
|
|
128
128
|
|
|
129
129
|
// nothing we can do here other
|
|
130
130
|
// than delegate to the app-level
|
|
131
131
|
// handler and log.
|
|
132
132
|
if (headerSent) {
|
|
133
|
-
return
|
|
133
|
+
return
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
const { res } = this
|
|
136
|
+
const { res } = this
|
|
137
137
|
|
|
138
138
|
// first unset all headers
|
|
139
139
|
/* istanbul ignore else */
|
|
140
140
|
if (typeof res.getHeaderNames === 'function') {
|
|
141
|
-
res.getHeaderNames().forEach(name => res.removeHeader(name))
|
|
141
|
+
res.getHeaderNames().forEach(name => res.removeHeader(name))
|
|
142
142
|
} else {
|
|
143
|
-
res._headers = {}
|
|
143
|
+
res._headers = {} // Node < 7.7
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
// then set those specified
|
|
147
|
-
this.set(err.headers)
|
|
147
|
+
this.set(err.headers)
|
|
148
148
|
|
|
149
149
|
// force text/plain
|
|
150
|
-
this.type = 'text'
|
|
150
|
+
this.type = 'text'
|
|
151
151
|
|
|
152
|
-
let statusCode = err.status || err.statusCode
|
|
152
|
+
let statusCode = err.status || err.statusCode
|
|
153
153
|
|
|
154
154
|
// ENOENT support
|
|
155
|
-
if ('ENOENT'
|
|
155
|
+
if (err.code === 'ENOENT') statusCode = 404
|
|
156
156
|
|
|
157
157
|
// default to 500
|
|
158
|
-
if ('number'
|
|
158
|
+
if (typeof statusCode !== 'number' || !statuses[statusCode]) statusCode = 500
|
|
159
159
|
|
|
160
160
|
// respond
|
|
161
|
-
const code = statuses[statusCode]
|
|
162
|
-
const msg = err.expose ? err.message : code
|
|
163
|
-
this.status = err.status = statusCode
|
|
164
|
-
this.length = Buffer.byteLength(msg)
|
|
165
|
-
res.end(msg)
|
|
161
|
+
const code = statuses[statusCode]
|
|
162
|
+
const msg = err.expose ? err.message : code
|
|
163
|
+
this.status = err.status = statusCode
|
|
164
|
+
this.length = Buffer.byteLength(msg)
|
|
165
|
+
res.end(msg)
|
|
166
166
|
},
|
|
167
167
|
|
|
168
|
-
get cookies() {
|
|
168
|
+
get cookies () {
|
|
169
169
|
if (!this[COOKIES]) {
|
|
170
170
|
this[COOKIES] = new Cookies(this.req, this.res, {
|
|
171
171
|
keys: this.app.keys,
|
|
172
172
|
secure: this.request.secure
|
|
173
|
-
})
|
|
173
|
+
})
|
|
174
174
|
}
|
|
175
|
-
return this[COOKIES]
|
|
175
|
+
return this[COOKIES]
|
|
176
176
|
},
|
|
177
177
|
|
|
178
|
-
set cookies(_cookies) {
|
|
179
|
-
this[COOKIES] = _cookies
|
|
178
|
+
set cookies (_cookies) {
|
|
179
|
+
this[COOKIES] = _cookies
|
|
180
180
|
}
|
|
181
|
-
}
|
|
181
|
+
}
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
184
|
* Custom inspection implementation for newer Node.js versions.
|
|
@@ -189,7 +189,7 @@ const proto = module.exports = {
|
|
|
189
189
|
|
|
190
190
|
/* istanbul ignore else */
|
|
191
191
|
if (util.inspect.custom) {
|
|
192
|
-
module.exports[util.inspect.custom] = module.exports.inspect
|
|
192
|
+
module.exports[util.inspect.custom] = module.exports.inspect
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
/**
|
|
@@ -213,7 +213,7 @@ delegate(proto, 'response')
|
|
|
213
213
|
.access('lastModified')
|
|
214
214
|
.access('etag')
|
|
215
215
|
.getter('headerSent')
|
|
216
|
-
.getter('writable')
|
|
216
|
+
.getter('writable')
|
|
217
217
|
|
|
218
218
|
/**
|
|
219
219
|
* Request delegation.
|
|
@@ -248,4 +248,4 @@ delegate(proto, 'request')
|
|
|
248
248
|
.getter('stale')
|
|
249
249
|
.getter('fresh')
|
|
250
250
|
.getter('ips')
|
|
251
|
-
.getter('ip')
|
|
251
|
+
.getter('ip')
|