@adonisjs/http-server 6.8.2-5 → 6.8.2-7

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 (208) hide show
  1. package/README.md +3 -6
  2. package/build/factories/http_context.d.ts +10 -1
  3. package/build/factories/http_context.js +27 -0
  4. package/build/factories/http_server.d.ts +8 -0
  5. package/build/factories/http_server.js +26 -0
  6. package/build/factories/main.d.ts +0 -1
  7. package/build/factories/main.js +8 -0
  8. package/build/factories/qs_parser_factory.d.ts +10 -1
  9. package/build/factories/qs_parser_factory.js +18 -0
  10. package/build/factories/request.d.ts +10 -1
  11. package/build/factories/request.js +31 -0
  12. package/build/factories/response.d.ts +10 -1
  13. package/build/factories/response.js +34 -0
  14. package/build/factories/router.d.ts +10 -1
  15. package/build/factories/router.js +25 -0
  16. package/build/factories/server_factory.d.ts +10 -1
  17. package/build/factories/server_factory.js +34 -0
  18. package/build/index.d.ts +0 -1
  19. package/build/index.js +8 -0
  20. package/build/src/cookies/client.d.ts +25 -1
  21. package/build/src/cookies/client.js +42 -0
  22. package/build/src/cookies/drivers/encrypted.d.ts +12 -1
  23. package/build/src/cookies/drivers/encrypted.js +20 -0
  24. package/build/src/cookies/drivers/plain.d.ts +12 -1
  25. package/build/src/cookies/drivers/plain.js +20 -0
  26. package/build/src/cookies/drivers/signed.d.ts +12 -1
  27. package/build/src/cookies/drivers/signed.js +20 -0
  28. package/build/src/cookies/parser.d.ts +28 -1
  29. package/build/src/cookies/parser.js +98 -0
  30. package/build/src/cookies/serializer.d.ts +22 -1
  31. package/build/src/cookies/serializer.js +40 -0
  32. package/build/src/debug.d.ts +0 -1
  33. package/build/src/debug.js +8 -0
  34. package/build/src/define_config.d.ts +3 -1
  35. package/build/src/define_config.js +11 -0
  36. package/build/src/define_middleware.d.ts +5 -1
  37. package/build/src/define_middleware.js +18 -0
  38. package/build/src/exception_handler.d.ts +65 -1
  39. package/build/src/exception_handler.js +95 -0
  40. package/build/src/exceptions.d.ts +6 -1
  41. package/build/src/exceptions.js +11 -0
  42. package/build/src/helpers.d.ts +14 -1
  43. package/build/src/helpers.js +22 -0
  44. package/build/src/http_context/local_storage.d.ts +3 -1
  45. package/build/src/http_context/local_storage.js +25 -0
  46. package/build/src/http_context/main.d.ts +36 -1
  47. package/build/src/http_context/main.js +54 -0
  48. package/build/src/qs.d.ts +4 -1
  49. package/build/src/qs.js +12 -0
  50. package/build/src/redirect.d.ts +24 -1
  51. package/build/src/redirect.js +60 -0
  52. package/build/src/request.d.ts +466 -1
  53. package/build/src/request.js +542 -0
  54. package/build/src/response.d.ts +425 -2
  55. package/build/src/response.js +608 -7
  56. package/build/src/router/brisk.d.ts +22 -1
  57. package/build/src/router/brisk.js +42 -0
  58. package/build/src/router/executor.d.ts +4 -1
  59. package/build/src/router/executor.js +12 -0
  60. package/build/src/router/factories/use_return_value.d.ts +4 -1
  61. package/build/src/router/factories/use_return_value.js +16 -3
  62. package/build/src/router/group.d.ts +47 -1
  63. package/build/src/router/group.js +88 -0
  64. package/build/src/router/lookup_store/main.d.ts +32 -1
  65. package/build/src/router/lookup_store/main.js +49 -0
  66. package/build/src/router/lookup_store/route_finder.d.ts +13 -1
  67. package/build/src/router/lookup_store/route_finder.js +21 -0
  68. package/build/src/router/lookup_store/url_builder.d.ts +36 -1
  69. package/build/src/router/lookup_store/url_builder.js +97 -0
  70. package/build/src/router/main.d.ts +87 -1
  71. package/build/src/router/main.js +142 -0
  72. package/build/src/router/matchers.d.ts +13 -1
  73. package/build/src/router/matchers.js +21 -0
  74. package/build/src/router/parser.d.ts +3 -1
  75. package/build/src/router/parser.js +12 -0
  76. package/build/src/router/resource.d.ts +28 -1
  77. package/build/src/router/resource.js +90 -0
  78. package/build/src/router/route.d.ts +65 -1
  79. package/build/src/router/route.js +142 -0
  80. package/build/src/router/store.d.ts +54 -1
  81. package/build/src/router/store.js +102 -0
  82. package/build/src/server/factories/final_handler.d.ts +5 -1
  83. package/build/src/server/factories/final_handler.js +13 -0
  84. package/build/src/server/factories/middleware_handler.d.ts +3 -1
  85. package/build/src/server/factories/middleware_handler.js +11 -0
  86. package/build/src/server/factories/write_response.d.ts +4 -1
  87. package/build/src/server/factories/write_response.js +12 -0
  88. package/build/src/server/main.d.ts +48 -1
  89. package/build/src/server/main.js +128 -0
  90. package/build/src/types/base.d.ts +12 -1
  91. package/build/src/types/base.js +8 -0
  92. package/build/src/types/main.d.ts +0 -1
  93. package/build/src/types/main.js +8 -0
  94. package/build/src/types/middleware.d.ts +18 -1
  95. package/build/src/types/middleware.js +8 -0
  96. package/build/src/types/qs.d.ts +53 -1
  97. package/build/src/types/qs.js +8 -0
  98. package/build/src/types/request.d.ts +32 -1
  99. package/build/src/types/request.js +8 -0
  100. package/build/src/types/response.d.ts +27 -1
  101. package/build/src/types/response.js +8 -0
  102. package/build/src/types/route.d.ts +87 -1
  103. package/build/src/types/route.js +8 -0
  104. package/build/src/types/server.d.ts +35 -1
  105. package/build/src/types/server.js +8 -0
  106. package/package.json +43 -70
  107. package/build/factories/http_context.d.ts.map +0 -1
  108. package/build/factories/main.d.ts.map +0 -1
  109. package/build/factories/qs_parser_factory.d.ts.map +0 -1
  110. package/build/factories/request.d.ts.map +0 -1
  111. package/build/factories/response.d.ts.map +0 -1
  112. package/build/factories/router.d.ts.map +0 -1
  113. package/build/factories/server_factory.d.ts.map +0 -1
  114. package/build/index.d.ts.map +0 -1
  115. package/build/src/cookies/client.d.ts.map +0 -1
  116. package/build/src/cookies/drivers/encrypted.d.ts.map +0 -1
  117. package/build/src/cookies/drivers/plain.d.ts.map +0 -1
  118. package/build/src/cookies/drivers/signed.d.ts.map +0 -1
  119. package/build/src/cookies/parser.d.ts.map +0 -1
  120. package/build/src/cookies/serializer.d.ts.map +0 -1
  121. package/build/src/debug.d.ts.map +0 -1
  122. package/build/src/define_config.d.ts.map +0 -1
  123. package/build/src/define_middleware.d.ts.map +0 -1
  124. package/build/src/exception_handler.d.ts.map +0 -1
  125. package/build/src/exceptions.d.ts.map +0 -1
  126. package/build/src/helpers.d.ts.map +0 -1
  127. package/build/src/http_context/local_storage.d.ts.map +0 -1
  128. package/build/src/http_context/main.d.ts.map +0 -1
  129. package/build/src/qs.d.ts.map +0 -1
  130. package/build/src/redirect.d.ts.map +0 -1
  131. package/build/src/request.d.ts.map +0 -1
  132. package/build/src/response.d.ts.map +0 -1
  133. package/build/src/router/brisk.d.ts.map +0 -1
  134. package/build/src/router/executor.d.ts.map +0 -1
  135. package/build/src/router/factories/use_return_value.d.ts.map +0 -1
  136. package/build/src/router/group.d.ts.map +0 -1
  137. package/build/src/router/lookup_store/main.d.ts.map +0 -1
  138. package/build/src/router/lookup_store/route_finder.d.ts.map +0 -1
  139. package/build/src/router/lookup_store/url_builder.d.ts.map +0 -1
  140. package/build/src/router/main.d.ts.map +0 -1
  141. package/build/src/router/matchers.d.ts.map +0 -1
  142. package/build/src/router/parser.d.ts.map +0 -1
  143. package/build/src/router/resource.d.ts.map +0 -1
  144. package/build/src/router/route.d.ts.map +0 -1
  145. package/build/src/router/store.d.ts.map +0 -1
  146. package/build/src/server/factories/final_handler.d.ts.map +0 -1
  147. package/build/src/server/factories/middleware_handler.d.ts.map +0 -1
  148. package/build/src/server/factories/write_response.d.ts.map +0 -1
  149. package/build/src/server/main.d.ts.map +0 -1
  150. package/build/src/types/base.d.ts.map +0 -1
  151. package/build/src/types/main.d.ts.map +0 -1
  152. package/build/src/types/middleware.d.ts.map +0 -1
  153. package/build/src/types/qs.d.ts.map +0 -1
  154. package/build/src/types/request.d.ts.map +0 -1
  155. package/build/src/types/response.d.ts.map +0 -1
  156. package/build/src/types/route.d.ts.map +0 -1
  157. package/build/src/types/server.d.ts.map +0 -1
  158. package/factories/http_context.ts +0 -73
  159. package/factories/main.ts +0 -15
  160. package/factories/qs_parser_factory.ts +0 -54
  161. package/factories/request.ts +0 -101
  162. package/factories/response.ts +0 -106
  163. package/factories/router.ts +0 -61
  164. package/factories/server_factory.ts +0 -94
  165. package/index.ts +0 -23
  166. package/src/cookies/client.ts +0 -98
  167. package/src/cookies/drivers/encrypted.ts +0 -42
  168. package/src/cookies/drivers/plain.ts +0 -37
  169. package/src/cookies/drivers/signed.ts +0 -42
  170. package/src/cookies/parser.ts +0 -196
  171. package/src/cookies/serializer.ts +0 -98
  172. package/src/debug.ts +0 -11
  173. package/src/define_config.ts +0 -56
  174. package/src/define_middleware.ts +0 -61
  175. package/src/exception_handler.ts +0 -290
  176. package/src/exceptions.ts +0 -55
  177. package/src/helpers.ts +0 -108
  178. package/src/http_context/local_storage.ts +0 -50
  179. package/src/http_context/main.ts +0 -126
  180. package/src/qs.ts +0 -31
  181. package/src/redirect.ts +0 -181
  182. package/src/request.ts +0 -982
  183. package/src/response.ts +0 -1421
  184. package/src/router/brisk.ts +0 -113
  185. package/src/router/executor.ts +0 -36
  186. package/src/router/factories/use_return_value.ts +0 -26
  187. package/src/router/group.ts +0 -243
  188. package/src/router/lookup_store/main.ts +0 -102
  189. package/src/router/lookup_store/route_finder.ts +0 -60
  190. package/src/router/lookup_store/url_builder.ts +0 -250
  191. package/src/router/main.ts +0 -431
  192. package/src/router/matchers.ts +0 -40
  193. package/src/router/parser.ts +0 -20
  194. package/src/router/resource.ts +0 -277
  195. package/src/router/route.ts +0 -363
  196. package/src/router/store.ts +0 -239
  197. package/src/server/factories/final_handler.ts +0 -38
  198. package/src/server/factories/middleware_handler.ts +0 -23
  199. package/src/server/factories/write_response.ts +0 -26
  200. package/src/server/main.ts +0 -356
  201. package/src/types/base.ts +0 -30
  202. package/src/types/main.ts +0 -16
  203. package/src/types/middleware.ts +0 -59
  204. package/src/types/qs.ts +0 -85
  205. package/src/types/request.ts +0 -52
  206. package/src/types/response.ts +0 -57
  207. package/src/types/route.ts +0 -217
  208. package/src/types/server.ts +0 -92
