@adonisjs/http-server 6.8.2-9 → 7.0.0-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/build/chunk-XX72ATFY.js +4388 -0
- package/build/factories/main.d.ts +149 -6
- package/build/factories/main.js +331 -14
- package/build/index.d.ts +272 -14
- package/build/index.js +308 -22
- package/build/{src/server/main.d.ts → main-29eaaee4.d.ts} +12 -17
- package/build/main-e5b46c83.d.ts +2210 -0
- package/build/src/types/main.d.ts +14 -7
- package/build/src/types/main.js +0 -15
- package/package.json +62 -53
- package/build/factories/http_context.d.ts +0 -25
- package/build/factories/http_context.js +0 -51
- package/build/factories/http_server.d.ts +0 -8
- package/build/factories/http_server.js +0 -26
- package/build/factories/qs_parser_factory.d.ts +0 -20
- package/build/factories/qs_parser_factory.js +0 -44
- package/build/factories/request.d.ts +0 -29
- package/build/factories/request.js +0 -73
- package/build/factories/response.d.ts +0 -29
- package/build/factories/response.js +0 -77
- package/build/factories/router.d.ts +0 -23
- package/build/factories/router.js +0 -45
- package/build/factories/server_factory.d.ts +0 -29
- package/build/factories/server_factory.js +0 -65
- package/build/src/cookies/client.d.ts +0 -37
- package/build/src/cookies/client.js +0 -84
- package/build/src/cookies/drivers/encrypted.d.ts +0 -16
- package/build/src/cookies/drivers/encrypted.js +0 -36
- package/build/src/cookies/drivers/plain.d.ts +0 -15
- package/build/src/cookies/drivers/plain.js +0 -33
- package/build/src/cookies/drivers/signed.d.ts +0 -16
- package/build/src/cookies/drivers/signed.js +0 -36
- package/build/src/cookies/parser.d.ts +0 -37
- package/build/src/cookies/parser.js +0 -167
- package/build/src/cookies/serializer.d.ts +0 -33
- package/build/src/cookies/serializer.js +0 -79
- package/build/src/debug.d.ts +0 -3
- package/build/src/debug.js +0 -10
- package/build/src/define_config.d.ts +0 -5
- package/build/src/define_config.js +0 -51
- package/build/src/define_middleware.d.ts +0 -11
- package/build/src/define_middleware.js +0 -35
- package/build/src/exception_handler.d.ts +0 -112
- package/build/src/exception_handler.js +0 -303
- package/build/src/exceptions.d.ts +0 -84
- package/build/src/exceptions.js +0 -38
- package/build/src/helpers.d.ts +0 -23
- package/build/src/helpers.js +0 -84
- package/build/src/http_context/local_storage.d.ts +0 -12
- package/build/src/http_context/local_storage.js +0 -39
- package/build/src/http_context/main.d.ts +0 -58
- package/build/src/http_context/main.js +0 -105
- package/build/src/qs.d.ts +0 -11
- package/build/src/qs.js +0 -25
- package/build/src/redirect.d.ts +0 -42
- package/build/src/redirect.js +0 -140
- package/build/src/request.d.ts +0 -565
- package/build/src/request.js +0 -865
- package/build/src/response.d.ts +0 -540
- package/build/src/response.js +0 -1208
- package/build/src/router/brisk.d.ts +0 -42
- package/build/src/router/brisk.js +0 -85
- package/build/src/router/executor.d.ts +0 -8
- package/build/src/router/executor.js +0 -29
- package/build/src/router/factories/use_return_value.d.ts +0 -6
- package/build/src/router/factories/use_return_value.js +0 -22
- package/build/src/router/group.d.ts +0 -65
- package/build/src/router/group.js +0 -207
- package/build/src/router/lookup_store/main.d.ts +0 -49
- package/build/src/router/lookup_store/main.js +0 -86
- package/build/src/router/lookup_store/route_finder.d.ts +0 -21
- package/build/src/router/lookup_store/route_finder.js +0 -49
- package/build/src/router/lookup_store/url_builder.d.ts +0 -52
- package/build/src/router/lookup_store/url_builder.js +0 -209
- package/build/src/router/main.d.ts +0 -128
- package/build/src/router/main.js +0 -316
- package/build/src/router/matchers.d.ts +0 -27
- package/build/src/router/matchers.js +0 -36
- package/build/src/router/parser.d.ts +0 -5
- package/build/src/router/parser.js +0 -17
- package/build/src/router/resource.d.ts +0 -54
- package/build/src/router/resource.js +0 -216
- package/build/src/router/route.d.ts +0 -92
- package/build/src/router/route.js +0 -293
- package/build/src/router/store.d.ts +0 -66
- package/build/src/router/store.js +0 -195
- package/build/src/server/factories/final_handler.d.ts +0 -9
- package/build/src/server/factories/final_handler.js +0 -30
- package/build/src/server/factories/middleware_handler.d.ts +0 -8
- package/build/src/server/factories/middleware_handler.js +0 -16
- package/build/src/server/factories/write_response.d.ts +0 -6
- package/build/src/server/factories/write_response.js +0 -24
- package/build/src/server/main.js +0 -283
- package/build/src/types/base.d.ts +0 -19
- package/build/src/types/base.js +0 -9
- package/build/src/types/middleware.d.ts +0 -35
- package/build/src/types/middleware.js +0 -9
- package/build/src/types/qs.d.ts +0 -68
- package/build/src/types/qs.js +0 -9
- package/build/src/types/request.d.ts +0 -39
- package/build/src/types/request.js +0 -9
- package/build/src/types/response.d.ts +0 -45
- package/build/src/types/response.js +0 -9
- package/build/src/types/route.d.ts +0 -165
- package/build/src/types/route.js +0 -9
- package/build/src/types/server.d.ts +0 -72
- package/build/src/types/server.js +0 -9
package/build/src/response.js
DELETED
|
@@ -1,1208 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @adonisjs/http-server
|
|
3
|
-
*
|
|
4
|
-
* (c) AdonisJS
|
|
5
|
-
*
|
|
6
|
-
* For the full copyright and license information, please view the LICENSE
|
|
7
|
-
* file that was distributed with this source code.
|
|
8
|
-
*/
|
|
9
|
-
import etag from 'etag';
|
|
10
|
-
import vary from 'vary';
|
|
11
|
-
import fresh from 'fresh';
|
|
12
|
-
import mime from 'mime-types';
|
|
13
|
-
import destroy from 'destroy';
|
|
14
|
-
import { extname } from 'node:path';
|
|
15
|
-
import onFinished from 'on-finished';
|
|
16
|
-
import json from '@poppinss/utils/json';
|
|
17
|
-
import Macroable from '@poppinss/macroable';
|
|
18
|
-
import { createReadStream } from 'node:fs';
|
|
19
|
-
import { stat } from 'node:fs/promises';
|
|
20
|
-
import { RuntimeException } from '@poppinss/utils';
|
|
21
|
-
import contentDisposition from 'content-disposition';
|
|
22
|
-
import { Redirect } from './redirect.js';
|
|
23
|
-
import { CookieSerializer } from './cookies/serializer.js';
|
|
24
|
-
import { E_HTTP_REQUEST_ABORTED } from './exceptions.js';
|
|
25
|
-
const CACHEABLE_HTTP_METHODS = ['GET', 'HEAD'];
|
|
26
|
-
/**
|
|
27
|
-
* The response is a wrapper over [ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse)
|
|
28
|
-
* streamlining the process of writing response body and automatically setting up appropriate headers.
|
|
29
|
-
*/
|
|
30
|
-
export class Response extends Macroable {
|
|
31
|
-
request;
|
|
32
|
-
response;
|
|
33
|
-
/**
|
|
34
|
-
* Query string parser
|
|
35
|
-
*/
|
|
36
|
-
#qs;
|
|
37
|
-
/**
|
|
38
|
-
* Outgoing headers
|
|
39
|
-
*/
|
|
40
|
-
#headers = {};
|
|
41
|
-
/**
|
|
42
|
-
* Has explicit status been set
|
|
43
|
-
*/
|
|
44
|
-
#hasExplicitStatus = false;
|
|
45
|
-
/**
|
|
46
|
-
* Cookies serializer to serialize the outgoing cookies
|
|
47
|
-
*/
|
|
48
|
-
#cookieSerializer;
|
|
49
|
-
/**
|
|
50
|
-
* Router is used to make the redirect URLs from routes
|
|
51
|
-
*/
|
|
52
|
-
#router;
|
|
53
|
-
/**
|
|
54
|
-
* Response config
|
|
55
|
-
*/
|
|
56
|
-
#config;
|
|
57
|
-
/**
|
|
58
|
-
* Does response has body set that will written to the
|
|
59
|
-
* response socket at the end of the request
|
|
60
|
-
*/
|
|
61
|
-
get hasLazyBody() {
|
|
62
|
-
return !!(this.lazyBody.content || this.lazyBody.fileToStream || this.lazyBody.stream);
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Find if the response has non-stream content
|
|
66
|
-
*/
|
|
67
|
-
get hasContent() {
|
|
68
|
-
return !!this.lazyBody.content;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Returns true when response body is set using "response.stream"
|
|
72
|
-
* method
|
|
73
|
-
*/
|
|
74
|
-
get hasStream() {
|
|
75
|
-
return !!this.lazyBody.stream;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Returns true when response body is set using "response.download"
|
|
79
|
-
* or "response.attachment" methods
|
|
80
|
-
*/
|
|
81
|
-
get hasFileToStream() {
|
|
82
|
-
return !!this.lazyBody.fileToStream;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Returns the response content. Check if the response
|
|
86
|
-
* has content using the "hasContent" method
|
|
87
|
-
*/
|
|
88
|
-
get content() {
|
|
89
|
-
return this.lazyBody.content;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Returns reference to the stream set using "response.stream"
|
|
93
|
-
* method
|
|
94
|
-
*/
|
|
95
|
-
get outgoingStream() {
|
|
96
|
-
return this.lazyBody.stream?.[0];
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Returns reference to the file path set using "response.stream"
|
|
100
|
-
* method.
|
|
101
|
-
*/
|
|
102
|
-
get fileToStream() {
|
|
103
|
-
return this.lazyBody.fileToStream
|
|
104
|
-
? {
|
|
105
|
-
path: this.lazyBody.fileToStream[0],
|
|
106
|
-
generateEtag: this.lazyBody.fileToStream[1],
|
|
107
|
-
}
|
|
108
|
-
: undefined;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Lazy body is used to set the response body. However, do not
|
|
112
|
-
* write it on the socket immediately unless `response.finish`
|
|
113
|
-
* is called.
|
|
114
|
-
*/
|
|
115
|
-
lazyBody = {};
|
|
116
|
-
/**
|
|
117
|
-
* The ctx will be set by the context itself. It creates a circular
|
|
118
|
-
* reference
|
|
119
|
-
*/
|
|
120
|
-
ctx;
|
|
121
|
-
constructor(request, response, encryption, config, router, qs) {
|
|
122
|
-
super();
|
|
123
|
-
this.request = request;
|
|
124
|
-
this.response = response;
|
|
125
|
-
this.#qs = qs;
|
|
126
|
-
this.#config = config;
|
|
127
|
-
this.#router = router;
|
|
128
|
-
this.#cookieSerializer = new CookieSerializer(encryption);
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Returns a boolean telling if response is finished or not.
|
|
132
|
-
* Any more attempts to update headers or body will result
|
|
133
|
-
* in raised exceptions.
|
|
134
|
-
*/
|
|
135
|
-
get finished() {
|
|
136
|
-
return this.response.writableFinished;
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Returns a boolean telling if response headers has been sent or not.
|
|
140
|
-
* Any more attempts to update headers will result in raised
|
|
141
|
-
* exceptions.
|
|
142
|
-
*/
|
|
143
|
-
get headersSent() {
|
|
144
|
-
return this.response.headersSent;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Returns a boolean telling if response headers and body is written
|
|
148
|
-
* or not. When value is `true`, you can feel free to write headers
|
|
149
|
-
* and body.
|
|
150
|
-
*/
|
|
151
|
-
get isPending() {
|
|
152
|
-
return !this.headersSent && !this.finished;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Normalizes header value to a string or an array of string
|
|
156
|
-
*/
|
|
157
|
-
#castHeaderValue(value) {
|
|
158
|
-
return Array.isArray(value) ? value.map(String) : String(value);
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Ends the response by flushing headers and writing body
|
|
162
|
-
*/
|
|
163
|
-
#endResponse(body, statusCode) {
|
|
164
|
-
this.writeHead(statusCode);
|
|
165
|
-
// avoid ArgumentsAdaptorTrampoline from V8 (inspired by fastify)
|
|
166
|
-
const res = this.response;
|
|
167
|
-
res.end(body, null, null);
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Returns type for the content body. Only following types are allowed
|
|
171
|
-
*
|
|
172
|
-
* - Dates
|
|
173
|
-
* - Arrays
|
|
174
|
-
* - Booleans
|
|
175
|
-
* - Objects
|
|
176
|
-
* - Strings
|
|
177
|
-
* - Buffer
|
|
178
|
-
*/
|
|
179
|
-
#getDataType(content) {
|
|
180
|
-
if (Buffer.isBuffer(content)) {
|
|
181
|
-
return 'buffer';
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Date instance
|
|
185
|
-
*/
|
|
186
|
-
if (content instanceof Date) {
|
|
187
|
-
return 'date';
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Regular expression
|
|
191
|
-
*/
|
|
192
|
-
if (content instanceof RegExp) {
|
|
193
|
-
return 'regexp';
|
|
194
|
-
}
|
|
195
|
-
const dataType = typeof content;
|
|
196
|
-
if (dataType === 'number' ||
|
|
197
|
-
dataType === 'boolean' ||
|
|
198
|
-
dataType === 'string' ||
|
|
199
|
-
dataType === 'bigint') {
|
|
200
|
-
return dataType;
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Object
|
|
204
|
-
*/
|
|
205
|
-
if (dataType === 'object') {
|
|
206
|
-
return 'object';
|
|
207
|
-
}
|
|
208
|
-
throw new RuntimeException(`Cannot serialize "${dataType}" to HTTP response`);
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Writes the body with appropriate response headers. Etag header is set
|
|
212
|
-
* when `generateEtag` is set to `true`.
|
|
213
|
-
*
|
|
214
|
-
* Empty body results in `204`.
|
|
215
|
-
*/
|
|
216
|
-
writeBody(content, generateEtag, jsonpCallbackName) {
|
|
217
|
-
const hasEmptyBody = content === null || content === undefined || content === '';
|
|
218
|
-
/**
|
|
219
|
-
* Set status to "204" when body is empty. The `safeStatus` method only
|
|
220
|
-
* sets the status when no explicit status has been set already
|
|
221
|
-
*/
|
|
222
|
-
if (hasEmptyBody) {
|
|
223
|
-
this.safeStatus(204);
|
|
224
|
-
}
|
|
225
|
-
const statusCode = this.response.statusCode;
|
|
226
|
-
/**
|
|
227
|
-
* Do not process body when status code is less than 200 or is 204 or 304. As per
|
|
228
|
-
* https://tools.ietf.org/html/rfc7230#section-3.3.2
|
|
229
|
-
*/
|
|
230
|
-
if (statusCode && (statusCode < 200 || statusCode === 204 || statusCode === 304)) {
|
|
231
|
-
this.removeHeader('Content-Type');
|
|
232
|
-
this.removeHeader('Content-Length');
|
|
233
|
-
this.removeHeader('Transfer-Encoding');
|
|
234
|
-
this.#endResponse();
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Body is empty and status code is not "204", "304" and neither under 200.
|
|
239
|
-
*/
|
|
240
|
-
if (hasEmptyBody) {
|
|
241
|
-
this.removeHeader('Content-Length');
|
|
242
|
-
this.#endResponse();
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Javascript data type for the content. We only handle a subset
|
|
247
|
-
* of data types. Check [[this.getDataType]] method for more
|
|
248
|
-
* info
|
|
249
|
-
*/
|
|
250
|
-
const dataType = this.#getDataType(content);
|
|
251
|
-
/**
|
|
252
|
-
* ----------------------------------------
|
|
253
|
-
* SERIALIZE CONTENT TO A STRING
|
|
254
|
-
* ----------------------------------------
|
|
255
|
-
*
|
|
256
|
-
* Transforming date, number, boolean and object to a string
|
|
257
|
-
*/
|
|
258
|
-
if (dataType === 'object') {
|
|
259
|
-
content = json.safeStringify(content);
|
|
260
|
-
}
|
|
261
|
-
else if (dataType === 'number' ||
|
|
262
|
-
dataType === 'boolean' ||
|
|
263
|
-
dataType === 'bigint' ||
|
|
264
|
-
dataType === 'regexp') {
|
|
265
|
-
content = String(content);
|
|
266
|
-
}
|
|
267
|
-
else if (dataType === 'date') {
|
|
268
|
-
content = content.toISOString();
|
|
269
|
-
}
|
|
270
|
-
/*
|
|
271
|
-
* ----------------------------------------
|
|
272
|
-
* MORE MODIFICATIONS FOR JSONP BODY
|
|
273
|
-
* ----------------------------------------
|
|
274
|
-
*
|
|
275
|
-
* If JSONP callback exists, then update the body to be a
|
|
276
|
-
* valid JSONP response
|
|
277
|
-
*/
|
|
278
|
-
if (jsonpCallbackName) {
|
|
279
|
-
/*
|
|
280
|
-
* replace chars not allowed in JavaScript that are in JSON
|
|
281
|
-
* https://github.com/rack/rack-contrib/pull/37
|
|
282
|
-
*/
|
|
283
|
-
content = content.replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029');
|
|
284
|
-
// the /**/ is a specific security mitigation for "Rosetta Flash JSONP abuse"
|
|
285
|
-
// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-4671
|
|
286
|
-
// http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
|
|
287
|
-
// http://drops.wooyun.org/tips/2554
|
|
288
|
-
content = `/**/ typeof ${jsonpCallbackName} === 'function' && ${jsonpCallbackName}(${content});`;
|
|
289
|
-
}
|
|
290
|
-
/*
|
|
291
|
-
* ----------------------------------------
|
|
292
|
-
* FINALY GENERATE AN ETAG
|
|
293
|
-
* ----------------------------------------
|
|
294
|
-
*
|
|
295
|
-
* Generate etag if instructed.
|
|
296
|
-
*/
|
|
297
|
-
if (generateEtag) {
|
|
298
|
-
this.setEtag(content);
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* End response when cache is fresh
|
|
302
|
-
*/
|
|
303
|
-
if (generateEtag && this.fresh()) {
|
|
304
|
-
this.removeHeader('Content-Type');
|
|
305
|
-
this.removeHeader('Content-Length');
|
|
306
|
-
this.removeHeader('Transfer-Encoding');
|
|
307
|
-
this.#endResponse(null, 304);
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
/*
|
|
311
|
-
* ----------------------------------------
|
|
312
|
-
* SET CONTENT-LENGTH HEADER
|
|
313
|
-
* ----------------------------------------
|
|
314
|
-
*/
|
|
315
|
-
this.header('Content-Length', Buffer.byteLength(content));
|
|
316
|
-
/**
|
|
317
|
-
* ----------------------------------------
|
|
318
|
-
* SET CONTENT-TYPE HEADER
|
|
319
|
-
* ----------------------------------------
|
|
320
|
-
*
|
|
321
|
-
* - If it is a JSONP response, then we always set the content type
|
|
322
|
-
* to "text/javascript"
|
|
323
|
-
*
|
|
324
|
-
* - String are checked for HTML and "text/plain" or "text/html" is set
|
|
325
|
-
* accordingly.
|
|
326
|
-
*
|
|
327
|
-
* - "text/plain" is set for "numbers" and "booleans" and "dates"
|
|
328
|
-
*
|
|
329
|
-
* - "application/octet-stream" is set for buffers
|
|
330
|
-
*
|
|
331
|
-
* - "application/json" is set for objects and arrays
|
|
332
|
-
*/
|
|
333
|
-
if (jsonpCallbackName) {
|
|
334
|
-
this.header('X-Content-Type-Options', 'nosniff');
|
|
335
|
-
this.safeHeader('Content-Type', 'text/javascript; charset=utf-8');
|
|
336
|
-
}
|
|
337
|
-
else {
|
|
338
|
-
switch (dataType) {
|
|
339
|
-
case 'string':
|
|
340
|
-
const type = /^\s*</.test(content) ? 'text/html' : 'text/plain';
|
|
341
|
-
this.safeHeader('Content-Type', `${type}; charset=utf-8`);
|
|
342
|
-
break;
|
|
343
|
-
case 'number':
|
|
344
|
-
case 'boolean':
|
|
345
|
-
case 'date':
|
|
346
|
-
case 'bigint':
|
|
347
|
-
case 'regexp':
|
|
348
|
-
this.safeHeader('Content-Type', 'text/plain; charset=utf-8');
|
|
349
|
-
break;
|
|
350
|
-
case 'buffer':
|
|
351
|
-
this.safeHeader('Content-Type', 'application/octet-stream; charset=utf-8');
|
|
352
|
-
break;
|
|
353
|
-
case 'object':
|
|
354
|
-
this.safeHeader('Content-Type', 'application/json; charset=utf-8');
|
|
355
|
-
break;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
this.#endResponse(content);
|
|
359
|
-
}
|
|
360
|
-
/**
|
|
361
|
-
* Stream the body to the response and handles cleaning up the stream
|
|
362
|
-
*/
|
|
363
|
-
streamBody(body, errorCallback) {
|
|
364
|
-
return new Promise((resolve) => {
|
|
365
|
-
let finished = false;
|
|
366
|
-
/*
|
|
367
|
-
* Listen for errors on the stream and properly destroy
|
|
368
|
-
* stream
|
|
369
|
-
*/
|
|
370
|
-
body.on('error', (error) => {
|
|
371
|
-
/* c8 ignore next 3 */
|
|
372
|
-
if (finished) {
|
|
373
|
-
return;
|
|
374
|
-
}
|
|
375
|
-
finished = true;
|
|
376
|
-
destroy(body);
|
|
377
|
-
this.type('text');
|
|
378
|
-
if (!this.headersSent) {
|
|
379
|
-
if (typeof errorCallback === 'function') {
|
|
380
|
-
this.#endResponse(...errorCallback(error));
|
|
381
|
-
}
|
|
382
|
-
else {
|
|
383
|
-
this.#endResponse(error.code === 'ENOENT' ? 'File not found' : 'Cannot process file', error.code === 'ENOENT' ? 404 : 500);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
else {
|
|
387
|
-
this.response.destroy();
|
|
388
|
-
}
|
|
389
|
-
resolve();
|
|
390
|
-
});
|
|
391
|
-
/*
|
|
392
|
-
* Listen for end and resolve the promise
|
|
393
|
-
*/
|
|
394
|
-
body.on('end', () => {
|
|
395
|
-
if (!this.headersSent) {
|
|
396
|
-
this.#endResponse();
|
|
397
|
-
}
|
|
398
|
-
resolve();
|
|
399
|
-
});
|
|
400
|
-
/*
|
|
401
|
-
* Cleanup stream when finishing response
|
|
402
|
-
*/
|
|
403
|
-
onFinished(this.response, () => {
|
|
404
|
-
finished = true;
|
|
405
|
-
destroy(body);
|
|
406
|
-
});
|
|
407
|
-
/*
|
|
408
|
-
* Pipe stream
|
|
409
|
-
*/
|
|
410
|
-
this.flushHeaders();
|
|
411
|
-
body.pipe(this.response);
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Downloads a file by streaming it to the response
|
|
416
|
-
*/
|
|
417
|
-
async streamFileForDownload(filePath, generateEtag, errorCallback) {
|
|
418
|
-
try {
|
|
419
|
-
const stats = await stat(filePath);
|
|
420
|
-
if (!stats || !stats.isFile()) {
|
|
421
|
-
throw new TypeError('response.download only accepts path to a file');
|
|
422
|
-
}
|
|
423
|
-
/*
|
|
424
|
-
* Set appropriate headers
|
|
425
|
-
*/
|
|
426
|
-
this.header('Last-Modified', stats.mtime.toUTCString());
|
|
427
|
-
this.type(extname(filePath));
|
|
428
|
-
/*
|
|
429
|
-
* Set the etag when instructed.
|
|
430
|
-
*/
|
|
431
|
-
if (generateEtag) {
|
|
432
|
-
this.setEtag(stats, true);
|
|
433
|
-
}
|
|
434
|
-
/*
|
|
435
|
-
* Do not stream files for HEAD request, but set the appropriate
|
|
436
|
-
* status code.
|
|
437
|
-
*
|
|
438
|
-
* 200: When not using etags or cache is not fresh. This forces browser
|
|
439
|
-
* to always make a GET request
|
|
440
|
-
*
|
|
441
|
-
* 304: When etags are used and cache is fresh
|
|
442
|
-
*/
|
|
443
|
-
if (this.request.method === 'HEAD') {
|
|
444
|
-
this.#endResponse(null, generateEtag && this.fresh() ? 304 : 200);
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
/*
|
|
448
|
-
* Regardless of request method, if we are using etags and
|
|
449
|
-
* cache is fresh, then we must respond with 304
|
|
450
|
-
*/
|
|
451
|
-
if (generateEtag && this.fresh()) {
|
|
452
|
-
this.#endResponse(null, 304);
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
/*
|
|
456
|
-
* Fix for https://tools.ietf.org/html/rfc7232#section-4.1. It is
|
|
457
|
-
* recommended to ignore headers other than Cache-Control,
|
|
458
|
-
* Content-Location, Date, ETag, Expires, and Vary.
|
|
459
|
-
*/
|
|
460
|
-
this.header('Content-length', stats.size);
|
|
461
|
-
/*
|
|
462
|
-
* Finally stream the file
|
|
463
|
-
*/
|
|
464
|
-
return this.streamBody(createReadStream(filePath), errorCallback);
|
|
465
|
-
}
|
|
466
|
-
catch (error) {
|
|
467
|
-
this.type('text');
|
|
468
|
-
this.removeHeader('Etag');
|
|
469
|
-
if (typeof errorCallback === 'function') {
|
|
470
|
-
this.#endResponse(...errorCallback(error));
|
|
471
|
-
}
|
|
472
|
-
else {
|
|
473
|
-
this.#endResponse(error.code === 'ENOENT' ? 'File not found' : 'Cannot process file', error.code === 'ENOENT' ? 404 : 500);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* Writes headers with the Node.js res object using the
|
|
479
|
-
* response.setHeader method
|
|
480
|
-
*/
|
|
481
|
-
flushHeaders() {
|
|
482
|
-
if (!this.headersSent) {
|
|
483
|
-
for (let key in this.#headers) {
|
|
484
|
-
const value = this.#headers[key];
|
|
485
|
-
if (value) {
|
|
486
|
-
this.response.setHeader(key, value);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* Calls res.writeHead on the Node.js res object.
|
|
493
|
-
*/
|
|
494
|
-
writeHead(statusCode) {
|
|
495
|
-
this.response.writeHead(statusCode || this.response.statusCode, this.#headers);
|
|
496
|
-
return this;
|
|
497
|
-
}
|
|
498
|
-
/**
|
|
499
|
-
* Returns the existing value for a given HTTP response
|
|
500
|
-
* header.
|
|
501
|
-
*/
|
|
502
|
-
getHeader(key) {
|
|
503
|
-
const value = this.#headers[key.toLowerCase()];
|
|
504
|
-
return value === undefined ? this.response.getHeader(key) : value;
|
|
505
|
-
}
|
|
506
|
-
/**
|
|
507
|
-
* Get response headers
|
|
508
|
-
*/
|
|
509
|
-
getHeaders() {
|
|
510
|
-
return {
|
|
511
|
-
...this.response.getHeaders(),
|
|
512
|
-
...this.#headers,
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
/**
|
|
516
|
-
* Set header on the response. To `append` values to the existing header, we suggest
|
|
517
|
-
* using [[append]] method.
|
|
518
|
-
*
|
|
519
|
-
* If `value` is non existy, then header won't be set.
|
|
520
|
-
*
|
|
521
|
-
* @example
|
|
522
|
-
* ```js
|
|
523
|
-
* response.header('content-type', 'application/json')
|
|
524
|
-
* ```
|
|
525
|
-
*/
|
|
526
|
-
header(key, value) {
|
|
527
|
-
if (value === null || value === undefined) {
|
|
528
|
-
return this;
|
|
529
|
-
}
|
|
530
|
-
this.#headers[key.toLowerCase()] = this.#castHeaderValue(value);
|
|
531
|
-
return this;
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* Append value to an existing header. To replace the value, we suggest using
|
|
535
|
-
* [[header]] method.
|
|
536
|
-
*
|
|
537
|
-
* If `value` is not existy, then header won't be set.
|
|
538
|
-
*
|
|
539
|
-
* @example
|
|
540
|
-
* ```js
|
|
541
|
-
* response.append('set-cookie', 'username=virk')
|
|
542
|
-
* ```
|
|
543
|
-
*/
|
|
544
|
-
append(key, value) {
|
|
545
|
-
if (value === null || value === undefined) {
|
|
546
|
-
return this;
|
|
547
|
-
}
|
|
548
|
-
key = key.toLowerCase();
|
|
549
|
-
let existingHeader = this.getHeader(key);
|
|
550
|
-
let casted = this.#castHeaderValue(value);
|
|
551
|
-
/**
|
|
552
|
-
* If there isn't any header, then setHeader right
|
|
553
|
-
* away
|
|
554
|
-
*/
|
|
555
|
-
if (!existingHeader) {
|
|
556
|
-
this.#headers[key] = casted;
|
|
557
|
-
return this;
|
|
558
|
-
}
|
|
559
|
-
existingHeader = this.#castHeaderValue(existingHeader);
|
|
560
|
-
casted = Array.isArray(existingHeader)
|
|
561
|
-
? existingHeader.concat(casted)
|
|
562
|
-
: [existingHeader].concat(casted);
|
|
563
|
-
this.#headers[key] = casted;
|
|
564
|
-
return this;
|
|
565
|
-
}
|
|
566
|
-
/**
|
|
567
|
-
* Adds HTTP response header, when it doesn't exists already.
|
|
568
|
-
*/
|
|
569
|
-
safeHeader(key, value) {
|
|
570
|
-
if (!this.getHeader(key)) {
|
|
571
|
-
this.header(key, value);
|
|
572
|
-
}
|
|
573
|
-
return this;
|
|
574
|
-
}
|
|
575
|
-
/**
|
|
576
|
-
* Removes the existing response header from being sent.
|
|
577
|
-
*/
|
|
578
|
-
removeHeader(key) {
|
|
579
|
-
key = key.toLowerCase();
|
|
580
|
-
this.response.removeHeader(key);
|
|
581
|
-
if (this.#headers[key]) {
|
|
582
|
-
delete this.#headers[key.toLowerCase()];
|
|
583
|
-
}
|
|
584
|
-
return this;
|
|
585
|
-
}
|
|
586
|
-
/**
|
|
587
|
-
* Returns the status code for the response
|
|
588
|
-
*/
|
|
589
|
-
getStatus() {
|
|
590
|
-
return this.response.statusCode;
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
|
-
* Set HTTP status code
|
|
594
|
-
*/
|
|
595
|
-
status(code) {
|
|
596
|
-
this.#hasExplicitStatus = true;
|
|
597
|
-
this.response.statusCode = code;
|
|
598
|
-
return this;
|
|
599
|
-
}
|
|
600
|
-
/**
|
|
601
|
-
* Set's status code only when it's not explictly
|
|
602
|
-
* set
|
|
603
|
-
*/
|
|
604
|
-
safeStatus(code) {
|
|
605
|
-
if (this.#hasExplicitStatus) {
|
|
606
|
-
return this;
|
|
607
|
-
}
|
|
608
|
-
this.response.statusCode = code;
|
|
609
|
-
return this;
|
|
610
|
-
}
|
|
611
|
-
/**
|
|
612
|
-
* Set response type by looking up for the mime-type using
|
|
613
|
-
* partial types like file extensions.
|
|
614
|
-
*
|
|
615
|
-
* Make sure to read [mime-types](https://www.npmjs.com/package/mime-types) docs
|
|
616
|
-
* too.
|
|
617
|
-
*
|
|
618
|
-
* @example
|
|
619
|
-
* ```js
|
|
620
|
-
* response.type('.json') // Content-type: application/json
|
|
621
|
-
* ```
|
|
622
|
-
*/
|
|
623
|
-
type(type, charset) {
|
|
624
|
-
type = charset ? `${type}; charset=${charset}` : type;
|
|
625
|
-
this.header('Content-Type', mime.contentType(type));
|
|
626
|
-
return this;
|
|
627
|
-
}
|
|
628
|
-
/**
|
|
629
|
-
* Set the Vary HTTP header
|
|
630
|
-
*/
|
|
631
|
-
vary(field) {
|
|
632
|
-
vary(this.response, field);
|
|
633
|
-
return this;
|
|
634
|
-
}
|
|
635
|
-
/**
|
|
636
|
-
* Set etag by computing hash from the body. This class will set the etag automatically
|
|
637
|
-
* when `etag = true` in the defined config object.
|
|
638
|
-
*
|
|
639
|
-
* Use this function, when you want to compute etag manually for some other resons.
|
|
640
|
-
*/
|
|
641
|
-
setEtag(body, weak = false) {
|
|
642
|
-
this.header('Etag', etag(body, { weak }));
|
|
643
|
-
return this;
|
|
644
|
-
}
|
|
645
|
-
/**
|
|
646
|
-
* Returns a boolean telling if the new response etag evaluates same
|
|
647
|
-
* as the request header `if-none-match`. In case of `true`, the
|
|
648
|
-
* server must return `304` response, telling the browser to
|
|
649
|
-
* use the client cache.
|
|
650
|
-
*
|
|
651
|
-
* You won't have to deal with this method directly, since AdonisJs will
|
|
652
|
-
* handle this for you when `http.etag = true` inside `config/app.js` file.
|
|
653
|
-
*
|
|
654
|
-
* However, this is how you can use it manually.
|
|
655
|
-
*
|
|
656
|
-
* @example
|
|
657
|
-
* ```js
|
|
658
|
-
* const responseBody = view.render('some-view')
|
|
659
|
-
*
|
|
660
|
-
* // sets the HTTP etag header for response
|
|
661
|
-
* response.setEtag(responseBody)
|
|
662
|
-
*
|
|
663
|
-
* if (response.fresh()) {
|
|
664
|
-
* response.sendStatus(304)
|
|
665
|
-
* } else {
|
|
666
|
-
* response.send(responseBody)
|
|
667
|
-
* }
|
|
668
|
-
* ```
|
|
669
|
-
*/
|
|
670
|
-
fresh() {
|
|
671
|
-
if (this.request.method && !CACHEABLE_HTTP_METHODS.includes(this.request.method)) {
|
|
672
|
-
return false;
|
|
673
|
-
}
|
|
674
|
-
const status = this.response.statusCode;
|
|
675
|
-
if ((status >= 200 && status < 300) || status === 304) {
|
|
676
|
-
return fresh(this.request.headers, this.#headers);
|
|
677
|
-
}
|
|
678
|
-
return false;
|
|
679
|
-
}
|
|
680
|
-
/**
|
|
681
|
-
* Returns the response body. Returns null when response
|
|
682
|
-
* body is a stream
|
|
683
|
-
*/
|
|
684
|
-
getBody() {
|
|
685
|
-
if (this.lazyBody.content) {
|
|
686
|
-
return this.lazyBody.content[0];
|
|
687
|
-
}
|
|
688
|
-
return null;
|
|
689
|
-
}
|
|
690
|
-
/**
|
|
691
|
-
* Send the body as response and optionally generate etag. The default value
|
|
692
|
-
* is read from `config/app.js` file, using `http.etag` property.
|
|
693
|
-
*
|
|
694
|
-
* This method buffers the body if `explicitEnd = true`, which is the default
|
|
695
|
-
* behavior and do not change, unless you know what you are doing.
|
|
696
|
-
*/
|
|
697
|
-
send(body, generateEtag = this.#config.etag) {
|
|
698
|
-
this.lazyBody.content = [body, generateEtag];
|
|
699
|
-
}
|
|
700
|
-
/**
|
|
701
|
-
* Alias of [[send]]
|
|
702
|
-
*/
|
|
703
|
-
json(body, generateEtag = this.#config.etag) {
|
|
704
|
-
return this.send(body, generateEtag);
|
|
705
|
-
}
|
|
706
|
-
/**
|
|
707
|
-
* Writes response as JSONP. The callback name is resolved as follows, with priority
|
|
708
|
-
* from top to bottom.
|
|
709
|
-
*
|
|
710
|
-
* 1. Explicitly defined as 2nd Param.
|
|
711
|
-
* 2. Fetch from request query string.
|
|
712
|
-
* 3. Use the config value `http.jsonpCallbackName` from `config/app.js`.
|
|
713
|
-
* 4. Fallback to `callback`.
|
|
714
|
-
*
|
|
715
|
-
* This method buffers the body if `explicitEnd = true`, which is the default
|
|
716
|
-
* behavior and do not change, unless you know what you are doing.
|
|
717
|
-
*/
|
|
718
|
-
jsonp(body, callbackName = this.#config.jsonpCallbackName, generateEtag = this.#config.etag) {
|
|
719
|
-
this.lazyBody.content = [body, generateEtag, callbackName];
|
|
720
|
-
}
|
|
721
|
-
/**
|
|
722
|
-
* Pipe stream to the response. This method will gracefully destroy
|
|
723
|
-
* the stream, avoiding memory leaks.
|
|
724
|
-
*
|
|
725
|
-
* If `raiseErrors=false`, then this method will self handle all the exceptions by
|
|
726
|
-
* writing a generic HTTP response. To have more control over the error, it is
|
|
727
|
-
* recommended to set `raiseErrors=true` and wrap this function inside a
|
|
728
|
-
* `try/catch` statement.
|
|
729
|
-
*
|
|
730
|
-
* Streaming a file from the disk and showing 404 when file is missing.
|
|
731
|
-
*
|
|
732
|
-
* @example
|
|
733
|
-
* ```js
|
|
734
|
-
* // Errors handled automatically with generic HTTP response
|
|
735
|
-
* response.stream(fs.createReadStream('file.txt'))
|
|
736
|
-
*
|
|
737
|
-
* // Manually handle (note the await call)
|
|
738
|
-
* try {
|
|
739
|
-
* await response.stream(fs.createReadStream('file.txt'))
|
|
740
|
-
* } catch () {
|
|
741
|
-
* response.status(404).send('File not found')
|
|
742
|
-
* }
|
|
743
|
-
* ```
|
|
744
|
-
*/
|
|
745
|
-
stream(body, errorCallback) {
|
|
746
|
-
if (typeof body.pipe !== 'function' || !body.readable || typeof body.read !== 'function') {
|
|
747
|
-
throw new TypeError('response.stream accepts a readable stream only');
|
|
748
|
-
}
|
|
749
|
-
this.lazyBody.stream = [body, errorCallback];
|
|
750
|
-
}
|
|
751
|
-
/**
|
|
752
|
-
* Download file by streaming it from the file path. This method will setup
|
|
753
|
-
* appropriate `Content-type`, `Content-type` and `Last-modified` headers.
|
|
754
|
-
*
|
|
755
|
-
* Unexpected stream errors are handled gracefully to avoid memory leaks.
|
|
756
|
-
*
|
|
757
|
-
* If `raiseErrors=false`, then this method will self handle all the exceptions by
|
|
758
|
-
* writing a generic HTTP response. To have more control over the error, it is
|
|
759
|
-
* recommended to set `raiseErrors=true` and wrap this function inside a
|
|
760
|
-
* `try/catch` statement.
|
|
761
|
-
*
|
|
762
|
-
* @example
|
|
763
|
-
* ```js
|
|
764
|
-
* // Errors handled automatically with generic HTTP response
|
|
765
|
-
* response.download('somefile.jpg')
|
|
766
|
-
*
|
|
767
|
-
* // Manually handle (note the await call)
|
|
768
|
-
* try {
|
|
769
|
-
* await response.download('somefile.jpg')
|
|
770
|
-
* } catch (error) {
|
|
771
|
-
* response.status(error.code === 'ENOENT' ? 404 : 500)
|
|
772
|
-
* response.send('Cannot process file')
|
|
773
|
-
* }
|
|
774
|
-
* ```
|
|
775
|
-
*/
|
|
776
|
-
download(filePath, generateEtag = this.#config.etag, errorCallback) {
|
|
777
|
-
this.lazyBody.fileToStream = [filePath, generateEtag, errorCallback];
|
|
778
|
-
}
|
|
779
|
-
/**
|
|
780
|
-
* Download the file by forcing the user to save the file vs displaying it
|
|
781
|
-
* within the browser.
|
|
782
|
-
*
|
|
783
|
-
* Internally calls [[download]]
|
|
784
|
-
*/
|
|
785
|
-
attachment(filePath, name, disposition, generateEtag, errorCallback) {
|
|
786
|
-
name = name || filePath;
|
|
787
|
-
this.header('Content-Disposition', contentDisposition(name, { type: disposition }));
|
|
788
|
-
return this.download(filePath, generateEtag, errorCallback);
|
|
789
|
-
}
|
|
790
|
-
/**
|
|
791
|
-
* Set the location header.
|
|
792
|
-
*
|
|
793
|
-
* @example
|
|
794
|
-
* ```js
|
|
795
|
-
* response.location('/login')
|
|
796
|
-
* ```
|
|
797
|
-
*/
|
|
798
|
-
location(url) {
|
|
799
|
-
this.header('Location', url);
|
|
800
|
-
return this;
|
|
801
|
-
}
|
|
802
|
-
redirect(path, forwardQueryString = false, statusCode = 302) {
|
|
803
|
-
const handler = new Redirect(this.request, this, this.#router, this.#qs);
|
|
804
|
-
if (forwardQueryString) {
|
|
805
|
-
handler.withQs();
|
|
806
|
-
}
|
|
807
|
-
if (path === 'back') {
|
|
808
|
-
return handler.status(statusCode).back();
|
|
809
|
-
}
|
|
810
|
-
if (path) {
|
|
811
|
-
return handler.status(statusCode).toPath(path);
|
|
812
|
-
}
|
|
813
|
-
return handler;
|
|
814
|
-
}
|
|
815
|
-
/**
|
|
816
|
-
* Abort the request with custom body and a status code. 400 is
|
|
817
|
-
* used when status is not defined
|
|
818
|
-
*/
|
|
819
|
-
abort(body, status) {
|
|
820
|
-
throw E_HTTP_REQUEST_ABORTED.invoke(body, status || 400);
|
|
821
|
-
}
|
|
822
|
-
/**
|
|
823
|
-
* Abort the request with custom body and a status code when
|
|
824
|
-
* passed condition returns `true`
|
|
825
|
-
*/
|
|
826
|
-
abortIf(condition, body, status) {
|
|
827
|
-
if (condition) {
|
|
828
|
-
this.abort(body, status);
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
/**
|
|
832
|
-
* Abort the request with custom body and a status code when
|
|
833
|
-
* passed condition returns `false`
|
|
834
|
-
*/
|
|
835
|
-
abortUnless(condition, body, status) {
|
|
836
|
-
if (!condition) {
|
|
837
|
-
this.abort(body, status);
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
/**
|
|
841
|
-
* Set signed cookie as the response header. The inline options overrides
|
|
842
|
-
* all options from the config.
|
|
843
|
-
*/
|
|
844
|
-
cookie(key, value, options) {
|
|
845
|
-
options = Object.assign({}, this.#config.cookie, options);
|
|
846
|
-
const serialized = this.#cookieSerializer.sign(key, value, options);
|
|
847
|
-
if (!serialized) {
|
|
848
|
-
return this;
|
|
849
|
-
}
|
|
850
|
-
this.append('set-cookie', serialized);
|
|
851
|
-
return this;
|
|
852
|
-
}
|
|
853
|
-
/**
|
|
854
|
-
* Set encrypted cookie as the response header. The inline options overrides
|
|
855
|
-
* all options from the config.
|
|
856
|
-
*/
|
|
857
|
-
encryptedCookie(key, value, options) {
|
|
858
|
-
options = Object.assign({}, this.#config.cookie, options);
|
|
859
|
-
const serialized = this.#cookieSerializer.encrypt(key, value, options);
|
|
860
|
-
if (!serialized) {
|
|
861
|
-
return this;
|
|
862
|
-
}
|
|
863
|
-
this.append('set-cookie', serialized);
|
|
864
|
-
return this;
|
|
865
|
-
}
|
|
866
|
-
/**
|
|
867
|
-
* Set unsigned cookie as the response header. The inline options overrides
|
|
868
|
-
* all options from the config.
|
|
869
|
-
*/
|
|
870
|
-
plainCookie(key, value, options) {
|
|
871
|
-
options = Object.assign({}, this.#config.cookie, options);
|
|
872
|
-
const serialized = this.#cookieSerializer.encode(key, value, options);
|
|
873
|
-
if (!serialized) {
|
|
874
|
-
return this;
|
|
875
|
-
}
|
|
876
|
-
this.append('set-cookie', serialized);
|
|
877
|
-
return this;
|
|
878
|
-
}
|
|
879
|
-
/**
|
|
880
|
-
* Clear existing cookie.
|
|
881
|
-
*/
|
|
882
|
-
clearCookie(key, options) {
|
|
883
|
-
options = Object.assign({}, this.#config.cookie, options);
|
|
884
|
-
options.expires = new Date(1);
|
|
885
|
-
options.maxAge = -1;
|
|
886
|
-
const serialized = this.#cookieSerializer.encode(key, '', { ...options, encode: false });
|
|
887
|
-
this.append('set-cookie', serialized);
|
|
888
|
-
return this;
|
|
889
|
-
}
|
|
890
|
-
/**
|
|
891
|
-
* Finishes the response by writing the lazy body, when `explicitEnd = true`
|
|
892
|
-
* and response is already pending.
|
|
893
|
-
*
|
|
894
|
-
* Calling this method twice or when `explicitEnd = false` is noop.
|
|
895
|
-
*/
|
|
896
|
-
finish() {
|
|
897
|
-
if (!this.isPending) {
|
|
898
|
-
return;
|
|
899
|
-
}
|
|
900
|
-
if (this.content) {
|
|
901
|
-
this.writeBody(...this.content);
|
|
902
|
-
return;
|
|
903
|
-
}
|
|
904
|
-
if (this.lazyBody.stream) {
|
|
905
|
-
this.streamBody(...this.lazyBody.stream);
|
|
906
|
-
return;
|
|
907
|
-
}
|
|
908
|
-
if (this.lazyBody.fileToStream) {
|
|
909
|
-
this.streamFileForDownload(...this.lazyBody.fileToStream);
|
|
910
|
-
return;
|
|
911
|
-
}
|
|
912
|
-
this.#endResponse();
|
|
913
|
-
}
|
|
914
|
-
/**
|
|
915
|
-
* Shorthand method to finish request with "100" status code
|
|
916
|
-
*/
|
|
917
|
-
continue() {
|
|
918
|
-
this.status(100);
|
|
919
|
-
return this.send(null, false);
|
|
920
|
-
}
|
|
921
|
-
/**
|
|
922
|
-
* Shorthand method to finish request with "101" status code
|
|
923
|
-
*/
|
|
924
|
-
switchingProtocols() {
|
|
925
|
-
this.status(101);
|
|
926
|
-
return this.send(null, false);
|
|
927
|
-
}
|
|
928
|
-
/**
|
|
929
|
-
* Shorthand method to finish request with "200" status code
|
|
930
|
-
*/
|
|
931
|
-
ok(body, generateEtag) {
|
|
932
|
-
this.status(200);
|
|
933
|
-
return this.send(body, generateEtag);
|
|
934
|
-
}
|
|
935
|
-
/**
|
|
936
|
-
* Shorthand method to finish request with "201" status code
|
|
937
|
-
*/
|
|
938
|
-
created(body, generateEtag) {
|
|
939
|
-
this.status(201);
|
|
940
|
-
return this.send(body, generateEtag);
|
|
941
|
-
}
|
|
942
|
-
/**
|
|
943
|
-
* Shorthand method to finish request with "202" status code
|
|
944
|
-
*/
|
|
945
|
-
accepted(body, generateEtag) {
|
|
946
|
-
this.status(202);
|
|
947
|
-
return this.send(body, generateEtag);
|
|
948
|
-
}
|
|
949
|
-
/**
|
|
950
|
-
* Shorthand method to finish request with "203" status code
|
|
951
|
-
*/
|
|
952
|
-
nonAuthoritativeInformation(body, generateEtag) {
|
|
953
|
-
this.status(203);
|
|
954
|
-
return this.send(body, generateEtag);
|
|
955
|
-
}
|
|
956
|
-
/**
|
|
957
|
-
* Shorthand method to finish request with "204" status code
|
|
958
|
-
*/
|
|
959
|
-
noContent() {
|
|
960
|
-
this.status(204);
|
|
961
|
-
return this.send(null, false);
|
|
962
|
-
}
|
|
963
|
-
/**
|
|
964
|
-
* Shorthand method to finish request with "205" status code
|
|
965
|
-
*/
|
|
966
|
-
resetContent() {
|
|
967
|
-
this.status(205);
|
|
968
|
-
return this.send(null, false);
|
|
969
|
-
}
|
|
970
|
-
/**
|
|
971
|
-
* Shorthand method to finish request with "206" status code
|
|
972
|
-
*/
|
|
973
|
-
partialContent(body, generateEtag) {
|
|
974
|
-
this.status(206);
|
|
975
|
-
return this.send(body, generateEtag);
|
|
976
|
-
}
|
|
977
|
-
/**
|
|
978
|
-
* Shorthand method to finish request with "300" status code
|
|
979
|
-
*/
|
|
980
|
-
multipleChoices(body, generateEtag) {
|
|
981
|
-
this.status(300);
|
|
982
|
-
return this.send(body, generateEtag);
|
|
983
|
-
}
|
|
984
|
-
/**
|
|
985
|
-
* Shorthand method to finish request with "301" status code
|
|
986
|
-
*/
|
|
987
|
-
movedPermanently(body, generateEtag) {
|
|
988
|
-
this.status(301);
|
|
989
|
-
return this.send(body, generateEtag);
|
|
990
|
-
}
|
|
991
|
-
/**
|
|
992
|
-
* Shorthand method to finish request with "302" status code
|
|
993
|
-
*/
|
|
994
|
-
movedTemporarily(body, generateEtag) {
|
|
995
|
-
this.status(302);
|
|
996
|
-
return this.send(body, generateEtag);
|
|
997
|
-
}
|
|
998
|
-
/**
|
|
999
|
-
* Shorthand method to finish request with "303" status code
|
|
1000
|
-
*/
|
|
1001
|
-
seeOther(body, generateEtag) {
|
|
1002
|
-
this.status(303);
|
|
1003
|
-
return this.send(body, generateEtag);
|
|
1004
|
-
}
|
|
1005
|
-
/**
|
|
1006
|
-
* Shorthand method to finish request with "304" status code
|
|
1007
|
-
*/
|
|
1008
|
-
notModified(body, generateEtag) {
|
|
1009
|
-
this.status(304);
|
|
1010
|
-
return this.send(body, generateEtag);
|
|
1011
|
-
}
|
|
1012
|
-
/**
|
|
1013
|
-
* Shorthand method to finish request with "305" status code
|
|
1014
|
-
*/
|
|
1015
|
-
useProxy(body, generateEtag) {
|
|
1016
|
-
this.status(305);
|
|
1017
|
-
return this.send(body, generateEtag);
|
|
1018
|
-
}
|
|
1019
|
-
/**
|
|
1020
|
-
* Shorthand method to finish request with "307" status code
|
|
1021
|
-
*/
|
|
1022
|
-
temporaryRedirect(body, generateEtag) {
|
|
1023
|
-
this.status(307);
|
|
1024
|
-
return this.send(body, generateEtag);
|
|
1025
|
-
}
|
|
1026
|
-
/**
|
|
1027
|
-
* Shorthand method to finish request with "400" status code
|
|
1028
|
-
*/
|
|
1029
|
-
badRequest(body, generateEtag) {
|
|
1030
|
-
this.status(400);
|
|
1031
|
-
return this.send(body, generateEtag);
|
|
1032
|
-
}
|
|
1033
|
-
/**
|
|
1034
|
-
* Shorthand method to finish request with "401" status code
|
|
1035
|
-
*/
|
|
1036
|
-
unauthorized(body, generateEtag) {
|
|
1037
|
-
this.status(401);
|
|
1038
|
-
return this.send(body, generateEtag);
|
|
1039
|
-
}
|
|
1040
|
-
/**
|
|
1041
|
-
* Shorthand method to finish request with "402" status code
|
|
1042
|
-
*/
|
|
1043
|
-
paymentRequired(body, generateEtag) {
|
|
1044
|
-
this.status(402);
|
|
1045
|
-
return this.send(body, generateEtag);
|
|
1046
|
-
}
|
|
1047
|
-
/**
|
|
1048
|
-
* Shorthand method to finish request with "403" status code
|
|
1049
|
-
*/
|
|
1050
|
-
forbidden(body, generateEtag) {
|
|
1051
|
-
this.status(403);
|
|
1052
|
-
return this.send(body, generateEtag);
|
|
1053
|
-
}
|
|
1054
|
-
/**
|
|
1055
|
-
* Shorthand method to finish request with "404" status code
|
|
1056
|
-
*/
|
|
1057
|
-
notFound(body, generateEtag) {
|
|
1058
|
-
this.status(404);
|
|
1059
|
-
return this.send(body, generateEtag);
|
|
1060
|
-
}
|
|
1061
|
-
/**
|
|
1062
|
-
* Shorthand method to finish request with "405" status code
|
|
1063
|
-
*/
|
|
1064
|
-
methodNotAllowed(body, generateEtag) {
|
|
1065
|
-
this.status(405);
|
|
1066
|
-
return this.send(body, generateEtag);
|
|
1067
|
-
}
|
|
1068
|
-
/**
|
|
1069
|
-
* Shorthand method to finish request with "406" status code
|
|
1070
|
-
*/
|
|
1071
|
-
notAcceptable(body, generateEtag) {
|
|
1072
|
-
this.status(406);
|
|
1073
|
-
return this.send(body, generateEtag);
|
|
1074
|
-
}
|
|
1075
|
-
/**
|
|
1076
|
-
* Shorthand method to finish request with "407" status code
|
|
1077
|
-
*/
|
|
1078
|
-
proxyAuthenticationRequired(body, generateEtag) {
|
|
1079
|
-
this.status(407);
|
|
1080
|
-
return this.send(body, generateEtag);
|
|
1081
|
-
}
|
|
1082
|
-
/**
|
|
1083
|
-
* Shorthand method to finish request with "408" status code
|
|
1084
|
-
*/
|
|
1085
|
-
requestTimeout(body, generateEtag) {
|
|
1086
|
-
this.status(408);
|
|
1087
|
-
return this.send(body, generateEtag);
|
|
1088
|
-
}
|
|
1089
|
-
/**
|
|
1090
|
-
* Shorthand method to finish request with "409" status code
|
|
1091
|
-
*/
|
|
1092
|
-
conflict(body, generateEtag) {
|
|
1093
|
-
this.status(409);
|
|
1094
|
-
return this.send(body, generateEtag);
|
|
1095
|
-
}
|
|
1096
|
-
/**
|
|
1097
|
-
* Shorthand method to finish request with "401" status code
|
|
1098
|
-
*/
|
|
1099
|
-
gone(body, generateEtag) {
|
|
1100
|
-
this.status(410);
|
|
1101
|
-
return this.send(body, generateEtag);
|
|
1102
|
-
}
|
|
1103
|
-
/**
|
|
1104
|
-
* Shorthand method to finish request with "411" status code
|
|
1105
|
-
*/
|
|
1106
|
-
lengthRequired(body, generateEtag) {
|
|
1107
|
-
this.status(411);
|
|
1108
|
-
return this.send(body, generateEtag);
|
|
1109
|
-
}
|
|
1110
|
-
/**
|
|
1111
|
-
* Shorthand method to finish request with "412" status code
|
|
1112
|
-
*/
|
|
1113
|
-
preconditionFailed(body, generateEtag) {
|
|
1114
|
-
this.status(412);
|
|
1115
|
-
return this.send(body, generateEtag);
|
|
1116
|
-
}
|
|
1117
|
-
/**
|
|
1118
|
-
* Shorthand method to finish request with "413" status code
|
|
1119
|
-
*/
|
|
1120
|
-
requestEntityTooLarge(body, generateEtag) {
|
|
1121
|
-
this.status(413);
|
|
1122
|
-
return this.send(body, generateEtag);
|
|
1123
|
-
}
|
|
1124
|
-
/**
|
|
1125
|
-
* Shorthand method to finish request with "414" status code
|
|
1126
|
-
*/
|
|
1127
|
-
requestUriTooLong(body, generateEtag) {
|
|
1128
|
-
this.status(414);
|
|
1129
|
-
return this.send(body, generateEtag);
|
|
1130
|
-
}
|
|
1131
|
-
/**
|
|
1132
|
-
* Shorthand method to finish request with "415" status code
|
|
1133
|
-
*/
|
|
1134
|
-
unsupportedMediaType(body, generateEtag) {
|
|
1135
|
-
this.status(415);
|
|
1136
|
-
return this.send(body, generateEtag);
|
|
1137
|
-
}
|
|
1138
|
-
/**
|
|
1139
|
-
* Shorthand method to finish request with "416" status code
|
|
1140
|
-
*/
|
|
1141
|
-
requestedRangeNotSatisfiable(body, generateEtag) {
|
|
1142
|
-
this.status(416);
|
|
1143
|
-
return this.send(body, generateEtag);
|
|
1144
|
-
}
|
|
1145
|
-
/**
|
|
1146
|
-
* Shorthand method to finish request with "417" status code
|
|
1147
|
-
*/
|
|
1148
|
-
expectationFailed(body, generateEtag) {
|
|
1149
|
-
this.status(417);
|
|
1150
|
-
return this.send(body, generateEtag);
|
|
1151
|
-
}
|
|
1152
|
-
/**
|
|
1153
|
-
* Shorthand method to finish request with "422" status code
|
|
1154
|
-
*/
|
|
1155
|
-
unprocessableEntity(body, generateEtag) {
|
|
1156
|
-
this.status(422);
|
|
1157
|
-
return this.send(body, generateEtag);
|
|
1158
|
-
}
|
|
1159
|
-
/**
|
|
1160
|
-
* Shorthand method to finish request with "429" status code
|
|
1161
|
-
*/
|
|
1162
|
-
tooManyRequests(body, generateEtag) {
|
|
1163
|
-
this.status(429);
|
|
1164
|
-
return this.send(body, generateEtag);
|
|
1165
|
-
}
|
|
1166
|
-
/**
|
|
1167
|
-
* Shorthand method to finish request with "500" status code
|
|
1168
|
-
*/
|
|
1169
|
-
internalServerError(body, generateEtag) {
|
|
1170
|
-
this.status(500);
|
|
1171
|
-
return this.send(body, generateEtag);
|
|
1172
|
-
}
|
|
1173
|
-
/**
|
|
1174
|
-
* Shorthand method to finish request with "501" status code
|
|
1175
|
-
*/
|
|
1176
|
-
notImplemented(body, generateEtag) {
|
|
1177
|
-
this.status(501);
|
|
1178
|
-
return this.send(body, generateEtag);
|
|
1179
|
-
}
|
|
1180
|
-
/**
|
|
1181
|
-
* Shorthand method to finish request with "502" status code
|
|
1182
|
-
*/
|
|
1183
|
-
badGateway(body, generateEtag) {
|
|
1184
|
-
this.status(502);
|
|
1185
|
-
return this.send(body, generateEtag);
|
|
1186
|
-
}
|
|
1187
|
-
/**
|
|
1188
|
-
* Shorthand method to finish request with "503" status code
|
|
1189
|
-
*/
|
|
1190
|
-
serviceUnavailable(body, generateEtag) {
|
|
1191
|
-
this.status(503);
|
|
1192
|
-
return this.send(body, generateEtag);
|
|
1193
|
-
}
|
|
1194
|
-
/**
|
|
1195
|
-
* Shorthand method to finish request with "504" status code
|
|
1196
|
-
*/
|
|
1197
|
-
gatewayTimeout(body, generateEtag) {
|
|
1198
|
-
this.status(504);
|
|
1199
|
-
return this.send(body, generateEtag);
|
|
1200
|
-
}
|
|
1201
|
-
/**
|
|
1202
|
-
* Shorthand method to finish request with "505" status code
|
|
1203
|
-
*/
|
|
1204
|
-
httpVersionNotSupported(body, generateEtag) {
|
|
1205
|
-
this.status(505);
|
|
1206
|
-
return this.send(body, generateEtag);
|
|
1207
|
-
}
|
|
1208
|
-
}
|