koa 2.5.1 → 2.6.1
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/History.md +44 -0
- package/lib/application.js +6 -11
- package/lib/context.js +31 -0
- package/lib/request.js +67 -7
- package/lib/response.js +17 -6
- package/package.json +23 -23
package/History.md
CHANGED
|
@@ -1,4 +1,48 @@
|
|
|
1
1
|
|
|
2
|
+
2.6.1 / 2018-10-23
|
|
3
|
+
==================
|
|
4
|
+
|
|
5
|
+
**fixes**
|
|
6
|
+
* [[`4964242`](http://github.com/koajs/koa/commit/49642428342e5f291eb9d690802e83ed830623b5)] - fix: use X-Forwarded-Host first on app.proxy present (#1263) (fengmk2 <<fengmk2@gmail.com>>)
|
|
7
|
+
|
|
8
|
+
2.6.0 / 2018-10-23
|
|
9
|
+
==================
|
|
10
|
+
|
|
11
|
+
**features**
|
|
12
|
+
* [[`9c5c58b`](http://github.com/koajs/koa/commit/9c5c58b18363494976185e7ddc790ac63de840ed)] - feat: use :authority header of http2 requests as host (#1262) (Martin Michaelis <<code@mgjm.de>>)
|
|
13
|
+
* [[`9146024`](http://github.com/koajs/koa/commit/9146024e1094e8bb871ab15d1b7fc556a710732f)] - feat: response.attachment append a parameter: options from contentDisposition (#1240) (小雷 <<863837949@qq.com>>)
|
|
14
|
+
|
|
15
|
+
**others**
|
|
16
|
+
* [[`d32623b`](http://github.com/koajs/koa/commit/d32623baa7a6273d47be67d587ad4ea0ecffc5de)] - docs: Update error-handling.md (#1239) (urugator <<j.placek@centrum.cz>>)
|
|
17
|
+
|
|
18
|
+
2.5.3 / 2018-09-11
|
|
19
|
+
==================
|
|
20
|
+
|
|
21
|
+
**fixes**
|
|
22
|
+
* [[`2ee32f5`](http://github.com/koajs/koa/commit/2ee32f50b88b383317e33cc0a4bfaa5f2eadead7)] - fix: pin debug@~3.1.0 avoid deprecated warnning (#1245) (fengmk2 <<fengmk2@gmail.com>>)
|
|
23
|
+
|
|
24
|
+
**others**
|
|
25
|
+
* [[`2180839`](http://github.com/koajs/koa/commit/2180839eda2cb16edcfda46ccfe24711680af850)] - docs: Update koa-vs-express.md (#1230) (Clayton Ray <<iamclaytonray@gmail.com>>)
|
|
26
|
+
|
|
27
|
+
2.5.2 / 2018-07-12
|
|
28
|
+
==================
|
|
29
|
+
|
|
30
|
+
* deps: upgrade all dependencies
|
|
31
|
+
* perf: avoid stringify when set header (#1220)
|
|
32
|
+
* perf: cache content type's result (#1218)
|
|
33
|
+
* perf: lazy init cookies and ip when first time use it (#1216)
|
|
34
|
+
* chore: fix comment & approve cov (#1214)
|
|
35
|
+
* docs: fix grammar
|
|
36
|
+
* test&cov: add test case (#1211)
|
|
37
|
+
* Lazily initialize `request.accept` and delegate `context.accept` (#1209)
|
|
38
|
+
* fix: use non deprecated custom inspect (#1198)
|
|
39
|
+
* Simplify processes in the getter `request.protocol` (#1203)
|
|
40
|
+
* docs: better demonstrate middleware flow (#1195)
|
|
41
|
+
* fix: Throw a TypeError instead of a AssertionError (#1199)
|
|
42
|
+
* chore: mistake in a comment (#1201)
|
|
43
|
+
* chore: use this.res.socket insteadof this.ctx.req.socket (#1177)
|
|
44
|
+
* chore: Using "listenerCount" instead of "listeners" (#1184)
|
|
45
|
+
|
|
2
46
|
2.5.1 / 2018-04-27
|
|
3
47
|
==================
|
|
4
48
|
|
package/lib/application.js
CHANGED
|
@@ -14,10 +14,8 @@ const isJSON = require('koa-is-json');
|
|
|
14
14
|
const context = require('./context');
|
|
15
15
|
const request = require('./request');
|
|
16
16
|
const statuses = require('statuses');
|
|
17
|
-
const Cookies = require('cookies');
|
|
18
|
-
const accepts = require('accepts');
|
|
19
17
|
const Emitter = require('events');
|
|
20
|
-
const
|
|
18
|
+
const util = require('util');
|
|
21
19
|
const Stream = require('stream');
|
|
22
20
|
const http = require('http');
|
|
23
21
|
const only = require('only');
|
|
@@ -46,6 +44,9 @@ module.exports = class Application extends Emitter {
|
|
|
46
44
|
this.context = Object.create(context);
|
|
47
45
|
this.request = Object.create(request);
|
|
48
46
|
this.response = Object.create(response);
|
|
47
|
+
if (util.inspect.custom) {
|
|
48
|
+
this[util.inspect.custom] = this.inspect;
|
|
49
|
+
}
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
/**
|
|
@@ -125,7 +126,7 @@ module.exports = class Application extends Emitter {
|
|
|
125
126
|
callback() {
|
|
126
127
|
const fn = compose(this.middleware);
|
|
127
128
|
|
|
128
|
-
if (!this.
|
|
129
|
+
if (!this.listenerCount('error')) this.on('error', this.onerror);
|
|
129
130
|
|
|
130
131
|
const handleRequest = (req, res) => {
|
|
131
132
|
const ctx = this.createContext(req, res);
|
|
@@ -167,12 +168,6 @@ module.exports = class Application extends Emitter {
|
|
|
167
168
|
request.response = response;
|
|
168
169
|
response.request = request;
|
|
169
170
|
context.originalUrl = request.originalUrl = req.url;
|
|
170
|
-
context.cookies = new Cookies(req, res, {
|
|
171
|
-
keys: this.keys,
|
|
172
|
-
secure: request.secure
|
|
173
|
-
});
|
|
174
|
-
request.ip = request.ips[0] || req.socket.remoteAddress || '';
|
|
175
|
-
context.accept = request.accept = accepts(req);
|
|
176
171
|
context.state = {};
|
|
177
172
|
return context;
|
|
178
173
|
}
|
|
@@ -185,7 +180,7 @@ module.exports = class Application extends Emitter {
|
|
|
185
180
|
*/
|
|
186
181
|
|
|
187
182
|
onerror(err) {
|
|
188
|
-
|
|
183
|
+
if (!(err instanceof Error)) throw new TypeError(util.format('non-error thrown: %j', err));
|
|
189
184
|
|
|
190
185
|
if (404 == err.status || err.expose) return;
|
|
191
186
|
if (this.silent) return;
|
package/lib/context.js
CHANGED
|
@@ -10,6 +10,9 @@ const createError = require('http-errors');
|
|
|
10
10
|
const httpAssert = require('http-assert');
|
|
11
11
|
const delegate = require('delegates');
|
|
12
12
|
const statuses = require('statuses');
|
|
13
|
+
const Cookies = require('cookies');
|
|
14
|
+
|
|
15
|
+
const COOKIES = Symbol('context#cookies');
|
|
13
16
|
|
|
14
17
|
/**
|
|
15
18
|
* Context prototype.
|
|
@@ -126,6 +129,7 @@ const proto = module.exports = {
|
|
|
126
129
|
const { res } = this;
|
|
127
130
|
|
|
128
131
|
// first unset all headers
|
|
132
|
+
/* istanbul ignore else */
|
|
129
133
|
if (typeof res.getHeaderNames === 'function') {
|
|
130
134
|
res.getHeaderNames().forEach(name => res.removeHeader(name));
|
|
131
135
|
} else {
|
|
@@ -150,9 +154,35 @@ const proto = module.exports = {
|
|
|
150
154
|
this.status = err.status;
|
|
151
155
|
this.length = Buffer.byteLength(msg);
|
|
152
156
|
this.res.end(msg);
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
get cookies() {
|
|
160
|
+
if (!this[COOKIES]) {
|
|
161
|
+
this[COOKIES] = new Cookies(this.req, this.res, {
|
|
162
|
+
keys: this.app.keys,
|
|
163
|
+
secure: this.request.secure
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return this[COOKIES];
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
set cookies(_cookies) {
|
|
170
|
+
this[COOKIES] = _cookies;
|
|
153
171
|
}
|
|
154
172
|
};
|
|
155
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Custom inspection implementation for newer Node.js versions.
|
|
176
|
+
*
|
|
177
|
+
* @return {Object}
|
|
178
|
+
* @api public
|
|
179
|
+
*/
|
|
180
|
+
|
|
181
|
+
/* istanbul ignore else */
|
|
182
|
+
if (util.inspect.custom) {
|
|
183
|
+
module.exports[util.inspect.custom] = module.exports.inspect;
|
|
184
|
+
}
|
|
185
|
+
|
|
156
186
|
/**
|
|
157
187
|
* Response delegation.
|
|
158
188
|
*/
|
|
@@ -194,6 +224,7 @@ delegate(proto, 'request')
|
|
|
194
224
|
.access('query')
|
|
195
225
|
.access('path')
|
|
196
226
|
.access('url')
|
|
227
|
+
.access('accept')
|
|
197
228
|
.getter('origin')
|
|
198
229
|
.getter('href')
|
|
199
230
|
.getter('subdomains')
|
package/lib/request.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const URL = require('url').URL;
|
|
9
9
|
const net = require('net');
|
|
10
|
+
const accepts = require('accepts');
|
|
10
11
|
const contentType = require('content-type');
|
|
11
12
|
const stringify = require('url').format;
|
|
12
13
|
const parse = require('parseurl');
|
|
@@ -14,6 +15,9 @@ const qs = require('querystring');
|
|
|
14
15
|
const typeis = require('type-is');
|
|
15
16
|
const fresh = require('fresh');
|
|
16
17
|
const only = require('only');
|
|
18
|
+
const util = require('util');
|
|
19
|
+
|
|
20
|
+
const IP = Symbol('context#ip');
|
|
17
21
|
|
|
18
22
|
/**
|
|
19
23
|
* Prototype.
|
|
@@ -226,7 +230,7 @@ module.exports = {
|
|
|
226
230
|
|
|
227
231
|
/**
|
|
228
232
|
* Set the search string. Same as
|
|
229
|
-
*
|
|
233
|
+
* request.querystring= but included for ubiquity.
|
|
230
234
|
*
|
|
231
235
|
* @param {String} str
|
|
232
236
|
* @api public
|
|
@@ -248,7 +252,10 @@ module.exports = {
|
|
|
248
252
|
get host() {
|
|
249
253
|
const proxy = this.app.proxy;
|
|
250
254
|
let host = proxy && this.get('X-Forwarded-Host');
|
|
251
|
-
|
|
255
|
+
if (!host) {
|
|
256
|
+
if (this.req.httpVersionMajor >= 2) host = this.get(':authority');
|
|
257
|
+
if (!host) host = this.get('Host');
|
|
258
|
+
}
|
|
252
259
|
if (!host) return '';
|
|
253
260
|
return host.split(/\s*,\s*/)[0];
|
|
254
261
|
},
|
|
@@ -278,6 +285,7 @@ module.exports = {
|
|
|
278
285
|
*/
|
|
279
286
|
|
|
280
287
|
get URL() {
|
|
288
|
+
/* istanbul ignore else */
|
|
281
289
|
if (!this.memoizedURL) {
|
|
282
290
|
const protocol = this.protocol;
|
|
283
291
|
const host = this.host;
|
|
@@ -397,11 +405,10 @@ module.exports = {
|
|
|
397
405
|
*/
|
|
398
406
|
|
|
399
407
|
get protocol() {
|
|
400
|
-
const proxy = this.app.proxy;
|
|
401
408
|
if (this.socket.encrypted) return 'https';
|
|
402
|
-
if (!proxy) return 'http';
|
|
403
|
-
const proto = this.get('X-Forwarded-Proto')
|
|
404
|
-
return proto.split(/\s*,\s*/)[0];
|
|
409
|
+
if (!this.app.proxy) return 'http';
|
|
410
|
+
const proto = this.get('X-Forwarded-Proto');
|
|
411
|
+
return proto ? proto.split(/\s*,\s*/)[0] : 'http';
|
|
405
412
|
},
|
|
406
413
|
|
|
407
414
|
/**
|
|
@@ -437,6 +444,26 @@ module.exports = {
|
|
|
437
444
|
: [];
|
|
438
445
|
},
|
|
439
446
|
|
|
447
|
+
/**
|
|
448
|
+
* Return request's remote address
|
|
449
|
+
* When `app.proxy` is `true`, parse
|
|
450
|
+
* the "X-Forwarded-For" ip address list and return the first one
|
|
451
|
+
*
|
|
452
|
+
* @return {String}
|
|
453
|
+
* @api public
|
|
454
|
+
*/
|
|
455
|
+
|
|
456
|
+
get ip() {
|
|
457
|
+
if (!this[IP]) {
|
|
458
|
+
this[IP] = this.ips[0] || this.socket.remoteAddress || '';
|
|
459
|
+
}
|
|
460
|
+
return this[IP];
|
|
461
|
+
},
|
|
462
|
+
|
|
463
|
+
set ip(_ip) {
|
|
464
|
+
this[IP] = _ip;
|
|
465
|
+
},
|
|
466
|
+
|
|
440
467
|
/**
|
|
441
468
|
* Return subdomains as an array.
|
|
442
469
|
*
|
|
@@ -463,6 +490,27 @@ module.exports = {
|
|
|
463
490
|
.slice(offset);
|
|
464
491
|
},
|
|
465
492
|
|
|
493
|
+
/**
|
|
494
|
+
* Get accept object.
|
|
495
|
+
* Lazily memoized.
|
|
496
|
+
*
|
|
497
|
+
* @return {Object}
|
|
498
|
+
* @api private
|
|
499
|
+
*/
|
|
500
|
+
get accept() {
|
|
501
|
+
return this._accept || (this._accept = accepts(this.req));
|
|
502
|
+
},
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Set accept object.
|
|
506
|
+
*
|
|
507
|
+
* @param {Object}
|
|
508
|
+
* @api private
|
|
509
|
+
*/
|
|
510
|
+
set accept(obj) {
|
|
511
|
+
return this._accept = obj;
|
|
512
|
+
},
|
|
513
|
+
|
|
466
514
|
/**
|
|
467
515
|
* Check if the given `type(s)` is acceptable, returning
|
|
468
516
|
* the best match when true, otherwise `false`, in which
|
|
@@ -620,7 +668,7 @@ module.exports = {
|
|
|
620
668
|
* // => "text/plain"
|
|
621
669
|
*
|
|
622
670
|
* this.get('Something');
|
|
623
|
-
* // =>
|
|
671
|
+
* // => ''
|
|
624
672
|
*
|
|
625
673
|
* @param {String} field
|
|
626
674
|
* @return {String}
|
|
@@ -665,3 +713,15 @@ module.exports = {
|
|
|
665
713
|
]);
|
|
666
714
|
}
|
|
667
715
|
};
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Custom inspection implementation for newer Node.js versions.
|
|
719
|
+
*
|
|
720
|
+
* @return {Object}
|
|
721
|
+
* @api public
|
|
722
|
+
*/
|
|
723
|
+
|
|
724
|
+
/* istanbul ignore else */
|
|
725
|
+
if (util.inspect.custom) {
|
|
726
|
+
module.exports[util.inspect.custom] = module.exports.inspect;
|
|
727
|
+
}
|
package/lib/response.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const contentDisposition = require('content-disposition');
|
|
9
9
|
const ensureErrorHandler = require('error-inject');
|
|
10
|
-
const getType = require('
|
|
10
|
+
const getType = require('cache-content-type');
|
|
11
11
|
const onFinish = require('on-finished');
|
|
12
12
|
const isJSON = require('koa-is-json');
|
|
13
13
|
const escape = require('escape-html');
|
|
@@ -18,6 +18,7 @@ const assert = require('assert');
|
|
|
18
18
|
const extname = require('path').extname;
|
|
19
19
|
const vary = require('vary');
|
|
20
20
|
const only = require('only');
|
|
21
|
+
const util = require('util');
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Prototype.
|
|
@@ -33,7 +34,7 @@ module.exports = {
|
|
|
33
34
|
*/
|
|
34
35
|
|
|
35
36
|
get socket() {
|
|
36
|
-
return this.
|
|
37
|
+
return this.res.socket;
|
|
37
38
|
},
|
|
38
39
|
|
|
39
40
|
/**
|
|
@@ -284,9 +285,9 @@ module.exports = {
|
|
|
284
285
|
* @api public
|
|
285
286
|
*/
|
|
286
287
|
|
|
287
|
-
attachment(filename) {
|
|
288
|
+
attachment(filename, options) {
|
|
288
289
|
if (filename) this.type = extname(filename);
|
|
289
|
-
this.set('Content-Disposition', contentDisposition(filename));
|
|
290
|
+
this.set('Content-Disposition', contentDisposition(filename, options));
|
|
290
291
|
},
|
|
291
292
|
|
|
292
293
|
/**
|
|
@@ -438,8 +439,8 @@ module.exports = {
|
|
|
438
439
|
if (this.headerSent) return;
|
|
439
440
|
|
|
440
441
|
if (2 == arguments.length) {
|
|
441
|
-
if (Array.isArray(val)) val = val.map(String);
|
|
442
|
-
else val = String(val);
|
|
442
|
+
if (Array.isArray(val)) val = val.map(v => typeof v === 'string' ? v : String(v));
|
|
443
|
+
else if (typeof val !== 'string') val = String(val);
|
|
443
444
|
this.res.setHeader(field, val);
|
|
444
445
|
} else {
|
|
445
446
|
for (const key in field) {
|
|
@@ -545,3 +546,13 @@ module.exports = {
|
|
|
545
546
|
this.res.flushHeaders();
|
|
546
547
|
}
|
|
547
548
|
};
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Custom inspection implementation for newer Node.js versions.
|
|
552
|
+
*
|
|
553
|
+
* @return {Object}
|
|
554
|
+
* @api public
|
|
555
|
+
*/
|
|
556
|
+
if (util.inspect.custom) {
|
|
557
|
+
module.exports[util.inspect.custom] = module.exports.inspect;
|
|
558
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koa",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"description": "Koa web app framework",
|
|
5
5
|
"main": "lib/application.js",
|
|
6
6
|
"scripts": {
|
|
@@ -22,30 +22,30 @@
|
|
|
22
22
|
],
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"accepts": "^1.
|
|
26
|
-
"content-
|
|
27
|
-
"content-
|
|
28
|
-
"
|
|
29
|
-
"
|
|
25
|
+
"accepts": "^1.3.5",
|
|
26
|
+
"cache-content-type": "^1.0.0",
|
|
27
|
+
"content-disposition": "~0.5.2",
|
|
28
|
+
"content-type": "^1.0.4",
|
|
29
|
+
"cookies": "~0.7.1",
|
|
30
|
+
"debug": "~3.1.0",
|
|
30
31
|
"delegates": "^1.0.0",
|
|
31
|
-
"depd": "^1.1.
|
|
32
|
-
"destroy": "^1.0.
|
|
33
|
-
"error-inject": "
|
|
34
|
-
"escape-html": "
|
|
35
|
-
"fresh": "
|
|
36
|
-
"http-assert": "^1.
|
|
37
|
-
"http-errors": "^1.
|
|
38
|
-
"is-generator-function": "^1.0.
|
|
39
|
-
"koa-compose": "^4.
|
|
32
|
+
"depd": "^1.1.2",
|
|
33
|
+
"destroy": "^1.0.4",
|
|
34
|
+
"error-inject": "^1.0.0",
|
|
35
|
+
"escape-html": "^1.0.3",
|
|
36
|
+
"fresh": "~0.5.2",
|
|
37
|
+
"http-assert": "^1.3.0",
|
|
38
|
+
"http-errors": "^1.6.3",
|
|
39
|
+
"is-generator-function": "^1.0.7",
|
|
40
|
+
"koa-compose": "^4.1.0",
|
|
40
41
|
"koa-convert": "^1.2.0",
|
|
41
42
|
"koa-is-json": "^1.0.0",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"vary": "^1.0.0"
|
|
43
|
+
"on-finished": "^2.3.0",
|
|
44
|
+
"only": "~0.0.2",
|
|
45
|
+
"parseurl": "^1.3.2",
|
|
46
|
+
"statuses": "^1.5.0",
|
|
47
|
+
"type-is": "^1.6.16",
|
|
48
|
+
"vary": "^1.1.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"eslint": "^3.17.1",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"eslint-plugin-promise": "^3.5.0",
|
|
55
55
|
"eslint-plugin-standard": "^2.1.1",
|
|
56
56
|
"jest": "^20.0.0",
|
|
57
|
-
"supertest": "^3.
|
|
57
|
+
"supertest": "^3.1.0"
|
|
58
58
|
},
|
|
59
59
|
"engines": {
|
|
60
60
|
"node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4"
|