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