@eggjs/koa 2.19.1 → 2.20.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/dist/commonjs/application.d.ts +1 -0
- package/dist/commonjs/application.js +2 -2
- package/dist/commonjs/context.d.ts +2 -1
- package/dist/commonjs/context.js +6 -6
- package/dist/commonjs/request.d.ts +19 -8
- package/dist/commonjs/request.js +70 -58
- package/dist/commonjs/response.d.ts +1 -0
- package/dist/commonjs/response.js +3 -3
- package/dist/esm/application.d.ts +1 -0
- package/dist/esm/application.js +2 -2
- package/dist/esm/context.d.ts +2 -1
- package/dist/esm/context.js +6 -6
- package/dist/esm/request.d.ts +19 -8
- package/dist/esm/request.js +70 -58
- package/dist/esm/response.d.ts +1 -0
- package/dist/esm/response.js +2 -2
- package/dist/package.json +4 -0
- package/package.json +10 -8
- package/src/application.ts +2 -1
- package/src/context.ts +7 -5
- package/src/request.ts +89 -39
- package/src/response.ts +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eggjs/koa",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">= 18.19.0"
|
|
6
6
|
},
|
|
@@ -30,18 +30,18 @@
|
|
|
30
30
|
],
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"accepts": "^1.3.
|
|
33
|
+
"accepts": "^1.3.8",
|
|
34
34
|
"cache-content-type": "^2.0.0",
|
|
35
35
|
"content-disposition": "~0.5.4",
|
|
36
36
|
"content-type": "^1.0.5",
|
|
37
|
-
"cookies": "
|
|
37
|
+
"cookies": "^0.9.1",
|
|
38
38
|
"delegates": "^1.0.0",
|
|
39
39
|
"destroy": "^1.0.4",
|
|
40
40
|
"encodeurl": "^1.0.2",
|
|
41
41
|
"escape-html": "^1.0.3",
|
|
42
42
|
"fresh": "~0.5.2",
|
|
43
43
|
"gals": "^1.0.1",
|
|
44
|
-
"http-assert": "^1.
|
|
44
|
+
"http-assert": "^1.5.0",
|
|
45
45
|
"http-errors": "^2.0.0",
|
|
46
46
|
"is-type-of": "^2.1.0",
|
|
47
47
|
"koa-compose": "^4.1.0",
|
|
@@ -52,14 +52,18 @@
|
|
|
52
52
|
"vary": "^1.1.2"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@arethetypeswrong/cli": "^0.
|
|
55
|
+
"@arethetypeswrong/cli": "^0.17.1",
|
|
56
56
|
"@eggjs/tsconfig": "^1.3.3",
|
|
57
|
+
"@types/accepts": "^1.3.7",
|
|
58
|
+
"@types/content-disposition": "^0.5.8",
|
|
57
59
|
"@types/content-type": "^1.1.8",
|
|
60
|
+
"@types/cookies": "^0.9.0",
|
|
58
61
|
"@types/delegates": "^1.0.3",
|
|
59
62
|
"@types/destroy": "^1.0.3",
|
|
60
63
|
"@types/encodeurl": "^1.0.2",
|
|
61
64
|
"@types/escape-html": "^1.0.4",
|
|
62
65
|
"@types/fresh": "^0.5.2",
|
|
66
|
+
"@types/http-assert": "^1.5.6",
|
|
63
67
|
"@types/http-errors": "^2.0.4",
|
|
64
68
|
"@types/koa-compose": "^3.2.8",
|
|
65
69
|
"@types/mocha": "^10.0.1",
|
|
@@ -76,7 +80,7 @@
|
|
|
76
80
|
"mm": "^3.3.0",
|
|
77
81
|
"supertest": "^3.1.0",
|
|
78
82
|
"tsd": "^0.31.0",
|
|
79
|
-
"tshy": "
|
|
83
|
+
"tshy": "3",
|
|
80
84
|
"tshy-after": "^1.0.0",
|
|
81
85
|
"typescript": "^5.4.5"
|
|
82
86
|
},
|
|
@@ -91,12 +95,10 @@
|
|
|
91
95
|
"./package.json": "./package.json",
|
|
92
96
|
".": {
|
|
93
97
|
"import": {
|
|
94
|
-
"source": "./src/index.ts",
|
|
95
98
|
"types": "./dist/esm/index.d.ts",
|
|
96
99
|
"default": "./dist/esm/index.js"
|
|
97
100
|
},
|
|
98
101
|
"require": {
|
|
99
|
-
"source": "./src/index.ts",
|
|
100
102
|
"types": "./dist/commonjs/index.d.ts",
|
|
101
103
|
"default": "./dist/commonjs/index.js"
|
|
102
104
|
}
|
package/src/application.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { Response } from './response.js';
|
|
|
17
17
|
import type { ContextDelegation } from './context.js';
|
|
18
18
|
import type { CustomError, AnyProto } from './types.js';
|
|
19
19
|
|
|
20
|
-
const debug = debuglog('@eggjs/koa
|
|
20
|
+
const debug = debuglog('@eggjs/koa/application');
|
|
21
21
|
|
|
22
22
|
export type ProtoImplClass<T = object> = new(...args: any[]) => T;
|
|
23
23
|
export type Next = () => Promise<void>;
|
|
@@ -29,6 +29,7 @@ export type MiddlewareFunc = _MiddlewareFunc & { _name?: string };
|
|
|
29
29
|
* Inherits from `Emitter.prototype`.
|
|
30
30
|
*/
|
|
31
31
|
export class Application extends Emitter {
|
|
32
|
+
[key: symbol]: unknown;
|
|
32
33
|
/**
|
|
33
34
|
* Make HttpError available to consumers of the library so that consumers don't
|
|
34
35
|
* have a direct dependency upon `http-errors`
|
package/src/context.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { Response } from './response.js';
|
|
|
11
11
|
import type { CustomError, AnyProto } from './types.js';
|
|
12
12
|
|
|
13
13
|
export class Context {
|
|
14
|
+
[key: symbol]: unknown;
|
|
14
15
|
app: Application;
|
|
15
16
|
req: IncomingMessage;
|
|
16
17
|
res: ServerResponse;
|
|
@@ -201,19 +202,20 @@ export class Context {
|
|
|
201
202
|
res.end(msg);
|
|
202
203
|
}
|
|
203
204
|
|
|
204
|
-
|
|
205
|
+
protected _cookies: Cookies | undefined;
|
|
206
|
+
|
|
205
207
|
get cookies() {
|
|
206
|
-
if (!this
|
|
207
|
-
this
|
|
208
|
+
if (!this._cookies) {
|
|
209
|
+
this._cookies = new Cookies(this.req, this.res, {
|
|
208
210
|
keys: this.app.keys,
|
|
209
211
|
secure: this.request.secure,
|
|
210
212
|
});
|
|
211
213
|
}
|
|
212
|
-
return this
|
|
214
|
+
return this._cookies;
|
|
213
215
|
}
|
|
214
216
|
|
|
215
217
|
set cookies(cookies: Cookies) {
|
|
216
|
-
this
|
|
218
|
+
this._cookies = cookies;
|
|
217
219
|
}
|
|
218
220
|
}
|
|
219
221
|
|
package/src/request.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import net from 'node:net';
|
|
2
|
-
import type { Socket } from 'node:net';
|
|
1
|
+
import net, { type Socket } from 'node:net';
|
|
3
2
|
import { format as stringify } from 'node:url';
|
|
4
|
-
import qs from 'node:querystring';
|
|
3
|
+
import qs, { type ParsedUrlQuery } from 'node:querystring';
|
|
5
4
|
import util from 'node:util';
|
|
6
|
-
import type { ParsedUrlQuery } from 'node:querystring';
|
|
7
5
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
8
|
-
import accepts from 'accepts';
|
|
6
|
+
import accepts, { type Accepts } from 'accepts';
|
|
9
7
|
import contentType from 'content-type';
|
|
10
8
|
import parse from 'parseurl';
|
|
11
9
|
import typeis from 'type-is';
|
|
@@ -15,6 +13,7 @@ import type { ContextDelegation } from './context.js';
|
|
|
15
13
|
import type { Response } from './response.js';
|
|
16
14
|
|
|
17
15
|
export class Request {
|
|
16
|
+
[key: symbol]: unknown;
|
|
18
17
|
app: Application;
|
|
19
18
|
req: IncomingMessage;
|
|
20
19
|
res: ServerResponse;
|
|
@@ -134,19 +133,19 @@ export class Request {
|
|
|
134
133
|
this.url = stringify(url);
|
|
135
134
|
}
|
|
136
135
|
|
|
137
|
-
|
|
136
|
+
protected _parsedUrlQueryCache: Record<string, ParsedUrlQuery> | undefined;
|
|
138
137
|
|
|
139
138
|
/**
|
|
140
139
|
* Get parsed query string.
|
|
141
140
|
*/
|
|
142
141
|
get query() {
|
|
143
142
|
const str = this.querystring;
|
|
144
|
-
if (!this
|
|
145
|
-
this
|
|
143
|
+
if (!this._parsedUrlQueryCache) {
|
|
144
|
+
this._parsedUrlQueryCache = {};
|
|
146
145
|
}
|
|
147
|
-
let parsedUrlQuery = this
|
|
146
|
+
let parsedUrlQuery = this._parsedUrlQueryCache[str];
|
|
148
147
|
if (!parsedUrlQuery) {
|
|
149
|
-
parsedUrlQuery = this
|
|
148
|
+
parsedUrlQuery = this._parsedUrlQueryCache[str] = qs.parse(str);
|
|
150
149
|
}
|
|
151
150
|
return parsedUrlQuery;
|
|
152
151
|
}
|
|
@@ -210,10 +209,16 @@ export class Request {
|
|
|
210
209
|
const proxy = this.app.proxy;
|
|
211
210
|
let host = proxy ? this.get<string>('X-Forwarded-Host') : '';
|
|
212
211
|
if (!host) {
|
|
213
|
-
if (this.req.httpVersionMajor >= 2)
|
|
214
|
-
|
|
212
|
+
if (this.req.httpVersionMajor >= 2) {
|
|
213
|
+
host = this.get(':authority');
|
|
214
|
+
}
|
|
215
|
+
if (!host) {
|
|
216
|
+
host = this.get('Host');
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (!host) {
|
|
220
|
+
return '';
|
|
215
221
|
}
|
|
216
|
-
if (!host) return '';
|
|
217
222
|
return host.split(/\s*,\s*/, 1)[0];
|
|
218
223
|
}
|
|
219
224
|
|
|
@@ -224,27 +229,31 @@ export class Request {
|
|
|
224
229
|
*/
|
|
225
230
|
get hostname() {
|
|
226
231
|
const host = this.host;
|
|
227
|
-
if (!host)
|
|
228
|
-
|
|
232
|
+
if (!host) {
|
|
233
|
+
return '';
|
|
234
|
+
}
|
|
235
|
+
if (host[0] === '[') {
|
|
236
|
+
return this.URL.hostname || ''; // IPv6
|
|
237
|
+
}
|
|
229
238
|
return host.split(':', 1)[0];
|
|
230
239
|
}
|
|
231
240
|
|
|
232
|
-
|
|
241
|
+
protected _memoizedURL: URL | undefined;
|
|
233
242
|
|
|
234
243
|
/**
|
|
235
244
|
* Get WHATWG parsed URL.
|
|
236
245
|
* Lazily memoized.
|
|
237
246
|
*/
|
|
238
247
|
get URL() {
|
|
239
|
-
if (!this
|
|
248
|
+
if (!this._memoizedURL) {
|
|
240
249
|
const originalUrl = this.originalUrl || ''; // avoid undefined in template string
|
|
241
250
|
try {
|
|
242
|
-
this
|
|
251
|
+
this._memoizedURL = new URL(`${this.origin}${originalUrl}`);
|
|
243
252
|
} catch {
|
|
244
|
-
this
|
|
253
|
+
this._memoizedURL = Object.create(null);
|
|
245
254
|
}
|
|
246
255
|
}
|
|
247
|
-
return this
|
|
256
|
+
return this._memoizedURL!;
|
|
248
257
|
}
|
|
249
258
|
|
|
250
259
|
/**
|
|
@@ -257,7 +266,9 @@ export class Request {
|
|
|
257
266
|
const status = this.response.status;
|
|
258
267
|
|
|
259
268
|
// GET or HEAD for weak freshness validation only
|
|
260
|
-
if (method !== 'GET' && method !== 'HEAD')
|
|
269
|
+
if (method !== 'GET' && method !== 'HEAD') {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
261
272
|
|
|
262
273
|
// 2xx or 304 as per rfc2616 14.26
|
|
263
274
|
if ((status >= 200 && status < 300) || status === 304) {
|
|
@@ -308,7 +319,9 @@ export class Request {
|
|
|
308
319
|
*/
|
|
309
320
|
get length() {
|
|
310
321
|
const len = this.get<string>('Content-Length');
|
|
311
|
-
if (len === '')
|
|
322
|
+
if (len === '') {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
312
325
|
return parseInt(len);
|
|
313
326
|
}
|
|
314
327
|
|
|
@@ -321,8 +334,12 @@ export class Request {
|
|
|
321
334
|
* may be enabled.
|
|
322
335
|
*/
|
|
323
336
|
get protocol() {
|
|
324
|
-
if (this.socket.encrypted)
|
|
325
|
-
|
|
337
|
+
if (this.socket.encrypted) {
|
|
338
|
+
return 'https';
|
|
339
|
+
}
|
|
340
|
+
if (!this.app.proxy) {
|
|
341
|
+
return 'http';
|
|
342
|
+
}
|
|
326
343
|
const proto = this.get<string>('X-Forwarded-Proto');
|
|
327
344
|
return proto ? proto.split(/\s*,\s*/, 1)[0] : 'http';
|
|
328
345
|
}
|
|
@@ -356,21 +373,21 @@ export class Request {
|
|
|
356
373
|
return ips;
|
|
357
374
|
}
|
|
358
375
|
|
|
359
|
-
|
|
376
|
+
protected _ip: string;
|
|
360
377
|
/**
|
|
361
378
|
* Return request's remote address
|
|
362
379
|
* When `app.proxy` is `true`, parse
|
|
363
380
|
* the "X-Forwarded-For" ip address list and return the first one
|
|
364
381
|
*/
|
|
365
382
|
get ip() {
|
|
366
|
-
if (!this
|
|
367
|
-
this
|
|
383
|
+
if (!this._ip) {
|
|
384
|
+
this._ip = this.ips[0] || this.socket.remoteAddress || '';
|
|
368
385
|
}
|
|
369
|
-
return this
|
|
386
|
+
return this._ip;
|
|
370
387
|
}
|
|
371
388
|
|
|
372
389
|
set ip(ip: string) {
|
|
373
|
-
this
|
|
390
|
+
this._ip = ip;
|
|
374
391
|
}
|
|
375
392
|
|
|
376
393
|
/**
|
|
@@ -395,20 +412,20 @@ export class Request {
|
|
|
395
412
|
.slice(offset);
|
|
396
413
|
}
|
|
397
414
|
|
|
398
|
-
|
|
415
|
+
protected _accept: Accepts;
|
|
399
416
|
/**
|
|
400
417
|
* Get accept object.
|
|
401
418
|
* Lazily memoized.
|
|
402
419
|
*/
|
|
403
420
|
get accept() {
|
|
404
|
-
return this
|
|
421
|
+
return this._accept || (this._accept = accepts(this.req));
|
|
405
422
|
}
|
|
406
423
|
|
|
407
424
|
/**
|
|
408
425
|
* Set accept object.
|
|
409
426
|
*/
|
|
410
|
-
set accept(obj) {
|
|
411
|
-
this
|
|
427
|
+
set accept(obj: Accepts) {
|
|
428
|
+
this._accept = obj;
|
|
412
429
|
}
|
|
413
430
|
|
|
414
431
|
/**
|
|
@@ -459,8 +476,19 @@ export class Request {
|
|
|
459
476
|
*
|
|
460
477
|
* ['gzip', 'deflate']
|
|
461
478
|
*/
|
|
462
|
-
acceptsEncodings(
|
|
463
|
-
|
|
479
|
+
acceptsEncodings(): string[];
|
|
480
|
+
acceptsEncodings(encodings: string[]): string | false;
|
|
481
|
+
acceptsEncodings(...encodings: string[]): string | false;
|
|
482
|
+
acceptsEncodings(encodings?: string | string[], ...others: string[]): string[] | string | false {
|
|
483
|
+
if (!encodings) {
|
|
484
|
+
return this.accept.encodings();
|
|
485
|
+
}
|
|
486
|
+
if (Array.isArray(encodings)) {
|
|
487
|
+
encodings = [ ...encodings, ...others ];
|
|
488
|
+
} else {
|
|
489
|
+
encodings = [ encodings, ...others ];
|
|
490
|
+
}
|
|
491
|
+
return this.accept.encodings(...encodings);
|
|
464
492
|
}
|
|
465
493
|
|
|
466
494
|
/**
|
|
@@ -471,8 +499,19 @@ export class Request {
|
|
|
471
499
|
*
|
|
472
500
|
* ['utf-8', 'utf-7', 'iso-8859-1']
|
|
473
501
|
*/
|
|
474
|
-
acceptsCharsets(
|
|
475
|
-
|
|
502
|
+
acceptsCharsets(): string[];
|
|
503
|
+
acceptsCharsets(charsets: string[]): string | false;
|
|
504
|
+
acceptsCharsets(...charsets: string[]): string | false;
|
|
505
|
+
acceptsCharsets(charsets?: string | string[], ...others: string[]): string[] | string | false {
|
|
506
|
+
if (!charsets) {
|
|
507
|
+
return this.accept.charsets();
|
|
508
|
+
}
|
|
509
|
+
if (Array.isArray(charsets)) {
|
|
510
|
+
charsets = [ ...charsets, ...others ];
|
|
511
|
+
} else {
|
|
512
|
+
charsets = [ charsets, ...others ];
|
|
513
|
+
}
|
|
514
|
+
return this.accept.charsets(...charsets);
|
|
476
515
|
}
|
|
477
516
|
|
|
478
517
|
/**
|
|
@@ -483,8 +522,19 @@ export class Request {
|
|
|
483
522
|
*
|
|
484
523
|
* ['es', 'pt', 'en']
|
|
485
524
|
*/
|
|
486
|
-
acceptsLanguages(
|
|
487
|
-
|
|
525
|
+
acceptsLanguages(): string[];
|
|
526
|
+
acceptsLanguages(languages: string[]): string | false;
|
|
527
|
+
acceptsLanguages(...languages: string[]): string | false;
|
|
528
|
+
acceptsLanguages(languages?: string | string[], ...others: string[]): string | string[] | false {
|
|
529
|
+
if (!languages) {
|
|
530
|
+
return this.accept.languages();
|
|
531
|
+
}
|
|
532
|
+
if (Array.isArray(languages)) {
|
|
533
|
+
languages = [ ...languages, ...others ];
|
|
534
|
+
} else {
|
|
535
|
+
languages = [ languages, ...others ];
|
|
536
|
+
}
|
|
537
|
+
return this.accept.languages(...languages);
|
|
488
538
|
}
|
|
489
539
|
|
|
490
540
|
/**
|
package/src/response.ts
CHANGED
|
@@ -4,7 +4,7 @@ import util from 'node:util';
|
|
|
4
4
|
import Stream from 'node:stream';
|
|
5
5
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
6
6
|
import contentDisposition from 'content-disposition';
|
|
7
|
-
import getType from 'cache-content-type';
|
|
7
|
+
import { getType } from 'cache-content-type';
|
|
8
8
|
import onFinish from 'on-finished';
|
|
9
9
|
import escape from 'escape-html';
|
|
10
10
|
import { is as typeis } from 'type-is';
|
|
@@ -17,6 +17,7 @@ import type { ContextDelegation } from './context.js';
|
|
|
17
17
|
import type { Request } from './request.js';
|
|
18
18
|
|
|
19
19
|
export class Response {
|
|
20
|
+
[key: symbol]: unknown;
|
|
20
21
|
app: Application;
|
|
21
22
|
req: IncomingMessage;
|
|
22
23
|
res: ServerResponse;
|