@eggjs/koa 2.17.0 → 2.18.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.
@@ -0,0 +1,522 @@
1
+ import net from 'node:net';
2
+ import { format as stringify } from 'node:url';
3
+ import qs from 'node:querystring';
4
+ import util from 'node:util';
5
+ import accepts from 'accepts';
6
+ import contentType from 'content-type';
7
+ import parse from 'parseurl';
8
+ import typeis from 'type-is';
9
+ import fresh from 'fresh';
10
+ export default class Request {
11
+ app;
12
+ req;
13
+ res;
14
+ ctx;
15
+ response;
16
+ originalUrl;
17
+ constructor(app, ctx, req, res) {
18
+ this.app = app;
19
+ this.req = req;
20
+ this.res = res;
21
+ this.ctx = ctx;
22
+ this.originalUrl = req.url;
23
+ }
24
+ /**
25
+ * Return request header.
26
+ */
27
+ get header() {
28
+ return this.req.headers;
29
+ }
30
+ /**
31
+ * Set request header.
32
+ */
33
+ set header(val) {
34
+ this.req.headers = val;
35
+ }
36
+ /**
37
+ * Return request header, alias as request.header
38
+ */
39
+ get headers() {
40
+ return this.req.headers;
41
+ }
42
+ /**
43
+ * Set request header, alias as request.header
44
+ */
45
+ set headers(val) {
46
+ this.req.headers = val;
47
+ }
48
+ /**
49
+ * Get request URL.
50
+ */
51
+ get url() {
52
+ return this.req.url;
53
+ }
54
+ /**
55
+ * Set request URL.
56
+ */
57
+ set url(val) {
58
+ this.req.url = val;
59
+ }
60
+ /**
61
+ * Get origin of URL.
62
+ */
63
+ get origin() {
64
+ return `${this.protocol}://${this.host}`;
65
+ }
66
+ /**
67
+ * Get full request URL.
68
+ */
69
+ get href() {
70
+ // support: `GET http://example.com/foo`
71
+ if (/^https?:\/\//i.test(this.originalUrl))
72
+ return this.originalUrl;
73
+ return this.origin + this.originalUrl;
74
+ }
75
+ /**
76
+ * Get request method.
77
+ */
78
+ get method() {
79
+ return this.req.method;
80
+ }
81
+ /**
82
+ * Set request method.
83
+ */
84
+ set method(val) {
85
+ this.req.method = val;
86
+ }
87
+ /**
88
+ * Get request pathname.
89
+ */
90
+ get path() {
91
+ return parse(this.req).pathname;
92
+ }
93
+ /**
94
+ * Set pathname, retaining the query string when present.
95
+ */
96
+ set path(path) {
97
+ const url = parse(this.req);
98
+ if (url.pathname === path)
99
+ return;
100
+ url.pathname = path;
101
+ url.path = null;
102
+ this.url = stringify(url);
103
+ }
104
+ #parsedUrlQueryCache;
105
+ /**
106
+ * Get parsed query string.
107
+ */
108
+ get query() {
109
+ const str = this.querystring;
110
+ if (!this.#parsedUrlQueryCache) {
111
+ this.#parsedUrlQueryCache = {};
112
+ }
113
+ let parsedUrlQuery = this.#parsedUrlQueryCache[str];
114
+ if (!parsedUrlQuery) {
115
+ parsedUrlQuery = this.#parsedUrlQueryCache[str] = qs.parse(str);
116
+ }
117
+ return parsedUrlQuery;
118
+ }
119
+ /**
120
+ * Set query string as an object.
121
+ */
122
+ set query(obj) {
123
+ this.querystring = qs.stringify(obj);
124
+ }
125
+ /**
126
+ * Get query string.
127
+ */
128
+ get querystring() {
129
+ if (!this.req)
130
+ return '';
131
+ return parse(this.req).query || '';
132
+ }
133
+ /**
134
+ * Set query string.
135
+ */
136
+ set querystring(str) {
137
+ const url = parse(this.req);
138
+ if (url.search === `?${str}`)
139
+ return;
140
+ url.search = str;
141
+ url.path = null;
142
+ this.url = stringify(url);
143
+ }
144
+ /**
145
+ * Get the search string. Same as the query string
146
+ * except it includes the leading ?.
147
+ */
148
+ get search() {
149
+ if (!this.querystring)
150
+ return '';
151
+ return `?${this.querystring}`;
152
+ }
153
+ /**
154
+ * Set the search string. Same as
155
+ * request.querystring= but included for ubiquity.
156
+ */
157
+ set search(str) {
158
+ this.querystring = str;
159
+ }
160
+ /**
161
+ * Parse the "Host" header field host
162
+ * and support X-Forwarded-Host when a
163
+ * proxy is enabled.
164
+ * return `hostname:port` format
165
+ */
166
+ get host() {
167
+ const proxy = this.app.proxy;
168
+ let host = proxy ? this.get('X-Forwarded-Host') : '';
169
+ if (!host) {
170
+ if (this.req.httpVersionMajor >= 2)
171
+ host = this.get(':authority');
172
+ if (!host)
173
+ host = this.get('Host');
174
+ }
175
+ if (!host)
176
+ return '';
177
+ return host.split(/\s*,\s*/, 1)[0];
178
+ }
179
+ /**
180
+ * Parse the "Host" header field hostname
181
+ * and support X-Forwarded-Host when a
182
+ * proxy is enabled.
183
+ */
184
+ get hostname() {
185
+ const host = this.host;
186
+ if (!host)
187
+ return '';
188
+ if (host[0] === '[')
189
+ return this.URL.hostname || ''; // IPv6
190
+ return host.split(':', 1)[0];
191
+ }
192
+ #memoizedURL;
193
+ /**
194
+ * Get WHATWG parsed URL.
195
+ * Lazily memoized.
196
+ */
197
+ get URL() {
198
+ if (!this.#memoizedURL) {
199
+ const originalUrl = this.originalUrl || ''; // avoid undefined in template string
200
+ try {
201
+ this.#memoizedURL = new URL(`${this.origin}${originalUrl}`);
202
+ }
203
+ catch {
204
+ this.#memoizedURL = Object.create(null);
205
+ }
206
+ }
207
+ return this.#memoizedURL;
208
+ }
209
+ /**
210
+ * Check if the request is fresh, aka
211
+ * Last-Modified and/or the ETag
212
+ * still match.
213
+ */
214
+ get fresh() {
215
+ const method = this.method;
216
+ const status = this.response.status;
217
+ // GET or HEAD for weak freshness validation only
218
+ if (method !== 'GET' && method !== 'HEAD')
219
+ return false;
220
+ // 2xx or 304 as per rfc2616 14.26
221
+ if ((status >= 200 && status < 300) || status === 304) {
222
+ return fresh(this.header, this.response.header);
223
+ }
224
+ return false;
225
+ }
226
+ /**
227
+ * Check if the request is stale, aka
228
+ * "Last-Modified" and / or the "ETag" for the
229
+ * resource has changed.
230
+ */
231
+ get stale() {
232
+ return !this.fresh;
233
+ }
234
+ /**
235
+ * Check if the request is idempotent.
236
+ */
237
+ get idempotent() {
238
+ const methods = ['GET', 'HEAD', 'PUT', 'DELETE', 'OPTIONS', 'TRACE'];
239
+ return methods.includes(this.method);
240
+ }
241
+ /**
242
+ * Return the request socket.
243
+ */
244
+ get socket() {
245
+ return this.req.socket;
246
+ }
247
+ /**
248
+ * Get the charset when present or undefined.
249
+ */
250
+ get charset() {
251
+ try {
252
+ const { parameters } = contentType.parse(this.req);
253
+ return parameters.charset || '';
254
+ }
255
+ catch {
256
+ return '';
257
+ }
258
+ }
259
+ /**
260
+ * Return parsed Content-Length when present.
261
+ */
262
+ get length() {
263
+ const len = this.get('Content-Length');
264
+ if (len === '')
265
+ return;
266
+ return parseInt(len);
267
+ }
268
+ /**
269
+ * Return the protocol string "http" or "https"
270
+ * when requested with TLS. When the proxy setting
271
+ * is enabled the "X-Forwarded-Proto" header
272
+ * field will be trusted. If you're running behind
273
+ * a reverse proxy that supplies https for you this
274
+ * may be enabled.
275
+ */
276
+ get protocol() {
277
+ if (this.socket.encrypted)
278
+ return 'https';
279
+ if (!this.app.proxy)
280
+ return 'http';
281
+ const proto = this.get('X-Forwarded-Proto');
282
+ return proto ? proto.split(/\s*,\s*/, 1)[0] : 'http';
283
+ }
284
+ /**
285
+ * Shorthand for:
286
+ *
287
+ * this.protocol == 'https'
288
+ */
289
+ get secure() {
290
+ return this.protocol === 'https';
291
+ }
292
+ /**
293
+ * When `app.proxy` is `true`, parse
294
+ * the "X-Forwarded-For" ip address list.
295
+ *
296
+ * For example if the value was "client, proxy1, proxy2"
297
+ * you would receive the array `["client", "proxy1", "proxy2"]`
298
+ * where "proxy2" is the furthest down-stream.
299
+ */
300
+ get ips() {
301
+ const proxy = this.app.proxy;
302
+ const val = this.get(this.app.proxyIpHeader);
303
+ let ips = proxy && val
304
+ ? val.split(/\s*,\s*/)
305
+ : [];
306
+ if (this.app.maxIpsCount > 0) {
307
+ ips = ips.slice(-this.app.maxIpsCount);
308
+ }
309
+ return ips;
310
+ }
311
+ #ip;
312
+ /**
313
+ * Return request's remote address
314
+ * When `app.proxy` is `true`, parse
315
+ * the "X-Forwarded-For" ip address list and return the first one
316
+ */
317
+ get ip() {
318
+ if (!this.#ip) {
319
+ this.#ip = this.ips[0] || this.socket.remoteAddress || '';
320
+ }
321
+ return this.#ip;
322
+ }
323
+ set ip(ip) {
324
+ this.#ip = ip;
325
+ }
326
+ /**
327
+ * Return subdomains as an array.
328
+ *
329
+ * Subdomains are the dot-separated parts of the host before the main domain
330
+ * of the app. By default, the domain of the app is assumed to be the last two
331
+ * parts of the host. This can be changed by setting `app.subdomainOffset`.
332
+ *
333
+ * For example, if the domain is "tobi.ferrets.example.com":
334
+ * If `app.subdomainOffset` is not set, this.subdomains is
335
+ * `["ferrets", "tobi"]`.
336
+ * If `app.subdomainOffset` is 3, this.subdomains is `["tobi"]`.
337
+ */
338
+ get subdomains() {
339
+ const offset = this.app.subdomainOffset;
340
+ const hostname = this.hostname;
341
+ if (net.isIP(hostname))
342
+ return [];
343
+ return hostname
344
+ .split('.')
345
+ .reverse()
346
+ .slice(offset);
347
+ }
348
+ #accept;
349
+ /**
350
+ * Get accept object.
351
+ * Lazily memoized.
352
+ */
353
+ get accept() {
354
+ return this.#accept || (this.#accept = accepts(this.req));
355
+ }
356
+ /**
357
+ * Set accept object.
358
+ */
359
+ set accept(obj) {
360
+ this.#accept = obj;
361
+ }
362
+ /**
363
+ * Check if the given `type(s)` is acceptable, returning
364
+ * the best match when true, otherwise `false`, in which
365
+ * case you should respond with 406 "Not Acceptable".
366
+ *
367
+ * The `type` value may be a single mime type string
368
+ * such as "application/json", the extension name
369
+ * such as "json" or an array `["json", "html", "text/plain"]`. When a list
370
+ * or array is given the _best_ match, if any is returned.
371
+ *
372
+ * Examples:
373
+ *
374
+ * // Accept: text/html
375
+ * this.accepts('html');
376
+ * // => "html"
377
+ *
378
+ * // Accept: text/*, application/json
379
+ * this.accepts('html');
380
+ * // => "html"
381
+ * this.accepts('text/html');
382
+ * // => "text/html"
383
+ * this.accepts('json', 'text');
384
+ * // => "json"
385
+ * this.accepts('application/json');
386
+ * // => "application/json"
387
+ *
388
+ * // Accept: text/*, application/json
389
+ * this.accepts('image/png');
390
+ * this.accepts('png');
391
+ * // => false
392
+ *
393
+ * // Accept: text/*;q=.5, application/json
394
+ * this.accepts(['html', 'json']);
395
+ * this.accepts('html', 'json');
396
+ * // => "json"
397
+ */
398
+ accepts(...args) {
399
+ return this.accept.types(...args);
400
+ }
401
+ /**
402
+ * Return accepted encodings or best fit based on `encodings`.
403
+ *
404
+ * Given `Accept-Encoding: gzip, deflate`
405
+ * an array sorted by quality is returned:
406
+ *
407
+ * ['gzip', 'deflate']
408
+ */
409
+ acceptsEncodings(...args) {
410
+ return this.accept.encodings(...args);
411
+ }
412
+ /**
413
+ * Return accepted charsets or best fit based on `charsets`.
414
+ *
415
+ * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5`
416
+ * an array sorted by quality is returned:
417
+ *
418
+ * ['utf-8', 'utf-7', 'iso-8859-1']
419
+ */
420
+ acceptsCharsets(...args) {
421
+ return this.accept.charsets(...args);
422
+ }
423
+ /**
424
+ * Return accepted languages or best fit based on `langs`.
425
+ *
426
+ * Given `Accept-Language: en;q=0.8, es, pt`
427
+ * an array sorted by quality is returned:
428
+ *
429
+ * ['es', 'pt', 'en']
430
+ */
431
+ acceptsLanguages(...args) {
432
+ return this.accept.languages(...args);
433
+ }
434
+ /**
435
+ * Check if the incoming request contains the "Content-Type"
436
+ * header field and if it contains any of the given mime `type`s.
437
+ * If there is no request body, `null` is returned.
438
+ * If there is no content type, `false` is returned.
439
+ * Otherwise, it returns the first `type` that matches.
440
+ *
441
+ * Examples:
442
+ *
443
+ * // With Content-Type: text/html; charset=utf-8
444
+ * this.is('html'); // => 'html'
445
+ * this.is('text/html'); // => 'text/html'
446
+ * this.is('text/*', 'application/json'); // => 'text/html'
447
+ *
448
+ * // When Content-Type is application/json
449
+ * this.is('json', 'urlencoded'); // => 'json'
450
+ * this.is('application/json'); // => 'application/json'
451
+ * this.is('html', 'application/*'); // => 'application/json'
452
+ *
453
+ * this.is('html'); // => false
454
+ */
455
+ is(type, ...types) {
456
+ const testTypes = Array.isArray(type) ? type :
457
+ (type ? [type] : []);
458
+ return typeis(this.req, [...testTypes, ...types]);
459
+ }
460
+ /**
461
+ * Return the request mime type void of
462
+ * parameters such as "charset".
463
+ */
464
+ get type() {
465
+ const type = this.get('Content-Type');
466
+ if (!type)
467
+ return '';
468
+ return type.split(';')[0];
469
+ }
470
+ /**
471
+ * Return request header.
472
+ *
473
+ * The `Referrer` header field is special-cased,
474
+ * both `Referrer` and `Referer` are interchangeable.
475
+ *
476
+ * Examples:
477
+ *
478
+ * this.get('Content-Type');
479
+ * // => "text/plain"
480
+ *
481
+ * this.get('content-type');
482
+ * // => "text/plain"
483
+ *
484
+ * this.get('Something');
485
+ * // => ''
486
+ */
487
+ get(field) {
488
+ const req = this.req;
489
+ switch (field = field.toLowerCase()) {
490
+ case 'referer':
491
+ case 'referrer':
492
+ return (req.headers.referrer || req.headers.referer || '');
493
+ default:
494
+ return (req.headers[field] || '');
495
+ }
496
+ }
497
+ /**
498
+ * Inspect implementation.
499
+ */
500
+ inspect() {
501
+ if (!this.req)
502
+ return;
503
+ return this.toJSON();
504
+ }
505
+ /**
506
+ * Custom inspection implementation for newer Node.js versions.
507
+ */
508
+ [util.inspect.custom]() {
509
+ return this.inspect();
510
+ }
511
+ /**
512
+ * Return JSON representation.
513
+ */
514
+ toJSON() {
515
+ return {
516
+ method: this.method,
517
+ url: this.url,
518
+ header: this.header,
519
+ };
520
+ }
521
+ }
522
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZXF1ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sR0FBRyxNQUFNLFVBQVUsQ0FBQztBQUUzQixPQUFPLEVBQUUsTUFBTSxJQUFJLFNBQVMsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUMvQyxPQUFPLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNsQyxPQUFPLElBQUksTUFBTSxXQUFXLENBQUM7QUFHN0IsT0FBTyxPQUFPLE1BQU0sU0FBUyxDQUFDO0FBQzlCLE9BQU8sV0FBVyxNQUFNLGNBQWMsQ0FBQztBQUN2QyxPQUFPLEtBQUssTUFBTSxVQUFVLENBQUM7QUFDN0IsT0FBTyxNQUFNLE1BQU0sU0FBUyxDQUFDO0FBQzdCLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUsxQixNQUFNLENBQUMsT0FBTyxPQUFPLE9BQU87SUFDMUIsR0FBRyxDQUFjO0lBQ2pCLEdBQUcsQ0FBa0I7SUFDckIsR0FBRyxDQUFpQjtJQUNwQixHQUFHLENBQVU7SUFDYixRQUFRLENBQVc7SUFDbkIsV0FBVyxDQUFTO0lBRXBCLFlBQVksR0FBZ0IsRUFBRSxHQUFZLEVBQUUsR0FBb0IsRUFBRSxHQUFtQjtRQUNuRixJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNmLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO1FBQ2YsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDZixJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNmLElBQUksQ0FBQyxXQUFXLEdBQUcsR0FBRyxDQUFDLEdBQUksQ0FBQztJQUM5QixDQUFDO0lBRUQ7O09BRUc7SUFFSCxJQUFJLE1BQU07UUFDUixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDO0lBQzFCLENBQUM7SUFFRDs7T0FFRztJQUVILElBQUksTUFBTSxDQUFDLEdBQUc7UUFDWixJ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