@adonisjs/http-server 6.8.2-7 → 6.8.2-9
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/exception_handler.d.ts +32 -10
- package/build/src/exception_handler.js +115 -51
- package/build/src/router/route.js +9 -2
- package/build/src/router/store.js +5 -0
- package/package.json +17 -16
|
@@ -30,14 +30,6 @@ export declare class ExceptionHandler {
|
|
|
30
30
|
* A collection of error status code range and the view to render.
|
|
31
31
|
*/
|
|
32
32
|
protected statusPages: Record<StatusPageRange, StatusPageRenderer>;
|
|
33
|
-
/**
|
|
34
|
-
* Renderers for rendering an error.
|
|
35
|
-
*/
|
|
36
|
-
protected renderers: {
|
|
37
|
-
html: (error: HttpError, ctx: HttpContext) => Promise<void>;
|
|
38
|
-
json: (error: HttpError, ctx: HttpContext) => Promise<void>;
|
|
39
|
-
json_api: (error: HttpError, ctx: HttpContext) => Promise<void>;
|
|
40
|
-
};
|
|
41
33
|
/**
|
|
42
34
|
* Enable/disable errors reporting
|
|
43
35
|
*/
|
|
@@ -62,9 +54,39 @@ export declare class ExceptionHandler {
|
|
|
62
54
|
*/
|
|
63
55
|
protected context(ctx: HttpContext): any;
|
|
64
56
|
/**
|
|
65
|
-
*
|
|
57
|
+
* Renders an error to JSON response
|
|
58
|
+
*/
|
|
59
|
+
protected renderErrorAsJSON(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Renders an error to JSON API response
|
|
62
|
+
*/
|
|
63
|
+
protected renderErrorAsJSONAPI(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Renders an error to HTML response
|
|
66
|
+
*/
|
|
67
|
+
protected renderErrorAsHTML(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Renders the validation error message to a JSON
|
|
70
|
+
* response
|
|
71
|
+
*/
|
|
72
|
+
protected renderValidationErrorAsJSON(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Renders the validation error message as per JSON API
|
|
75
|
+
* spec
|
|
76
|
+
*/
|
|
77
|
+
protected renderValidationErrorAsJSONAPI(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Renders the validation error as an HTML string
|
|
80
|
+
*/
|
|
81
|
+
protected renderValidationErrorAsHTML(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Renders the error to response
|
|
84
|
+
*/
|
|
85
|
+
protected renderError(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Renders the validation error to response
|
|
66
88
|
*/
|
|
67
|
-
protected
|
|
89
|
+
protected renderValidationError(error: HttpError, ctx: HttpContext): Promise<void>;
|
|
68
90
|
/**
|
|
69
91
|
* Returns the log level for an error based upon the error
|
|
70
92
|
* status code.
|
|
@@ -22,6 +22,10 @@ import * as errors from './exceptions.js';
|
|
|
22
22
|
* - Reporting errors
|
|
23
23
|
*/
|
|
24
24
|
export class ExceptionHandler {
|
|
25
|
+
/**
|
|
26
|
+
* Computed from the status pages property
|
|
27
|
+
*/
|
|
28
|
+
#expandedStatusPages;
|
|
25
29
|
/**
|
|
26
30
|
* Whether or not to render debug info. When set to true, the errors
|
|
27
31
|
* will have the complete error stack.
|
|
@@ -37,50 +41,6 @@ export class ExceptionHandler {
|
|
|
37
41
|
* A collection of error status code range and the view to render.
|
|
38
42
|
*/
|
|
39
43
|
statusPages = {};
|
|
40
|
-
/**
|
|
41
|
-
* Computed from the status pages property
|
|
42
|
-
*/
|
|
43
|
-
#expandedStatusPages;
|
|
44
|
-
/**
|
|
45
|
-
* Renderers for rendering an error.
|
|
46
|
-
*/
|
|
47
|
-
renderers = {
|
|
48
|
-
html: async (error, ctx) => {
|
|
49
|
-
if (this.isDebuggingEnabled(ctx)) {
|
|
50
|
-
const { default: Youch } = await import('youch');
|
|
51
|
-
const html = await new Youch(error, ctx.request.request).toHTML();
|
|
52
|
-
ctx.response.status(error.status).send(html);
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
ctx.response.status(error.status).send(`<p> ${error.message} </p>`);
|
|
56
|
-
},
|
|
57
|
-
json: async (error, ctx) => {
|
|
58
|
-
if (this.isDebuggingEnabled(ctx)) {
|
|
59
|
-
const { default: Youch } = await import('youch');
|
|
60
|
-
const json = await new Youch(error, ctx.request.request).toJSON();
|
|
61
|
-
ctx.response.status(error.status).send(json.error);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
ctx.response.status(error.status).send({ message: error.message });
|
|
65
|
-
},
|
|
66
|
-
json_api: async (error, ctx) => {
|
|
67
|
-
if (this.isDebuggingEnabled(ctx)) {
|
|
68
|
-
const { default: Youch } = await import('youch');
|
|
69
|
-
const json = await new Youch(error, ctx.request.request).toJSON();
|
|
70
|
-
ctx.response.status(error.status).send(json.error);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
ctx.response.status(error.status).send({
|
|
74
|
-
errors: [
|
|
75
|
-
{
|
|
76
|
-
title: error.message,
|
|
77
|
-
code: error.code,
|
|
78
|
-
status: error.status,
|
|
79
|
-
},
|
|
80
|
-
],
|
|
81
|
-
});
|
|
82
|
-
},
|
|
83
|
-
};
|
|
84
44
|
/**
|
|
85
45
|
* Enable/disable errors reporting
|
|
86
46
|
*/
|
|
@@ -140,17 +100,115 @@ export class ExceptionHandler {
|
|
|
140
100
|
: {};
|
|
141
101
|
}
|
|
142
102
|
/**
|
|
143
|
-
*
|
|
103
|
+
* Renders an error to JSON response
|
|
144
104
|
*/
|
|
145
|
-
|
|
105
|
+
async renderErrorAsJSON(error, ctx) {
|
|
106
|
+
if (this.isDebuggingEnabled(ctx)) {
|
|
107
|
+
const { default: Youch } = await import('youch');
|
|
108
|
+
const json = await new Youch(error, ctx.request.request).toJSON();
|
|
109
|
+
ctx.response.status(error.status).send(json.error);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
ctx.response.status(error.status).send({ message: error.message });
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Renders an error to JSON API response
|
|
116
|
+
*/
|
|
117
|
+
async renderErrorAsJSONAPI(error, ctx) {
|
|
118
|
+
if (this.isDebuggingEnabled(ctx)) {
|
|
119
|
+
const { default: Youch } = await import('youch');
|
|
120
|
+
const json = await new Youch(error, ctx.request.request).toJSON();
|
|
121
|
+
ctx.response.status(error.status).send(json.error);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
ctx.response.status(error.status).send({
|
|
125
|
+
errors: [
|
|
126
|
+
{
|
|
127
|
+
title: error.message,
|
|
128
|
+
code: error.code,
|
|
129
|
+
status: error.status,
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Renders an error to HTML response
|
|
136
|
+
*/
|
|
137
|
+
async renderErrorAsHTML(error, ctx) {
|
|
138
|
+
if (this.isDebuggingEnabled(ctx)) {
|
|
139
|
+
const { default: Youch } = await import('youch');
|
|
140
|
+
const html = await new Youch(error, ctx.request.request).toHTML();
|
|
141
|
+
ctx.response.status(error.status).send(html);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
ctx.response.status(error.status).send(`<p> ${error.message} </p>`);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Renders the validation error message to a JSON
|
|
148
|
+
* response
|
|
149
|
+
*/
|
|
150
|
+
async renderValidationErrorAsJSON(error, ctx) {
|
|
151
|
+
ctx.response.status(error.status).send({
|
|
152
|
+
errors: error.messages,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Renders the validation error message as per JSON API
|
|
157
|
+
* spec
|
|
158
|
+
*/
|
|
159
|
+
async renderValidationErrorAsJSONAPI(error, ctx) {
|
|
160
|
+
ctx.response.status(error.status).send({
|
|
161
|
+
errors: error.messages.map((message) => {
|
|
162
|
+
return {
|
|
163
|
+
title: message.message,
|
|
164
|
+
code: message.rule,
|
|
165
|
+
source: {
|
|
166
|
+
pointer: message.field,
|
|
167
|
+
},
|
|
168
|
+
meta: message.meta,
|
|
169
|
+
};
|
|
170
|
+
}),
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Renders the validation error as an HTML string
|
|
175
|
+
*/
|
|
176
|
+
async renderValidationErrorAsHTML(error, ctx) {
|
|
177
|
+
ctx.response
|
|
178
|
+
.status(error.status)
|
|
179
|
+
.type('html')
|
|
180
|
+
.send(error.messages
|
|
181
|
+
.map((message) => {
|
|
182
|
+
return `${message.field} - ${message.message}`;
|
|
183
|
+
})
|
|
184
|
+
.join('<br />'));
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Renders the error to response
|
|
188
|
+
*/
|
|
189
|
+
renderError(error, ctx) {
|
|
146
190
|
switch (ctx.request.accepts(['html', 'application/vnd.api+json', 'json'])) {
|
|
147
191
|
case 'application/vnd.api+json':
|
|
148
|
-
return
|
|
192
|
+
return this.renderErrorAsJSONAPI(error, ctx);
|
|
149
193
|
case 'json':
|
|
150
|
-
return
|
|
194
|
+
return this.renderErrorAsJSON(error, ctx);
|
|
151
195
|
case 'html':
|
|
152
196
|
default:
|
|
153
|
-
return
|
|
197
|
+
return this.renderErrorAsHTML(error, ctx);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Renders the validation error to response
|
|
202
|
+
*/
|
|
203
|
+
renderValidationError(error, ctx) {
|
|
204
|
+
switch (ctx.request.accepts(['html', 'application/vnd.api+json', 'json'])) {
|
|
205
|
+
case 'application/vnd.api+json':
|
|
206
|
+
return this.renderValidationErrorAsJSONAPI(error, ctx);
|
|
207
|
+
case 'json':
|
|
208
|
+
return this.renderValidationErrorAsJSON(error, ctx);
|
|
209
|
+
case 'html':
|
|
210
|
+
default:
|
|
211
|
+
return this.renderValidationErrorAsHTML(error, ctx);
|
|
154
212
|
}
|
|
155
213
|
}
|
|
156
214
|
/**
|
|
@@ -223,6 +281,13 @@ export class ExceptionHandler {
|
|
|
223
281
|
if (typeof httpError.handle === 'function') {
|
|
224
282
|
return httpError.handle(httpError, ctx);
|
|
225
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Handle validation error using the validation error
|
|
286
|
+
* renderers
|
|
287
|
+
*/
|
|
288
|
+
if (httpError.code === 'E_VALIDATION_ERROR' && 'messages' in httpError) {
|
|
289
|
+
return this.renderValidationError(httpError, ctx);
|
|
290
|
+
}
|
|
226
291
|
/**
|
|
227
292
|
* Render status page
|
|
228
293
|
*/
|
|
@@ -233,7 +298,6 @@ export class ExceptionHandler {
|
|
|
233
298
|
/**
|
|
234
299
|
* Use the format renderers.
|
|
235
300
|
*/
|
|
236
|
-
|
|
237
|
-
return this.renderers[responseFormat](httpError, ctx);
|
|
301
|
+
return this.renderError(httpError, ctx);
|
|
238
302
|
}
|
|
239
303
|
}
|
|
@@ -13,6 +13,7 @@ import { RuntimeException } from '@poppinss/utils';
|
|
|
13
13
|
import { moduleCaller, moduleExpression, moduleImporter } from '@adonisjs/fold';
|
|
14
14
|
import { execute } from './executor.js';
|
|
15
15
|
import { dropSlash } from '../helpers.js';
|
|
16
|
+
import debug from '../debug.js';
|
|
16
17
|
/**
|
|
17
18
|
* The route class exposes the APIs for constructing a route using the
|
|
18
19
|
* fluent API.
|
|
@@ -263,8 +264,14 @@ export class Route extends Macroable {
|
|
|
263
264
|
*/
|
|
264
265
|
#getMiddlewareForStore() {
|
|
265
266
|
const middleware = new Middleware();
|
|
266
|
-
this.#routerMiddleware.forEach((one) =>
|
|
267
|
-
|
|
267
|
+
this.#routerMiddleware.forEach((one) => {
|
|
268
|
+
debug('adding global middleware to route %s, %O', this.#pattern, one);
|
|
269
|
+
middleware.add(one);
|
|
270
|
+
});
|
|
271
|
+
this.#middleware.flat().forEach((one) => {
|
|
272
|
+
debug('adding named middleware to route %s, %O', this.#pattern, one);
|
|
273
|
+
middleware.add(one);
|
|
274
|
+
});
|
|
268
275
|
return middleware;
|
|
269
276
|
}
|
|
270
277
|
/**
|
|
@@ -11,6 +11,7 @@ import matchit from '@poppinss/matchit';
|
|
|
11
11
|
import lodash from '@poppinss/utils/lodash';
|
|
12
12
|
import { RuntimeException } from '@poppinss/utils';
|
|
13
13
|
import { parseRoutePattern } from './parser.js';
|
|
14
|
+
import debug from '../debug.js';
|
|
14
15
|
/**
|
|
15
16
|
* Store class is used to store a list of routes, along side with their tokens
|
|
16
17
|
* to match the URLs.
|
|
@@ -92,6 +93,10 @@ export class RoutesStore {
|
|
|
92
93
|
if (methodRoutes.routes[route.pattern]) {
|
|
93
94
|
throw new RuntimeException(`Duplicate route found. "${method}: ${route.pattern}" route already exists`);
|
|
94
95
|
}
|
|
96
|
+
if (debug.enabled) {
|
|
97
|
+
debug('registering route to the store %O', route);
|
|
98
|
+
debug('route middleware %O', route.middleware.all().entries());
|
|
99
|
+
}
|
|
95
100
|
methodRoutes.tokens.push(tokens);
|
|
96
101
|
methodRoutes.routes[route.pattern] = route;
|
|
97
102
|
methodRoutes.routeKeys[route.pattern] =
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adonisjs/http-server",
|
|
3
|
-
"version": "6.8.2-
|
|
3
|
+
"version": "6.8.2-9",
|
|
4
4
|
"description": "AdonisJS HTTP server with support packed with Routing and Cookies",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -43,22 +43,22 @@
|
|
|
43
43
|
"author": "virk,adonisjs",
|
|
44
44
|
"license": "MIT",
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@adonisjs/application": "^7.1.2-
|
|
46
|
+
"@adonisjs/application": "^7.1.2-8",
|
|
47
47
|
"@adonisjs/encryption": "^5.1.2-2",
|
|
48
|
-
"@adonisjs/eslint-config": "^1.1.
|
|
48
|
+
"@adonisjs/eslint-config": "^1.1.8",
|
|
49
49
|
"@adonisjs/events": "^8.4.9-3",
|
|
50
|
-
"@adonisjs/fold": "^9.9.3-
|
|
50
|
+
"@adonisjs/fold": "^9.9.3-6",
|
|
51
51
|
"@adonisjs/logger": "^5.4.2-3",
|
|
52
|
-
"@adonisjs/prettier-config": "^1.1.
|
|
53
|
-
"@adonisjs/tsconfig": "^1.1.
|
|
54
|
-
"@commitlint/cli": "^17.6.
|
|
55
|
-
"@commitlint/config-conventional": "^17.6.
|
|
52
|
+
"@adonisjs/prettier-config": "^1.1.8",
|
|
53
|
+
"@adonisjs/tsconfig": "^1.1.8",
|
|
54
|
+
"@commitlint/cli": "^17.6.7",
|
|
55
|
+
"@commitlint/config-conventional": "^17.6.7",
|
|
56
56
|
"@fastify/middie": "^8.3.0",
|
|
57
57
|
"@japa/api-client": "^2.0.0-0",
|
|
58
58
|
"@japa/assert": "^2.0.0-1",
|
|
59
59
|
"@japa/expect-type": "^2.0.0-0",
|
|
60
|
-
"@japa/runner": "^3.0.0-
|
|
61
|
-
"@swc/core": "^1.3.
|
|
60
|
+
"@japa/runner": "^3.0.0-5",
|
|
61
|
+
"@swc/core": "^1.3.70",
|
|
62
62
|
"@types/accepts": "^1.3.5",
|
|
63
63
|
"@types/content-disposition": "^0.5.5",
|
|
64
64
|
"@types/cookie": "^0.5.1",
|
|
@@ -69,20 +69,21 @@
|
|
|
69
69
|
"@types/fs-extra": "^11.0.1",
|
|
70
70
|
"@types/http-status-codes": "^1.2.0",
|
|
71
71
|
"@types/mime-types": "^2.1.1",
|
|
72
|
-
"@types/node": "^20.
|
|
72
|
+
"@types/node": "^20.4.2",
|
|
73
73
|
"@types/on-finished": "^2.3.1",
|
|
74
|
-
"@types/pem": "^1.
|
|
74
|
+
"@types/pem": "^1.14.0",
|
|
75
75
|
"@types/proxy-addr": "^2.0.0",
|
|
76
76
|
"@types/qs": "^6.9.7",
|
|
77
77
|
"@types/supertest": "^2.0.12",
|
|
78
78
|
"@types/type-is": "^1.6.3",
|
|
79
79
|
"@types/vary": "^1.1.0",
|
|
80
|
+
"@vinejs/vine": "^1.5.2",
|
|
80
81
|
"autocannon": "^7.11.0",
|
|
81
82
|
"c8": "^8.0.0",
|
|
82
83
|
"cross-env": "^7.0.3",
|
|
83
84
|
"del-cli": "^5.0.0",
|
|
84
|
-
"eslint": "^8.
|
|
85
|
-
"fastify": "^4.
|
|
85
|
+
"eslint": "^8.45.0",
|
|
86
|
+
"fastify": "^4.20.0",
|
|
86
87
|
"fs-extra": "^11.1.1",
|
|
87
88
|
"get-port": "^7.0.0",
|
|
88
89
|
"github-label-sync": "^2.3.1",
|
|
@@ -90,7 +91,7 @@
|
|
|
90
91
|
"husky": "^8.0.3",
|
|
91
92
|
"np": "^8.0.4",
|
|
92
93
|
"pem": "^1.14.8",
|
|
93
|
-
"prettier": "^
|
|
94
|
+
"prettier": "^3.0.0",
|
|
94
95
|
"reflect-metadata": "^0.1.13",
|
|
95
96
|
"supertest": "^6.3.3",
|
|
96
97
|
"ts-node": "^10.9.1",
|
|
@@ -102,7 +103,7 @@
|
|
|
102
103
|
"@poppinss/matchit": "^3.1.2",
|
|
103
104
|
"@poppinss/middleware": "^3.1.3",
|
|
104
105
|
"@poppinss/utils": "^6.5.0-3",
|
|
105
|
-
"@sindresorhus/is": "^5.
|
|
106
|
+
"@sindresorhus/is": "^5.5.2",
|
|
106
107
|
"accepts": "^1.3.8",
|
|
107
108
|
"content-disposition": "^0.5.4",
|
|
108
109
|
"cookie": "^0.5.0",
|