@adonisjs/http-server 6.8.2-9 → 7.0.0-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/src/define_config.d.ts +5 -1
- package/build/src/define_config.js +18 -1
- package/build/src/exception_handler.d.ts +24 -23
- package/build/src/exception_handler.js +43 -40
- package/build/src/helpers.js +21 -0
- package/build/src/response.d.ts +82 -2
- package/build/src/response.js +2 -2
- package/build/src/router/executor.d.ts +2 -1
- package/build/src/router/executor.js +2 -1
- package/build/src/server/factories/final_handler.d.ts +2 -1
- package/build/src/server/factories/final_handler.js +2 -2
- package/build/src/server/main.d.ts +1 -1
- package/build/src/server/main.js +14 -5
- package/build/src/types/response.d.ts +2 -2
- package/build/src/types/route.d.ts +2 -1
- package/build/src/types/server.d.ts +1 -1
- package/package.json +61 -49
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { ServerConfig } from './types/server.js';
|
|
2
|
+
type UserDefinedServerConfig = Partial<Omit<ServerConfig, 'trustProxy'> & {
|
|
3
|
+
trustProxy: ((address: string, distance: number) => boolean) | boolean | string;
|
|
4
|
+
}>;
|
|
2
5
|
/**
|
|
3
6
|
* Define configuration for the HTTP server
|
|
4
7
|
*/
|
|
5
|
-
export declare function defineConfig(config:
|
|
8
|
+
export declare function defineConfig(config: UserDefinedServerConfig): ServerConfig;
|
|
9
|
+
export {};
|
|
@@ -12,6 +12,7 @@ import string from '@poppinss/utils/string';
|
|
|
12
12
|
* Define configuration for the HTTP server
|
|
13
13
|
*/
|
|
14
14
|
export function defineConfig(config) {
|
|
15
|
+
const { trustProxy, ...rest } = config;
|
|
15
16
|
const normalizedConfig = {
|
|
16
17
|
allowMethodSpoofing: false,
|
|
17
18
|
trustProxy: proxyAddr.compile('loopback'),
|
|
@@ -42,10 +43,26 @@ export function defineConfig(config) {
|
|
|
42
43
|
skipNulls: false,
|
|
43
44
|
},
|
|
44
45
|
},
|
|
45
|
-
...
|
|
46
|
+
...rest,
|
|
46
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* Normalizing maxAge property on cookies to be a number in
|
|
50
|
+
* seconds
|
|
51
|
+
*/
|
|
47
52
|
if (normalizedConfig.cookie.maxAge) {
|
|
48
53
|
normalizedConfig.cookie.maxAge = string.seconds.parse(normalizedConfig.cookie.maxAge);
|
|
49
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Normalizing trust proxy setting to allow boolean and
|
|
57
|
+
* string values
|
|
58
|
+
*/
|
|
59
|
+
if (typeof trustProxy === 'boolean') {
|
|
60
|
+
const tpValue = trustProxy;
|
|
61
|
+
normalizedConfig.trustProxy = (_, __) => tpValue;
|
|
62
|
+
}
|
|
63
|
+
else if (typeof trustProxy === 'string') {
|
|
64
|
+
const tpValue = trustProxy;
|
|
65
|
+
normalizedConfig.trustProxy = proxyAddr.compile(tpValue);
|
|
66
|
+
}
|
|
50
67
|
return normalizedConfig;
|
|
51
68
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Macroable from '@poppinss/macroable';
|
|
1
2
|
import type { Level } from '@adonisjs/logger/types';
|
|
2
3
|
import type { HttpContext } from './http_context/main.js';
|
|
3
4
|
import type { HttpError, StatusPageRange, StatusPageRenderer } from './types/server.js';
|
|
@@ -13,7 +14,7 @@ import type { HttpError, StatusPageRange, StatusPageRenderer } from './types/ser
|
|
|
13
14
|
* - Transforming errors to JSON or HTML using content negotiation
|
|
14
15
|
* - Reporting errors
|
|
15
16
|
*/
|
|
16
|
-
export declare class ExceptionHandler {
|
|
17
|
+
export declare class ExceptionHandler extends Macroable {
|
|
17
18
|
#private;
|
|
18
19
|
/**
|
|
19
20
|
* Whether or not to render debug info. When set to true, the errors
|
|
@@ -53,54 +54,54 @@ export declare class ExceptionHandler {
|
|
|
53
54
|
* Error reporting context
|
|
54
55
|
*/
|
|
55
56
|
protected context(ctx: HttpContext): any;
|
|
57
|
+
/**
|
|
58
|
+
* Returns the log level for an error based upon the error
|
|
59
|
+
* status code.
|
|
60
|
+
*/
|
|
61
|
+
protected getErrorLogLevel(error: HttpError): Level;
|
|
62
|
+
/**
|
|
63
|
+
* A boolean to control if errors should be rendered with
|
|
64
|
+
* all the available debugging info.
|
|
65
|
+
*/
|
|
66
|
+
protected isDebuggingEnabled(_: HttpContext): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Returns a boolean by checking if an error should be reported.
|
|
69
|
+
*/
|
|
70
|
+
protected shouldReport(error: HttpError): boolean;
|
|
56
71
|
/**
|
|
57
72
|
* Renders an error to JSON response
|
|
58
73
|
*/
|
|
59
|
-
|
|
74
|
+
renderErrorAsJSON(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
60
75
|
/**
|
|
61
76
|
* Renders an error to JSON API response
|
|
62
77
|
*/
|
|
63
|
-
|
|
78
|
+
renderErrorAsJSONAPI(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
64
79
|
/**
|
|
65
80
|
* Renders an error to HTML response
|
|
66
81
|
*/
|
|
67
|
-
|
|
82
|
+
renderErrorAsHTML(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
68
83
|
/**
|
|
69
84
|
* Renders the validation error message to a JSON
|
|
70
85
|
* response
|
|
71
86
|
*/
|
|
72
|
-
|
|
87
|
+
renderValidationErrorAsJSON(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
73
88
|
/**
|
|
74
89
|
* Renders the validation error message as per JSON API
|
|
75
90
|
* spec
|
|
76
91
|
*/
|
|
77
|
-
|
|
92
|
+
renderValidationErrorAsJSONAPI(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
78
93
|
/**
|
|
79
94
|
* Renders the validation error as an HTML string
|
|
80
95
|
*/
|
|
81
|
-
|
|
96
|
+
renderValidationErrorAsHTML(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
82
97
|
/**
|
|
83
98
|
* Renders the error to response
|
|
84
99
|
*/
|
|
85
|
-
|
|
100
|
+
renderError(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
86
101
|
/**
|
|
87
102
|
* Renders the validation error to response
|
|
88
103
|
*/
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Returns the log level for an error based upon the error
|
|
92
|
-
* status code.
|
|
93
|
-
*/
|
|
94
|
-
protected getErrorLogLevel(error: HttpError): Level;
|
|
95
|
-
/**
|
|
96
|
-
* A boolean to control if errors should be rendered with
|
|
97
|
-
* all the available debugging info.
|
|
98
|
-
*/
|
|
99
|
-
protected isDebuggingEnabled(_: HttpContext): boolean;
|
|
100
|
-
/**
|
|
101
|
-
* Returns a boolean by checking if an error should be reported.
|
|
102
|
-
*/
|
|
103
|
-
protected shouldReport(error: HttpError): boolean;
|
|
104
|
+
renderValidationError(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
104
105
|
/**
|
|
105
106
|
* Reports an error during an HTTP request
|
|
106
107
|
*/
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* file that was distributed with this source code.
|
|
8
8
|
*/
|
|
9
9
|
import is from '@sindresorhus/is';
|
|
10
|
+
import Macroable from '@poppinss/macroable';
|
|
10
11
|
import { parseRange } from './helpers.js';
|
|
11
12
|
import * as errors from './exceptions.js';
|
|
12
13
|
/**
|
|
@@ -21,7 +22,7 @@ import * as errors from './exceptions.js';
|
|
|
21
22
|
* - Transforming errors to JSON or HTML using content negotiation
|
|
22
23
|
* - Reporting errors
|
|
23
24
|
*/
|
|
24
|
-
export class ExceptionHandler {
|
|
25
|
+
export class ExceptionHandler extends Macroable {
|
|
25
26
|
/**
|
|
26
27
|
* Computed from the status pages property
|
|
27
28
|
*/
|
|
@@ -99,6 +100,44 @@ export class ExceptionHandler {
|
|
|
99
100
|
}
|
|
100
101
|
: {};
|
|
101
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Returns the log level for an error based upon the error
|
|
105
|
+
* status code.
|
|
106
|
+
*/
|
|
107
|
+
getErrorLogLevel(error) {
|
|
108
|
+
if (error.status >= 500) {
|
|
109
|
+
return 'error';
|
|
110
|
+
}
|
|
111
|
+
if (error.status >= 400) {
|
|
112
|
+
return 'warn';
|
|
113
|
+
}
|
|
114
|
+
return 'info';
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* A boolean to control if errors should be rendered with
|
|
118
|
+
* all the available debugging info.
|
|
119
|
+
*/
|
|
120
|
+
isDebuggingEnabled(_) {
|
|
121
|
+
return this.debug;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Returns a boolean by checking if an error should be reported.
|
|
125
|
+
*/
|
|
126
|
+
shouldReport(error) {
|
|
127
|
+
if (this.reportErrors === false) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
if (this.ignoreStatuses.includes(error.status)) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
if (error.code && this.ignoreCodes.includes(error.code)) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
if (this.ignoreExceptions.find((exception) => error instanceof exception)) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
102
141
|
/**
|
|
103
142
|
* Renders an error to JSON response
|
|
104
143
|
*/
|
|
@@ -137,7 +176,9 @@ export class ExceptionHandler {
|
|
|
137
176
|
async renderErrorAsHTML(error, ctx) {
|
|
138
177
|
if (this.isDebuggingEnabled(ctx)) {
|
|
139
178
|
const { default: Youch } = await import('youch');
|
|
140
|
-
const html = await new Youch(error, ctx.request.request).toHTML(
|
|
179
|
+
const html = await new Youch(error, ctx.request.request).toHTML({
|
|
180
|
+
cspNonce: 'nonce' in ctx.response ? ctx.response.nonce : undefined,
|
|
181
|
+
});
|
|
141
182
|
ctx.response.status(error.status).send(html);
|
|
142
183
|
return;
|
|
143
184
|
}
|
|
@@ -211,44 +252,6 @@ export class ExceptionHandler {
|
|
|
211
252
|
return this.renderValidationErrorAsHTML(error, ctx);
|
|
212
253
|
}
|
|
213
254
|
}
|
|
214
|
-
/**
|
|
215
|
-
* Returns the log level for an error based upon the error
|
|
216
|
-
* status code.
|
|
217
|
-
*/
|
|
218
|
-
getErrorLogLevel(error) {
|
|
219
|
-
if (error.status >= 500) {
|
|
220
|
-
return 'error';
|
|
221
|
-
}
|
|
222
|
-
if (error.status >= 400) {
|
|
223
|
-
return 'warn';
|
|
224
|
-
}
|
|
225
|
-
return 'info';
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* A boolean to control if errors should be rendered with
|
|
229
|
-
* all the available debugging info.
|
|
230
|
-
*/
|
|
231
|
-
isDebuggingEnabled(_) {
|
|
232
|
-
return this.debug;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Returns a boolean by checking if an error should be reported.
|
|
236
|
-
*/
|
|
237
|
-
shouldReport(error) {
|
|
238
|
-
if (this.reportErrors === false) {
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
if (this.ignoreStatuses.includes(error.status)) {
|
|
242
|
-
return false;
|
|
243
|
-
}
|
|
244
|
-
if (error.code && this.ignoreCodes.includes(error.code)) {
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
if (this.ignoreExceptions.find((exception) => error instanceof exception)) {
|
|
248
|
-
return false;
|
|
249
|
-
}
|
|
250
|
-
return true;
|
|
251
|
-
}
|
|
252
255
|
/**
|
|
253
256
|
* Reports an error during an HTTP request
|
|
254
257
|
*/
|
package/build/src/helpers.js
CHANGED
|
@@ -66,17 +66,38 @@ export function parseRange(range, value) {
|
|
|
66
66
|
const parts = range.split('..');
|
|
67
67
|
const min = Number(parts[0]);
|
|
68
68
|
const max = Number(parts[1]);
|
|
69
|
+
/**
|
|
70
|
+
* The ending status code does not exists
|
|
71
|
+
*/
|
|
72
|
+
if (parts.length === 1 && !Number.isNaN(min)) {
|
|
73
|
+
return {
|
|
74
|
+
[min]: value,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The starting status code is not a number
|
|
79
|
+
*/
|
|
69
80
|
if (Number.isNaN(min) || Number.isNaN(max)) {
|
|
70
81
|
return {};
|
|
71
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Min and max are same
|
|
85
|
+
*/
|
|
72
86
|
if (min === max) {
|
|
73
87
|
return {
|
|
74
88
|
[min]: value,
|
|
75
89
|
};
|
|
76
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Max cannot be smaller than min
|
|
93
|
+
*/
|
|
77
94
|
if (max < min) {
|
|
78
95
|
throw new InvalidArgumentsException(`Invalid range "${range}"`);
|
|
79
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Loop over the range and create a collection
|
|
99
|
+
* of status codes
|
|
100
|
+
*/
|
|
80
101
|
return [...Array(max - min + 1).keys()].reduce((result, step) => {
|
|
81
102
|
result[min + step] = value;
|
|
82
103
|
return result;
|
package/build/src/response.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
3
4
|
import Macroable from '@poppinss/macroable';
|
|
4
5
|
import type { Encryption } from '@adonisjs/encryption';
|
|
5
6
|
import { ServerResponse, IncomingMessage } from 'node:http';
|
|
@@ -44,7 +45,7 @@ export declare class Response extends Macroable {
|
|
|
44
45
|
* Returns reference to the stream set using "response.stream"
|
|
45
46
|
* method
|
|
46
47
|
*/
|
|
47
|
-
get outgoingStream():
|
|
48
|
+
get outgoingStream(): import("stream").Readable | undefined;
|
|
48
49
|
/**
|
|
49
50
|
* Returns reference to the file path set using "response.stream"
|
|
50
51
|
* method.
|
|
@@ -106,7 +107,7 @@ export declare class Response extends Macroable {
|
|
|
106
107
|
* Writes headers with the Node.js res object using the
|
|
107
108
|
* response.setHeader method
|
|
108
109
|
*/
|
|
109
|
-
|
|
110
|
+
relayHeaders(): void;
|
|
110
111
|
/**
|
|
111
112
|
* Calls res.writeHead on the Node.js res object.
|
|
112
113
|
*/
|
|
@@ -121,6 +122,85 @@ export declare class Response extends Macroable {
|
|
|
121
122
|
*/
|
|
122
123
|
getHeaders(): {
|
|
123
124
|
[x: string]: import("http").OutgoingHttpHeader | undefined;
|
|
125
|
+
accept?: string | string[] | undefined;
|
|
126
|
+
"accept-charset"?: string | string[] | undefined;
|
|
127
|
+
"accept-encoding"?: string | string[] | undefined;
|
|
128
|
+
"accept-language"?: string | string[] | undefined;
|
|
129
|
+
"accept-ranges"?: string | undefined;
|
|
130
|
+
"access-control-allow-credentials"?: string | undefined;
|
|
131
|
+
"access-control-allow-headers"?: string | undefined;
|
|
132
|
+
"access-control-allow-methods"?: string | undefined;
|
|
133
|
+
"access-control-allow-origin"?: string | undefined;
|
|
134
|
+
"access-control-expose-headers"?: string | undefined;
|
|
135
|
+
"access-control-max-age"?: string | undefined;
|
|
136
|
+
"access-control-request-headers"?: string | undefined;
|
|
137
|
+
"access-control-request-method"?: string | undefined;
|
|
138
|
+
age?: string | undefined;
|
|
139
|
+
allow?: string | undefined;
|
|
140
|
+
authorization?: string | undefined;
|
|
141
|
+
"cache-control"?: string | undefined;
|
|
142
|
+
"cdn-cache-control"?: string | undefined;
|
|
143
|
+
connection?: string | string[] | undefined;
|
|
144
|
+
"content-disposition"?: string | undefined;
|
|
145
|
+
"content-encoding"?: string | undefined;
|
|
146
|
+
"content-language"?: string | undefined;
|
|
147
|
+
"content-length"?: string | number | undefined;
|
|
148
|
+
"content-location"?: string | undefined;
|
|
149
|
+
"content-range"?: string | undefined;
|
|
150
|
+
"content-security-policy"?: string | undefined;
|
|
151
|
+
"content-security-policy-report-only"?: string | undefined;
|
|
152
|
+
cookie?: string | string[] | undefined;
|
|
153
|
+
dav?: string | string[] | undefined;
|
|
154
|
+
dnt?: string | undefined;
|
|
155
|
+
date?: string | undefined;
|
|
156
|
+
etag?: string | undefined;
|
|
157
|
+
expect?: string | undefined;
|
|
158
|
+
expires?: string | undefined;
|
|
159
|
+
forwarded?: string | undefined;
|
|
160
|
+
from?: string | undefined;
|
|
161
|
+
host?: string | undefined;
|
|
162
|
+
"if-match"?: string | undefined;
|
|
163
|
+
"if-modified-since"?: string | undefined;
|
|
164
|
+
"if-none-match"?: string | undefined;
|
|
165
|
+
"if-range"?: string | undefined;
|
|
166
|
+
"if-unmodified-since"?: string | undefined;
|
|
167
|
+
"last-modified"?: string | undefined;
|
|
168
|
+
link?: string | string[] | undefined;
|
|
169
|
+
location?: string | undefined;
|
|
170
|
+
"max-forwards"?: string | undefined;
|
|
171
|
+
origin?: string | undefined;
|
|
172
|
+
prgama?: string | string[] | undefined;
|
|
173
|
+
"proxy-authenticate"?: string | string[] | undefined;
|
|
174
|
+
"proxy-authorization"?: string | undefined;
|
|
175
|
+
"public-key-pins"?: string | undefined;
|
|
176
|
+
"public-key-pins-report-only"?: string | undefined;
|
|
177
|
+
range?: string | undefined;
|
|
178
|
+
referer?: string | undefined;
|
|
179
|
+
"referrer-policy"?: string | undefined;
|
|
180
|
+
refresh?: string | undefined;
|
|
181
|
+
"retry-after"?: string | undefined;
|
|
182
|
+
"sec-websocket-accept"?: string | undefined;
|
|
183
|
+
"sec-websocket-extensions"?: string | string[] | undefined;
|
|
184
|
+
"sec-websocket-key"?: string | undefined;
|
|
185
|
+
"sec-websocket-protocol"?: string | string[] | undefined;
|
|
186
|
+
"sec-websocket-version"?: string | undefined;
|
|
187
|
+
server?: string | undefined;
|
|
188
|
+
"set-cookie"?: string | string[] | undefined;
|
|
189
|
+
"strict-transport-security"?: string | undefined;
|
|
190
|
+
te?: string | undefined;
|
|
191
|
+
trailer?: string | undefined;
|
|
192
|
+
"transfer-encoding"?: string | undefined;
|
|
193
|
+
"user-agent"?: string | undefined;
|
|
194
|
+
upgrade?: string | undefined;
|
|
195
|
+
"upgrade-insecure-requests"?: string | undefined;
|
|
196
|
+
vary?: string | undefined;
|
|
197
|
+
via?: string | string[] | undefined;
|
|
198
|
+
warning?: string | undefined;
|
|
199
|
+
"www-authenticate"?: string | string[] | undefined;
|
|
200
|
+
"x-content-type-options"?: string | undefined;
|
|
201
|
+
"x-dns-prefetch-control"?: string | undefined;
|
|
202
|
+
"x-frame-options"?: string | undefined;
|
|
203
|
+
"x-xss-protection"?: string | undefined;
|
|
124
204
|
};
|
|
125
205
|
/**
|
|
126
206
|
* Set header on the response. To `append` values to the existing header, we suggest
|
package/build/src/response.js
CHANGED
|
@@ -407,7 +407,7 @@ export class Response extends Macroable {
|
|
|
407
407
|
/*
|
|
408
408
|
* Pipe stream
|
|
409
409
|
*/
|
|
410
|
-
this.
|
|
410
|
+
this.relayHeaders();
|
|
411
411
|
body.pipe(this.response);
|
|
412
412
|
});
|
|
413
413
|
}
|
|
@@ -478,7 +478,7 @@ export class Response extends Macroable {
|
|
|
478
478
|
* Writes headers with the Node.js res object using the
|
|
479
479
|
* response.setHeader method
|
|
480
480
|
*/
|
|
481
|
-
|
|
481
|
+
relayHeaders() {
|
|
482
482
|
if (!this.headersSent) {
|
|
483
483
|
for (let key in this.#headers) {
|
|
484
484
|
const value = this.#headers[key];
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { ContainerResolver } from '@adonisjs/fold';
|
|
2
2
|
import type { StoreRouteNode } from '../types/route.js';
|
|
3
3
|
import type { HttpContext } from '../http_context/main.js';
|
|
4
|
+
import type { ServerErrorHandler } from '../types/server.js';
|
|
4
5
|
/**
|
|
5
6
|
* Executor to execute the route middleware pipeline the route
|
|
6
7
|
* handler
|
|
7
8
|
*/
|
|
8
|
-
export declare function execute(route: StoreRouteNode, resolver: ContainerResolver<any>, ctx: HttpContext): Promise<void>;
|
|
9
|
+
export declare function execute(route: StoreRouteNode, resolver: ContainerResolver<any>, ctx: HttpContext, errorResponder: ServerErrorHandler['handle']): Promise<void>;
|
|
@@ -11,9 +11,10 @@ import { useReturnValue } from './factories/use_return_value.js';
|
|
|
11
11
|
* Executor to execute the route middleware pipeline the route
|
|
12
12
|
* handler
|
|
13
13
|
*/
|
|
14
|
-
export function execute(route, resolver, ctx) {
|
|
14
|
+
export function execute(route, resolver, ctx, errorResponder) {
|
|
15
15
|
return route.middleware
|
|
16
16
|
.runner()
|
|
17
|
+
.errorHandler((error) => errorResponder(error, ctx))
|
|
17
18
|
.finalHandler(async () => {
|
|
18
19
|
if (typeof route.handler === 'function') {
|
|
19
20
|
return Promise.resolve(route.handler(ctx)).then(useReturnValue(ctx));
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { ContainerResolver } from '@adonisjs/fold';
|
|
2
2
|
import type { Router } from '../../router/main.js';
|
|
3
3
|
import type { HttpContext } from '../../http_context/main.js';
|
|
4
|
+
import type { ServerErrorHandler } from '../../types/server.js';
|
|
4
5
|
/**
|
|
5
6
|
* The final handler is executed after the server middleware stack.
|
|
6
7
|
* It looks for a matching route and executes the route middleware
|
|
7
8
|
* stack.
|
|
8
9
|
*/
|
|
9
|
-
export declare function finalHandler(router: Router, resolver: ContainerResolver<any>, ctx: HttpContext): () => any;
|
|
10
|
+
export declare function finalHandler(router: Router, resolver: ContainerResolver<any>, ctx: HttpContext, errorResponder: ServerErrorHandler['handle']): () => any;
|
|
@@ -12,7 +12,7 @@ import * as errors from '../../exceptions.js';
|
|
|
12
12
|
* It looks for a matching route and executes the route middleware
|
|
13
13
|
* stack.
|
|
14
14
|
*/
|
|
15
|
-
export function finalHandler(router, resolver, ctx) {
|
|
15
|
+
export function finalHandler(router, resolver, ctx, errorResponder) {
|
|
16
16
|
return function () {
|
|
17
17
|
const url = ctx.request.url();
|
|
18
18
|
const method = ctx.request.method();
|
|
@@ -23,7 +23,7 @@ export function finalHandler(router, resolver, ctx) {
|
|
|
23
23
|
ctx.subdomains = route.subdomains;
|
|
24
24
|
ctx.route = route.route;
|
|
25
25
|
ctx.routeKey = route.routeKey;
|
|
26
|
-
return route.route.execute(route.route, resolver, ctx);
|
|
26
|
+
return route.route.execute(route.route, resolver, ctx, errorResponder);
|
|
27
27
|
}
|
|
28
28
|
return Promise.reject(new errors.E_ROUTE_NOT_FOUND([method, url]));
|
|
29
29
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
-
import { Emitter } from '@adonisjs/events';
|
|
4
3
|
import type { Logger } from '@adonisjs/logger';
|
|
4
|
+
import type { Emitter } from '@adonisjs/events';
|
|
5
5
|
import type { Encryption } from '@adonisjs/encryption';
|
|
6
6
|
import type { Server as HttpsServer } from 'node:https';
|
|
7
7
|
import type { Application } from '@adonisjs/application';
|
package/build/src/server/main.js
CHANGED
|
@@ -84,6 +84,18 @@ export class Server {
|
|
|
84
84
|
* Middleware store to be shared with the routes
|
|
85
85
|
*/
|
|
86
86
|
#middleware = [];
|
|
87
|
+
/**
|
|
88
|
+
* The request error response is attached to the middleware
|
|
89
|
+
* pipeline to intercept errors and invoke the user
|
|
90
|
+
* registered error handler.
|
|
91
|
+
*
|
|
92
|
+
* We share this with the route middleware pipeline as well,
|
|
93
|
+
* so that it does not throw any exceptions
|
|
94
|
+
*/
|
|
95
|
+
#requestErrorResponder = (error, ctx) => {
|
|
96
|
+
this.#resolvedErrorHandler.report(error, ctx);
|
|
97
|
+
return this.#resolvedErrorHandler.handle(error, ctx);
|
|
98
|
+
};
|
|
87
99
|
/**
|
|
88
100
|
* Know if async local storage is enabled or not.
|
|
89
101
|
*/
|
|
@@ -127,11 +139,8 @@ export class Server {
|
|
|
127
139
|
*/
|
|
128
140
|
#handleRequest(ctx, resolver) {
|
|
129
141
|
return this.#serverMiddlewareStack.runner()
|
|
130
|
-
.errorHandler((error) =>
|
|
131
|
-
this.#
|
|
132
|
-
return this.#resolvedErrorHandler.handle(error, ctx);
|
|
133
|
-
})
|
|
134
|
-
.finalHandler(finalHandler(this.#router, resolver, ctx))
|
|
142
|
+
.errorHandler((error) => this.#requestErrorResponder(error, ctx))
|
|
143
|
+
.finalHandler(finalHandler(this.#router, resolver, ctx, this.#requestErrorResponder))
|
|
135
144
|
.run(middlewareHandler(resolver, ctx))
|
|
136
145
|
.catch((error) => {
|
|
137
146
|
ctx.logger.fatal({ err: error }, 'Exception raised by error handler');
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
|
|
2
|
+
import { Readable } from 'node:stream';
|
|
3
3
|
/**
|
|
4
4
|
* Cookie options can that can be set on the response
|
|
5
5
|
*/
|
|
@@ -42,4 +42,4 @@ export type ResponseConfig = {
|
|
|
42
42
|
/**
|
|
43
43
|
* Stream that can be piped to the "response.stream" method
|
|
44
44
|
*/
|
|
45
|
-
export type ResponseStream =
|
|
45
|
+
export type ResponseStream = Readable;
|
|
@@ -3,6 +3,7 @@ import type { ContainerResolver } from '@adonisjs/fold';
|
|
|
3
3
|
import type { Constructor, LazyImport } from './base.js';
|
|
4
4
|
import type { HttpContext } from '../http_context/main.js';
|
|
5
5
|
import type { MiddlewareFn, ParsedGlobalMiddleware } from './middleware.js';
|
|
6
|
+
import { ServerErrorHandler } from './server.js';
|
|
6
7
|
/**
|
|
7
8
|
* Returns a union of methods from a controller that accepts
|
|
8
9
|
* the context as the first argument.
|
|
@@ -45,7 +46,7 @@ export type StoreRouteNode = {
|
|
|
45
46
|
* The execute function to execute the route middleware
|
|
46
47
|
* and the handler
|
|
47
48
|
*/
|
|
48
|
-
execute: (route: StoreRouteNode, resolver: ContainerResolver<any>, ctx: HttpContext) => any;
|
|
49
|
+
execute: (route: StoreRouteNode, resolver: ContainerResolver<any>, ctx: HttpContext, errorResponder: ServerErrorHandler['handle']) => any;
|
|
49
50
|
/**
|
|
50
51
|
* A unique name for the route
|
|
51
52
|
*/
|
|
@@ -30,7 +30,7 @@ export interface TestingMiddlewarePipeline {
|
|
|
30
30
|
/**
|
|
31
31
|
* The expression to define a status page range
|
|
32
32
|
*/
|
|
33
|
-
export type StatusPageRange = `${number}..${number}
|
|
33
|
+
export type StatusPageRange = `${number}..${number}` | `${number}` | number;
|
|
34
34
|
/**
|
|
35
35
|
* The callback function to render status page for a given
|
|
36
36
|
* error.
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adonisjs/http-server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0-1",
|
|
4
4
|
"description": "AdonisJS HTTP server with support packed with Routing and Cookies",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
8
|
-
"build/src",
|
|
9
8
|
"build/factories",
|
|
9
|
+
"build/src",
|
|
10
10
|
"build/index.d.ts",
|
|
11
11
|
"build/index.js"
|
|
12
12
|
],
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"compile": "npm run lint && npm run clean && tsc",
|
|
27
27
|
"build": "npm run compile",
|
|
28
28
|
"prebenchmark": "npm run build",
|
|
29
|
-
"benchmark": "node
|
|
29
|
+
"benchmark": "node benchmarks/index.js",
|
|
30
30
|
"release": "np",
|
|
31
31
|
"version": "npm run build",
|
|
32
32
|
"format": "prettier --write .",
|
|
@@ -43,67 +43,67 @@
|
|
|
43
43
|
"author": "virk,adonisjs",
|
|
44
44
|
"license": "MIT",
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@adonisjs/application": "^
|
|
47
|
-
"@adonisjs/encryption": "^5.1.2-
|
|
46
|
+
"@adonisjs/application": "^8.0.0-0",
|
|
47
|
+
"@adonisjs/encryption": "^5.1.2-3",
|
|
48
48
|
"@adonisjs/eslint-config": "^1.1.8",
|
|
49
|
-
"@adonisjs/events": "^
|
|
50
|
-
"@adonisjs/fold": "^9.9.3-
|
|
51
|
-
"@adonisjs/logger": "^5.4.2-
|
|
49
|
+
"@adonisjs/events": "^9.0.0-0",
|
|
50
|
+
"@adonisjs/fold": "^9.9.3-10",
|
|
51
|
+
"@adonisjs/logger": "^5.4.2-6",
|
|
52
52
|
"@adonisjs/prettier-config": "^1.1.8",
|
|
53
53
|
"@adonisjs/tsconfig": "^1.1.8",
|
|
54
|
-
"@commitlint/cli": "^17.
|
|
55
|
-
"@commitlint/config-conventional": "^17.
|
|
54
|
+
"@commitlint/cli": "^17.8.0",
|
|
55
|
+
"@commitlint/config-conventional": "^17.8.0",
|
|
56
56
|
"@fastify/middie": "^8.3.0",
|
|
57
|
-
"@japa/
|
|
58
|
-
"@japa/
|
|
59
|
-
"@japa/
|
|
60
|
-
"@
|
|
61
|
-
"@swc/core": "^1.3.70",
|
|
57
|
+
"@japa/assert": "^2.0.0",
|
|
58
|
+
"@japa/expect-type": "^2.0.0",
|
|
59
|
+
"@japa/runner": "^3.0.2",
|
|
60
|
+
"@swc/core": "1.3.82",
|
|
62
61
|
"@types/accepts": "^1.3.5",
|
|
63
|
-
"@types/content-disposition": "^0.5.
|
|
64
|
-
"@types/cookie": "^0.5.
|
|
65
|
-
"@types/destroy": "^1.0.
|
|
62
|
+
"@types/content-disposition": "^0.5.6",
|
|
63
|
+
"@types/cookie": "^0.5.2",
|
|
64
|
+
"@types/destroy": "^1.0.1",
|
|
66
65
|
"@types/encodeurl": "^1.0.0",
|
|
67
66
|
"@types/etag": "^1.8.1",
|
|
68
67
|
"@types/fresh": "^0.5.0",
|
|
69
|
-
"@types/fs-extra": "^11.0.
|
|
68
|
+
"@types/fs-extra": "^11.0.2",
|
|
70
69
|
"@types/http-status-codes": "^1.2.0",
|
|
71
|
-
"@types/mime-types": "^2.1.
|
|
72
|
-
"@types/node": "^20.
|
|
73
|
-
"@types/on-finished": "^2.3.
|
|
74
|
-
"@types/pem": "^1.14.
|
|
75
|
-
"@types/proxy-addr": "^2.0.
|
|
76
|
-
"@types/qs": "^6.9.
|
|
77
|
-
"@types/supertest": "^2.0.
|
|
78
|
-
"@types/type-is": "^1.6.
|
|
79
|
-
"@types/vary": "^1.1.
|
|
80
|
-
"@vinejs/vine": "^1.
|
|
81
|
-
"autocannon": "^7.
|
|
82
|
-
"c8": "^8.0.
|
|
70
|
+
"@types/mime-types": "^2.1.2",
|
|
71
|
+
"@types/node": "^20.8.6",
|
|
72
|
+
"@types/on-finished": "^2.3.2",
|
|
73
|
+
"@types/pem": "^1.14.2",
|
|
74
|
+
"@types/proxy-addr": "^2.0.1",
|
|
75
|
+
"@types/qs": "^6.9.8",
|
|
76
|
+
"@types/supertest": "^2.0.14",
|
|
77
|
+
"@types/type-is": "^1.6.4",
|
|
78
|
+
"@types/vary": "^1.1.1",
|
|
79
|
+
"@vinejs/vine": "^1.6.0",
|
|
80
|
+
"autocannon": "^7.12.0",
|
|
81
|
+
"c8": "^8.0.1",
|
|
83
82
|
"cross-env": "^7.0.3",
|
|
84
|
-
"del-cli": "^5.
|
|
85
|
-
"eslint": "^8.
|
|
86
|
-
"fastify": "^4.
|
|
83
|
+
"del-cli": "^5.1.0",
|
|
84
|
+
"eslint": "^8.51.0",
|
|
85
|
+
"fastify": "^4.24.2",
|
|
87
86
|
"fs-extra": "^11.1.1",
|
|
88
87
|
"get-port": "^7.0.0",
|
|
89
88
|
"github-label-sync": "^2.3.1",
|
|
90
|
-
"http-status-codes": "^2.
|
|
89
|
+
"http-status-codes": "^2.3.0",
|
|
91
90
|
"husky": "^8.0.3",
|
|
92
91
|
"np": "^8.0.4",
|
|
93
92
|
"pem": "^1.14.8",
|
|
94
|
-
"prettier": "^3.0.
|
|
93
|
+
"prettier": "^3.0.3",
|
|
95
94
|
"reflect-metadata": "^0.1.13",
|
|
96
95
|
"supertest": "^6.3.3",
|
|
97
96
|
"ts-node": "^10.9.1",
|
|
98
|
-
"
|
|
97
|
+
"tsup": "^7.2.0",
|
|
98
|
+
"typescript": "^5.2.2"
|
|
99
99
|
},
|
|
100
100
|
"dependencies": {
|
|
101
|
-
"@paralleldrive/cuid2": "^2.2.
|
|
102
|
-
"@poppinss/macroable": "^1.0.0
|
|
101
|
+
"@paralleldrive/cuid2": "^2.2.2",
|
|
102
|
+
"@poppinss/macroable": "^1.0.0",
|
|
103
103
|
"@poppinss/matchit": "^3.1.2",
|
|
104
|
-
"@poppinss/middleware": "^3.
|
|
105
|
-
"@poppinss/utils": "^6.5.0
|
|
106
|
-
"@sindresorhus/is": "^
|
|
104
|
+
"@poppinss/middleware": "^3.2.0",
|
|
105
|
+
"@poppinss/utils": "^6.5.0",
|
|
106
|
+
"@sindresorhus/is": "^6.0.1",
|
|
107
107
|
"accepts": "^1.3.8",
|
|
108
108
|
"content-disposition": "^0.5.4",
|
|
109
109
|
"cookie": "^0.5.0",
|
|
@@ -118,14 +118,14 @@
|
|
|
118
118
|
"tmp-cache": "^1.1.0",
|
|
119
119
|
"type-is": "^1.6.18",
|
|
120
120
|
"vary": "^1.1.2",
|
|
121
|
-
"youch": "^3.2
|
|
121
|
+
"youch": "^3.3.2"
|
|
122
122
|
},
|
|
123
123
|
"peerDependencies": {
|
|
124
|
-
"@adonisjs/application": "^
|
|
125
|
-
"@adonisjs/encryption": "^5.1.2-
|
|
126
|
-
"@adonisjs/events": "^
|
|
127
|
-
"@adonisjs/fold": "^9.9.3-
|
|
128
|
-
"@adonisjs/logger": "^5.4.2-
|
|
124
|
+
"@adonisjs/application": "^8.0.0-0",
|
|
125
|
+
"@adonisjs/encryption": "^5.1.2-3",
|
|
126
|
+
"@adonisjs/events": "^9.0.0-0",
|
|
127
|
+
"@adonisjs/fold": "^9.9.3-10",
|
|
128
|
+
"@adonisjs/logger": "^5.4.2-6"
|
|
129
129
|
},
|
|
130
130
|
"repository": {
|
|
131
131
|
"type": "git",
|
|
@@ -164,5 +164,17 @@
|
|
|
164
164
|
"eslintConfig": {
|
|
165
165
|
"extends": "@adonisjs/eslint-config/package"
|
|
166
166
|
},
|
|
167
|
-
"prettier": "@adonisjs/prettier-config"
|
|
167
|
+
"prettier": "@adonisjs/prettier-config",
|
|
168
|
+
"tsup": {
|
|
169
|
+
"entry": [
|
|
170
|
+
"./index.ts",
|
|
171
|
+
"./src/types/main.ts",
|
|
172
|
+
"./factories/main.ts"
|
|
173
|
+
],
|
|
174
|
+
"outDir": "./build",
|
|
175
|
+
"clean": true,
|
|
176
|
+
"format": "esm",
|
|
177
|
+
"dts": true,
|
|
178
|
+
"target": "esnext"
|
|
179
|
+
}
|
|
168
180
|
}
|