@@ -1,3 +1,11 @@
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
+ */
1
9
  import etag from 'etag';
2
10
  import vary from 'vary';
3
11
  import fresh from 'fresh';
@@ -15,33 +23,82 @@ import { Redirect } from './redirect.js';
15
23
  import { CookieSerializer } from './cookies/serializer.js';
16
24
  import { E_HTTP_REQUEST_ABORTED } from './exceptions.js';
17
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
+ */
18
30
  export class Response extends Macroable {
19
31
  request;
20
32
  response;
33
+ /**
34
+ * Query string parser
35
+ */
21
36
  #qs;
37
+ /**
38
+ * Outgoing headers
39
+ */
22
40
  #headers = {};
41
+ /**
42
+ * Has explicit status been set
43
+ */
23
44
  #hasExplicitStatus = false;
45
+ /**
46
+ * Cookies serializer to serialize the outgoing cookies
47
+ */
24
48
  #cookieSerializer;
49
+ /**
50
+ * Router is used to make the redirect URLs from routes
51
+ */
25
52
  #router;
53
+ /**
54
+ * Response config
55
+ */
26
56
  #config;
57
+ /**
58
+ * Does response has body set that will written to the
59
+ * response socket at the end of the request
60
+ */
27
61
  get hasLazyBody() {
28
62
  return !!(this.lazyBody.content || this.lazyBody.fileToStream || this.lazyBody.stream);
29
63
  }
64
+ /**
65
+ * Find if the response has non-stream content
66
+ */
30
67
  get hasContent() {
31
68
  return !!this.lazyBody.content;
32
69
  }
70
+ /**
71
+ * Returns true when response body is set using "response.stream"
72
+ * method
73
+ */
33
74
  get hasStream() {
34
75
  return !!this.lazyBody.stream;
35
76
  }
77
+ /**
78
+ * Returns true when response body is set using "response.download"
79
+ * or "response.attachment" methods
80
+ */
36
81
  get hasFileToStream() {
37
82
  return !!this.lazyBody.fileToStream;
38
83
  }
84
+ /**
85
+ * Returns the response content. Check if the response
86
+ * has content using the "hasContent" method
87
+ */
39
88
  get content() {
40
89
  return this.lazyBody.content;
41
90
  }
91
+ /**
92
+ * Returns reference to the stream set using "response.stream"
93
+ * method
94
+ */
42
95
  get outgoingStream() {
43
96
  return this.lazyBody.stream?.[0];
44
97
  }
98
+ /**
99
+ * Returns reference to the file path set using "response.stream"
100
+ * method.
101
+ */
45
102
  get fileToStream() {
46
103
  return this.lazyBody.fileToStream
47
104
  ? {
@@ -50,7 +107,16 @@ export class Response extends Macroable {
50
107
  }
51
108
  : undefined;
52
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
+ */
53
115
  lazyBody = {};
116
+ /**
117
+ * The ctx will be set by the context itself. It creates a circular
118
+ * reference
119
+ */
54
120
  ctx;
55
121
  constructor(request, response, encryption, config, router, qs) {
56
122
  super();
@@ -61,30 +127,68 @@ export class Response extends Macroable {
61
127
  this.#router = router;
62
128
  this.#cookieSerializer = new CookieSerializer(encryption);
63
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
+ */
64
135
  get finished() {
65
136
  return this.response.writableFinished;
66
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
+ */
67
143
  get headersSent() {
68
144
  return this.response.headersSent;
69
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
+ */
70
151
  get isPending() {
71
152
  return !this.headersSent && !this.finished;
72
153
  }
154
+ /**
155
+ * Normalizes header value to a string or an array of string
156
+ */
73
157
  #castHeaderValue(value) {
74
158
  return Array.isArray(value) ? value.map(String) : String(value);
75
159
  }
160
+ /**
161
+ * Ends the response by flushing headers and writing body
162
+ */
76
163
  #endResponse(body, statusCode) {
77
- this.flushHeaders(statusCode);
164
+ this.writeHead(statusCode);
165
+ // avoid ArgumentsAdaptorTrampoline from V8 (inspired by fastify)
78
166
  const res = this.response;
79
167
  res.end(body, null, null);
80
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
+ */
81
179
  #getDataType(content) {
82
180
  if (Buffer.isBuffer(content)) {
83
181
  return 'buffer';
84
182
  }
183
+ /**
184
+ * Date instance
185
+ */
85
186
  if (content instanceof Date) {
86
187
  return 'date';
87
188
  }
189
+ /**
190
+ * Regular expression
191
+ */
88
192
  if (content instanceof RegExp) {
89
193
  return 'regexp';
90
194
  }
@@ -95,17 +199,34 @@ export class Response extends Macroable {
95
199
  dataType === 'bigint') {
96
200
  return dataType;
97
201
  }
202
+ /**
203
+ * Object
204
+ */
98
205
  if (dataType === 'object') {
99
206
  return 'object';
100
207
  }
101
208
  throw new RuntimeException(`Cannot serialize "${dataType}" to HTTP response`);
102
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
+ */
103
216
  writeBody(content, generateEtag, jsonpCallbackName) {
104
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
+ */
105
222
  if (hasEmptyBody) {
106
223
  this.safeStatus(204);
107
224
  }
108
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
+ */
109
230
  if (statusCode && (statusCode < 200 || statusCode === 204 || statusCode === 304)) {
110
231
  this.removeHeader('Content-Type');
111
232
  this.removeHeader('Content-Length');
@@ -113,12 +234,27 @@ export class Response extends Macroable {
113
234
  this.#endResponse();
114
235
  return;
115
236
  }
237
+ /**
238
+ * Body is empty and status code is not "204", "304" and neither under 200.
239
+ */
116
240
  if (hasEmptyBody) {
117
241
  this.removeHeader('Content-Length');
118
242
  this.#endResponse();
119
243
  return;
120
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
+ */
121
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
+ */
122
258
  if (dataType === 'object') {
123
259
  content = json.safeStringify(content);
124
260
  }
@@ -131,13 +267,39 @@ export class Response extends Macroable {
131
267
  else if (dataType === 'date') {
132
268
  content = content.toISOString();
133
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
+ */
134
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
+ */
135
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
136
288
  content = `/**/ typeof ${jsonpCallbackName} === 'function' && ${jsonpCallbackName}(${content});`;
137
289
  }
290
+ /*
291
+ * ----------------------------------------
292
+ * FINALY GENERATE AN ETAG
293
+ * ----------------------------------------
294
+ *
295
+ * Generate etag if instructed.
296
+ */
138
297
  if (generateEtag) {
139
298
  this.setEtag(content);
140
299
  }
300
+ /**
301
+ * End response when cache is fresh
302
+ */
141
303
  if (generateEtag && this.fresh()) {
142
304
  this.removeHeader('Content-Type');
143
305
  this.removeHeader('Content-Length');
@@ -145,7 +307,29 @@ export class Response extends Macroable {
145
307
  this.#endResponse(null, 304);
146
308
  return;
147
309
  }
310
+ /*
311
+ * ----------------------------------------
312
+ * SET CONTENT-LENGTH HEADER
313
+ * ----------------------------------------
314
+ */
148
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
+ */
149
333
  if (jsonpCallbackName) {
150
334
  this.header('X-Content-Type-Options', 'nosniff');
151
335
  this.safeHeader('Content-Type', 'text/javascript; charset=utf-8');
@@ -173,53 +357,110 @@ export class Response extends Macroable {
173
357
  }
174
358
  this.#endResponse(content);
175
359
  }
360
+ /**
361
+ * Stream the body to the response and handles cleaning up the stream
362
+ */
176
363
  streamBody(body, errorCallback) {
177
364
  return new Promise((resolve) => {
178
365
  let finished = false;
366
+ /*
367
+ * Listen for errors on the stream and properly destroy
368
+ * stream
369
+ */
179
370
  body.on('error', (error) => {
371
+ /* c8 ignore next 3 */
180
372
  if (finished) {
181
373
  return;
182
374
  }
183
375
  finished = true;
184
376
  destroy(body);
185
377
  this.type('text');
186
- if (typeof errorCallback === 'function') {
187
- this.#endResponse(...errorCallback(error));
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
+ }
188
385
  }
189
386
  else {
190
- this.#endResponse(error.code === 'ENOENT' ? 'File not found' : 'Cannot process file', error.code === 'ENOENT' ? 404 : 500);
191
- resolve();
387
+ this.response.destroy();
192
388
  }
389
+ resolve();
193
390
  });
194
- body.on('end', resolve);
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
+ */
195
403
  onFinished(this.response, () => {
196
404
  finished = true;
197
405
  destroy(body);
198
406
  });
407
+ /*
408
+ * Pipe stream
409
+ */
199
410
  this.flushHeaders();
200
411
  body.pipe(this.response);
201
412
  });
202
413
  }
414
+ /**
415
+ * Downloads a file by streaming it to the response
416
+ */
203
417
  async streamFileForDownload(filePath, generateEtag, errorCallback) {
204
418
  try {
205
419
  const stats = await stat(filePath);
206
420
  if (!stats || !stats.isFile()) {
207
421
  throw new TypeError('response.download only accepts path to a file');
208
422
  }
423
+ /*
424
+ * Set appropriate headers
425
+ */
209
426
  this.header('Last-Modified', stats.mtime.toUTCString());
210
427
  this.type(extname(filePath));
428
+ /*
429
+ * Set the etag when instructed.
430
+ */
211
431
  if (generateEtag) {
212
432
  this.setEtag(stats, true);
213
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
+ */
214
443
  if (this.request.method === 'HEAD') {
215
444
  this.#endResponse(null, generateEtag && this.fresh() ? 304 : 200);
216
445
  return;
217
446
  }
447
+ /*
448
+ * Regardless of request method, if we are using etags and
449
+ * cache is fresh, then we must respond with 304
450
+ */
218
451
  if (generateEtag && this.fresh()) {
219
452
  this.#endResponse(null, 304);
220
453
  return;
221
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
+ */
222
460
  this.header('Content-length', stats.size);
461
+ /*
462
+ * Finally stream the file
463
+ */
223
464
  return this.streamBody(createReadStream(filePath), errorCallback);
224
465
  }
225
466
  catch (error) {
@@ -233,20 +474,55 @@ export class Response extends Macroable {
233
474
  }
234
475
  }
235
476
  }
236
- flushHeaders(statusCode) {
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) {
237
495
  this.response.writeHead(statusCode || this.response.statusCode, this.#headers);
238
496
  return this;
239
497
  }
498
+ /**
499
+ * Returns the existing value for a given HTTP response
500
+ * header.
501
+ */
240
502
  getHeader(key) {
241
503
  const value = this.#headers[key.toLowerCase()];
242
504
  return value === undefined ? this.response.getHeader(key) : value;
243
505
  }
506
+ /**
507
+ * Get response headers
508
+ */
244
509
  getHeaders() {
245
510
  return {
246
511
  ...this.response.getHeaders(),
247
512
  ...this.#headers,
248
513
  };
249
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
+ */
250
526
  header(key, value) {
251
527
  if (value === null || value === undefined) {
252
528
  return this;
@@ -254,6 +530,17 @@ export class Response extends Macroable {
254
530
  this.#headers[key.toLowerCase()] = this.#castHeaderValue(value);
255
531
  return this;
256
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
+ */
257
544
  append(key, value) {
258
545
  if (value === null || value === undefined) {
259
546
  return this;
@@ -261,6 +548,10 @@ export class Response extends Macroable {
261
548
  key = key.toLowerCase();
262
549
  let existingHeader = this.getHeader(key);
263
550
  let casted = this.#castHeaderValue(value);
551
+ /**
552
+ * If there isn't any header, then setHeader right
553
+ * away
554
+ */
264
555
  if (!existingHeader) {
265
556
  this.#headers[key] = casted;
266
557
  return this;
@@ -272,12 +563,18 @@ export class Response extends Macroable {
272
563
  this.#headers[key] = casted;
273
564
  return this;
274
565
  }
566
+ /**
567
+ * Adds HTTP response header, when it doesn't exists already.
568
+ */
275
569
  safeHeader(key, value) {
276
570
  if (!this.getHeader(key)) {
277
571
  this.header(key, value);
278
572
  }
279
573
  return this;
280
574
  }
575
+ /**
576
+ * Removes the existing response header from being sent.
577
+ */
281
578
  removeHeader(key) {
282
579
  key = key.toLowerCase();
283
580
  this.response.removeHeader(key);
@@ -286,14 +583,24 @@ export class Response extends Macroable {
286
583
  }
287
584
  return this;
288
585
  }
586
+ /**
587
+ * Returns the status code for the response
588
+ */
289
589
  getStatus() {
290
590
  return this.response.statusCode;
291
591
  }
592
+ /**
593
+ * Set HTTP status code
594
+ */
292
595
  status(code) {
293
596
  this.#hasExplicitStatus = true;
294
597
  this.response.statusCode = code;
295
598
  return this;
296
599
  }
600
+ /**
601
+ * Set's status code only when it's not explictly
602
+ * set
603
+ */
297
604
  safeStatus(code) {
298
605
  if (this.#hasExplicitStatus) {
299
606
  return this;
@@ -301,19 +608,65 @@ export class Response extends Macroable {
301
608
  this.response.statusCode = code;
302
609
  return this;
303
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
+ */
304
623
  type(type, charset) {
305
624
  type = charset ? `${type}; charset=${charset}` : type;
306
625
  this.header('Content-Type', mime.contentType(type));
307
626
  return this;
308
627
  }
628
+ /**
629
+ * Set the Vary HTTP header
630
+ */
309
631
  vary(field) {
310
632
  vary(this.response, field);
311
633
  return this;
312
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
+ */
313
641
  setEtag(body, weak = false) {
314
642
  this.header('Etag', etag(body, { weak }));
315
643
  return this;
316
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
+ */
317
670
  fresh() {
318
671
  if (this.request.method && !CACHEABLE_HTTP_METHODS.includes(this.request.method)) {
319
672
  return false;
@@ -324,35 +677,124 @@ export class Response extends Macroable {
324
677
  }
325
678
  return false;
326
679
  }
680
+ /**
681
+ * Returns the response body. Returns null when response
682
+ * body is a stream
683
+ */
327
684
  getBody() {
328
685
  if (this.lazyBody.content) {
329
686
  return this.lazyBody.content[0];
330
687
  }
331
688
  return null;
332
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
+ */
333
697
  send(body, generateEtag = this.#config.etag) {
334
698
  this.lazyBody.content = [body, generateEtag];
335
699
  }
700
+ /**
701
+ * Alias of [[send]]
702
+ */
336
703
  json(body, generateEtag = this.#config.etag) {
337
704
  return this.send(body, generateEtag);
338
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
+ */
339
718
  jsonp(body, callbackName = this.#config.jsonpCallbackName, generateEtag = this.#config.etag) {
340
719
  this.lazyBody.content = [body, generateEtag, callbackName];
341
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
+ */
342
745
  stream(body, errorCallback) {
343
746
  if (typeof body.pipe !== 'function' || !body.readable || typeof body.read !== 'function') {
344
747
  throw new TypeError('response.stream accepts a readable stream only');
345
748
  }
346
749
  this.lazyBody.stream = [body, errorCallback];
347
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
+ */
348
776
  download(filePath, generateEtag = this.#config.etag, errorCallback) {
349
777
  this.lazyBody.fileToStream = [filePath, generateEtag, errorCallback];
350
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
+ */
351
785
  attachment(filePath, name, disposition, generateEtag, errorCallback) {
352
786
  name = name || filePath;
353
787
  this.header('Content-Disposition', contentDisposition(name, { type: disposition }));
354
788
  return this.download(filePath, generateEtag, errorCallback);
355
789
  }
790
+ /**
791
+ * Set the location header.
792
+ *
793
+ * @example
794
+ * ```js
795
+ * response.location('/login')
796
+ * ```
797
+ */
356
798
  location(url) {
357
799
  this.header('Location', url);
358
800
  return this;
@@ -370,19 +812,35 @@ export class Response extends Macroable {
370
812
  }
371
813
  return handler;
372
814
  }
815
+ /**
816
+ * Abort the request with custom body and a status code. 400 is
817
+ * used when status is not defined
818
+ */
373
819
  abort(body, status) {
374
820
  throw E_HTTP_REQUEST_ABORTED.invoke(body, status || 400);
375
821
  }
822
+ /**
823
+ * Abort the request with custom body and a status code when
824
+ * passed condition returns `true`
825
+ */
376
826
  abortIf(condition, body, status) {
377
827
  if (condition) {
378
828
  this.abort(body, status);
379
829
  }
380
830
  }
831
+ /**
832
+ * Abort the request with custom body and a status code when
833
+ * passed condition returns `false`
834
+ */
381
835
  abortUnless(condition, body, status) {
382
836
  if (!condition) {
383
837
  this.abort(body, status);
384
838
  }
385
839
  }
840
+ /**
841
+ * Set signed cookie as the response header. The inline options overrides
842
+ * all options from the config.
843
+ */
386
844
  cookie(key, value, options) {
387
845
  options = Object.assign({}, this.#config.cookie, options);
388
846
  const serialized = this.#cookieSerializer.sign(key, value, options);
@@ -392,6 +850,10 @@ export class Response extends Macroable {
392
850
  this.append('set-cookie', serialized);
393
851
  return this;
394
852
  }
853
+ /**
854
+ * Set encrypted cookie as the response header. The inline options overrides
855
+ * all options from the config.
856
+ */
395
857
  encryptedCookie(key, value, options) {
396
858
  options = Object.assign({}, this.#config.cookie, options);
397
859
  const serialized = this.#cookieSerializer.encrypt(key, value, options);
@@ -401,6 +863,10 @@ export class Response extends Macroable {
401
863
  this.append('set-cookie', serialized);
402
864
  return this;
403
865
  }
866
+ /**
867
+ * Set unsigned cookie as the response header. The inline options overrides
868
+ * all options from the config.
869
+ */
404
870
  plainCookie(key, value, options) {
405
871
  options = Object.assign({}, this.#config.cookie, options);
406
872
  const serialized = this.#cookieSerializer.encode(key, value, options);
@@ -410,6 +876,9 @@ export class Response extends Macroable {
410
876
  this.append('set-cookie', serialized);
411
877
  return this;
412
878
  }
879
+ /**
880
+ * Clear existing cookie.
881
+ */
413
882
  clearCookie(key, options) {
414
883
  options = Object.assign({}, this.#config.cookie, options);
415
884
  options.expires = new Date(1);
@@ -418,6 +887,12 @@ export class Response extends Macroable {
418
887
  this.append('set-cookie', serialized);
419
888
  return this;
420
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
+ */
421
896
  finish() {
422
897
  if (!this.isPending) {
423
898
  return;
@@ -436,170 +911,296 @@ export class Response extends Macroable {
436
911
  }
437
912
  this.#endResponse();
438
913
  }
914
+ /**
915
+ * Shorthand method to finish request with "100" status code
916
+ */
439
917
  continue() {
440
918
  this.status(100);
441
919
  return this.send(null, false);
442
920
  }
921
+ /**
922
+ * Shorthand method to finish request with "101" status code
923
+ */
443
924
  switchingProtocols() {
444
925
  this.status(101);
445
926
  return this.send(null, false);
446
927
  }
928
+ /**
929
+ * Shorthand method to finish request with "200" status code
930
+ */
447
931
  ok(body, generateEtag) {
448
932
  this.status(200);
449
933
  return this.send(body, generateEtag);
450
934
  }
935
+ /**
936
+ * Shorthand method to finish request with "201" status code
937
+ */
451
938
  created(body, generateEtag) {
452
939
  this.status(201);
453
940
  return this.send(body, generateEtag);
454
941
  }
942
+ /**
943
+ * Shorthand method to finish request with "202" status code
944
+ */
455
945
  accepted(body, generateEtag) {
456
946
  this.status(202);
457
947
  return this.send(body, generateEtag);
458
948
  }
949
+ /**
950
+ * Shorthand method to finish request with "203" status code
951
+ */
459
952
  nonAuthoritativeInformation(body, generateEtag) {
460
953
  this.status(203);
461
954
  return this.send(body, generateEtag);
462
955
  }
956
+ /**
957
+ * Shorthand method to finish request with "204" status code
958
+ */
463
959
  noContent() {
464
960
  this.status(204);
465
961
  return this.send(null, false);
466
962
  }
963
+ /**
964
+ * Shorthand method to finish request with "205" status code
965
+ */
467
966
  resetContent() {
468
967
  this.status(205);
469
968
  return this.send(null, false);
470
969
  }
970
+ /**
971
+ * Shorthand method to finish request with "206" status code
972
+ */
471
973
  partialContent(body, generateEtag) {
472
974
  this.status(206);
473
975
  return this.send(body, generateEtag);
474
976
  }
977
+ /**
978
+ * Shorthand method to finish request with "300" status code
979
+ */
475
980
  multipleChoices(body, generateEtag) {
476
981
  this.status(300);
477
982
  return this.send(body, generateEtag);
478
983
  }
984
+ /**
985
+ * Shorthand method to finish request with "301" status code
986
+ */
479
987
  movedPermanently(body, generateEtag) {
480
988
  this.status(301);
481
989
  return this.send(body, generateEtag);
482
990
  }
991
+ /**
992
+ * Shorthand method to finish request with "302" status code
993
+ */
483
994
  movedTemporarily(body, generateEtag) {
484
995
  this.status(302);
485
996
  return this.send(body, generateEtag);
486
997
  }
998
+ /**
999
+ * Shorthand method to finish request with "303" status code
1000
+ */
487
1001
  seeOther(body, generateEtag) {
488
1002
  this.status(303);
489
1003
  return this.send(body, generateEtag);
490
1004
  }
1005
+ /**
1006
+ * Shorthand method to finish request with "304" status code
1007
+ */
491
1008
  notModified(body, generateEtag) {
492
1009
  this.status(304);
493
1010
  return this.send(body, generateEtag);
494
1011
  }
1012
+ /**
1013
+ * Shorthand method to finish request with "305" status code
1014
+ */
495
1015
  useProxy(body, generateEtag) {
496
1016
  this.status(305);
497
1017
  return this.send(body, generateEtag);
498
1018
  }
1019
+ /**
1020
+ * Shorthand method to finish request with "307" status code
1021
+ */
499
1022
  temporaryRedirect(body, generateEtag) {
500
1023
  this.status(307);
501
1024
  return this.send(body, generateEtag);
502
1025
  }
1026
+ /**
1027
+ * Shorthand method to finish request with "400" status code
1028
+ */
503
1029
  badRequest(body, generateEtag) {
504
1030
  this.status(400);
505
1031
  return this.send(body, generateEtag);
506
1032
  }
1033
+ /**
1034
+ * Shorthand method to finish request with "401" status code
1035
+ */
507
1036
  unauthorized(body, generateEtag) {
508
1037
  this.status(401);
509
1038
  return this.send(body, generateEtag);
510
1039
  }
1040
+ /**
1041
+ * Shorthand method to finish request with "402" status code
1042
+ */
511
1043
  paymentRequired(body, generateEtag) {
512
1044
  this.status(402);
513
1045
  return this.send(body, generateEtag);
514
1046
  }
1047
+ /**
1048
+ * Shorthand method to finish request with "403" status code
1049
+ */
515
1050
  forbidden(body, generateEtag) {
516
1051
  this.status(403);
517
1052
  return this.send(body, generateEtag);
518
1053
  }
1054
+ /**
1055
+ * Shorthand method to finish request with "404" status code
1056
+ */
519
1057
  notFound(body, generateEtag) {
520
1058
  this.status(404);
521
1059
  return this.send(body, generateEtag);
522
1060
  }
1061
+ /**
1062
+ * Shorthand method to finish request with "405" status code
1063
+ */
523
1064
  methodNotAllowed(body, generateEtag) {
524
1065
  this.status(405);
525
1066
  return this.send(body, generateEtag);
526
1067
  }
1068
+ /**
1069
+ * Shorthand method to finish request with "406" status code
1070
+ */
527
1071
  notAcceptable(body, generateEtag) {
528
1072
  this.status(406);
529
1073
  return this.send(body, generateEtag);
530
1074
  }
1075
+ /**
1076
+ * Shorthand method to finish request with "407" status code
1077
+ */
531
1078
  proxyAuthenticationRequired(body, generateEtag) {
532
1079
  this.status(407);
533
1080
  return this.send(body, generateEtag);
534
1081
  }
1082
+ /**
1083
+ * Shorthand method to finish request with "408" status code
1084
+ */
535
1085
  requestTimeout(body, generateEtag) {
536
1086
  this.status(408);
537
1087
  return this.send(body, generateEtag);
538
1088
  }
1089
+ /**
1090
+ * Shorthand method to finish request with "409" status code
1091
+ */
539
1092
  conflict(body, generateEtag) {
540
1093
  this.status(409);
541
1094
  return this.send(body, generateEtag);
542
1095
  }
1096
+ /**
1097
+ * Shorthand method to finish request with "401" status code
1098
+ */
543
1099
  gone(body, generateEtag) {
544
1100
  this.status(410);
545
1101
  return this.send(body, generateEtag);
546
1102
  }
1103
+ /**
1104
+ * Shorthand method to finish request with "411" status code
1105
+ */
547
1106
  lengthRequired(body, generateEtag) {
548
1107
  this.status(411);
549
1108
  return this.send(body, generateEtag);
550
1109
  }
1110
+ /**
1111
+ * Shorthand method to finish request with "412" status code
1112
+ */
551
1113
  preconditionFailed(body, generateEtag) {
552
1114
  this.status(412);
553
1115
  return this.send(body, generateEtag);
554
1116
  }
1117
+ /**
1118
+ * Shorthand method to finish request with "413" status code
1119
+ */
555
1120
  requestEntityTooLarge(body, generateEtag) {
556
1121
  this.status(413);
557
1122
  return this.send(body, generateEtag);
558
1123
  }
1124
+ /**
1125
+ * Shorthand method to finish request with "414" status code
1126
+ */
559
1127
  requestUriTooLong(body, generateEtag) {
560
1128
  this.status(414);
561
1129
  return this.send(body, generateEtag);
562
1130
  }
1131
+ /**
1132
+ * Shorthand method to finish request with "415" status code
1133
+ */
563
1134
  unsupportedMediaType(body, generateEtag) {
564
1135
  this.status(415);
565
1136
  return this.send(body, generateEtag);
566
1137
  }
1138
+ /**
1139
+ * Shorthand method to finish request with "416" status code
1140
+ */
567
1141
  requestedRangeNotSatisfiable(body, generateEtag) {
568
1142
  this.status(416);
569
1143
  return this.send(body, generateEtag);
570
1144
  }
1145
+ /**
1146
+ * Shorthand method to finish request with "417" status code
1147
+ */
571
1148
  expectationFailed(body, generateEtag) {
572
1149
  this.status(417);
573
1150
  return this.send(body, generateEtag);
574
1151
  }
1152
+ /**
1153
+ * Shorthand method to finish request with "422" status code
1154
+ */
575
1155
  unprocessableEntity(body, generateEtag) {
576
1156
  this.status(422);
577
1157
  return this.send(body, generateEtag);
578
1158
  }
1159
+ /**
1160
+ * Shorthand method to finish request with "429" status code
1161
+ */
579
1162
  tooManyRequests(body, generateEtag) {
580
1163
  this.status(429);
581
1164
  return this.send(body, generateEtag);
582
1165
  }
1166
+ /**
1167
+ * Shorthand method to finish request with "500" status code
1168
+ */
583
1169
  internalServerError(body, generateEtag) {
584
1170
  this.status(500);
585
1171
  return this.send(body, generateEtag);
586
1172
  }
1173
+ /**
1174
+ * Shorthand method to finish request with "501" status code
1175
+ */
587
1176
  notImplemented(body, generateEtag) {
588
1177
  this.status(501);
589
1178
  return this.send(body, generateEtag);
590
1179
  }
1180
+ /**
1181
+ * Shorthand method to finish request with "502" status code
1182
+ */
591
1183
  badGateway(body, generateEtag) {
592
1184
  this.status(502);
593
1185
  return this.send(body, generateEtag);
594
1186
  }
1187
+ /**
1188
+ * Shorthand method to finish request with "503" status code
1189
+ */
595
1190
  serviceUnavailable(body, generateEtag) {
596
1191
  this.status(503);
597
1192
  return this.send(body, generateEtag);
598
1193
  }
1194
+ /**
1195
+ * Shorthand method to finish request with "504" status code
1196
+ */
599
1197
  gatewayTimeout(body, generateEtag) {
600
1198
  this.status(504);
601
1199
  return this.send(body, generateEtag);
602
1200
  }
1201
+ /**
1202
+ * Shorthand method to finish request with "505" status code
1203
+ */
603
1204
  httpVersionNotSupported(body, generateEtag) {
604
1205
  this.status(505);
605
1206
  return this.send(body, generateEtag);