@adonisjs/http-server 5.12.0 → 6.0.1-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -38
- package/build/index.d.ts +16 -0
- package/build/index.js +16 -0
- package/build/src/cookies/client.d.ts +12 -0
- package/build/src/cookies/client.js +42 -0
- package/build/src/cookies/drivers/encrypted.d.ts +4 -0
- package/build/src/cookies/drivers/encrypted.js +16 -0
- package/build/src/cookies/drivers/plain.d.ts +3 -0
- package/build/src/cookies/drivers/plain.js +13 -0
- package/build/src/cookies/drivers/signed.d.ts +4 -0
- package/build/src/cookies/drivers/signed.js +16 -0
- package/build/src/cookies/parser.d.ts +9 -0
- package/build/src/cookies/parser.js +69 -0
- package/build/src/cookies/serializer.d.ts +11 -0
- package/build/src/cookies/serializer.js +39 -0
- package/build/src/debug.d.ts +3 -0
- package/build/src/debug.js +2 -0
- package/build/src/define_config.d.ts +2 -0
- package/build/src/define_config.js +40 -0
- package/build/src/define_middleware.d.ts +4 -0
- package/build/src/define_middleware.js +6 -0
- package/build/src/exceptions/abort_exception.d.ts +5 -0
- package/build/src/exceptions/abort_exception.js +6 -0
- package/build/src/exceptions/cannot_lookup_route.d.ts +5 -0
- package/build/src/exceptions/cannot_lookup_route.js +5 -0
- package/build/src/exceptions/http_exception.d.ts +6 -0
- package/build/src/exceptions/http_exception.js +20 -0
- package/build/src/exceptions/route_not_found.d.ts +5 -0
- package/build/src/exceptions/route_not_found.js +5 -0
- package/build/src/helpers.d.ts +6 -67
- package/build/src/helpers.js +13 -168
- package/build/src/http_context/local_storage.d.ts +9 -0
- package/build/src/http_context/local_storage.js +14 -0
- package/build/src/http_context/main.d.ts +20 -0
- package/build/src/http_context/main.js +49 -0
- package/build/src/middleware/store.d.ts +11 -0
- package/build/src/middleware/store.js +33 -0
- package/build/src/qs.d.ts +7 -0
- package/build/src/qs.js +13 -0
- package/build/src/redirect.d.ts +18 -0
- package/build/src/redirect.js +80 -0
- package/build/src/request.d.ts +81 -0
- package/build/src/request.js +315 -0
- package/build/src/response.d.ts +108 -0
- package/build/src/response.js +587 -0
- package/build/src/router/brisk.d.ts +18 -0
- package/build/src/router/brisk.js +35 -0
- package/build/src/router/executor.d.ts +4 -0
- package/build/src/router/executor.js +16 -0
- package/build/src/router/group.d.ts +19 -0
- package/build/src/router/group.js +117 -0
- package/build/src/router/lookup_store/main.d.ts +17 -0
- package/build/src/router/lookup_store/main.js +37 -0
- package/build/src/router/lookup_store/route_finder.d.ts +8 -0
- package/build/src/router/lookup_store/route_finder.js +28 -0
- package/build/src/router/lookup_store/url_builder.d.ts +16 -0
- package/build/src/router/lookup_store/url_builder.js +111 -0
- package/build/src/router/main.d.ts +36 -0
- package/build/src/router/main.js +161 -0
- package/build/src/router/matchers.d.ts +14 -0
- package/build/src/router/matchers.js +15 -0
- package/build/src/router/resource.d.ts +27 -0
- package/build/src/router/resource.js +124 -0
- package/build/src/router/route.d.ts +28 -0
- package/build/src/router/route.js +135 -0
- package/build/src/router/store.d.ts +12 -0
- package/build/src/router/store.js +87 -0
- package/build/src/server/factories/final_handler.d.ts +4 -0
- package/build/src/server/factories/final_handler.js +17 -0
- package/build/src/server/factories/middleware_handler.d.ts +5 -0
- package/build/src/server/factories/middleware_handler.js +5 -0
- package/build/src/server/factories/use_return_value.d.ts +2 -0
- package/build/src/server/factories/use_return_value.js +9 -0
- package/build/src/server/factories/write_response.d.ts +2 -0
- package/build/src/server/factories/write_response.js +12 -0
- package/build/src/server/main.d.ts +23 -0
- package/build/src/server/main.js +124 -0
- package/build/src/types/base.d.ts +5 -0
- package/build/src/types/base.js +1 -0
- package/build/src/types/main.d.ts +7 -0
- package/build/src/types/main.js +7 -0
- package/build/src/types/middleware.d.ts +14 -0
- package/build/src/types/middleware.js +1 -0
- package/build/src/types/qs.d.ts +15 -0
- package/build/src/types/qs.js +1 -0
- package/build/src/types/request.d.ts +7 -0
- package/build/src/types/request.js +1 -0
- package/build/src/types/response.d.ts +18 -0
- package/build/src/types/response.js +1 -0
- package/build/src/types/route.d.ts +74 -0
- package/build/src/types/route.js +1 -0
- package/build/src/types/server.d.ts +13 -0
- package/build/src/types/server.js +1 -0
- package/package.json +88 -86
- package/build/adonis-typings/container.d.ts +0 -24
- package/build/adonis-typings/container.js +0 -8
- package/build/adonis-typings/context.d.ts +0 -73
- package/build/adonis-typings/context.js +0 -8
- package/build/adonis-typings/cookie-client.d.ts +0 -34
- package/build/adonis-typings/cookie-client.js +0 -8
- package/build/adonis-typings/http-server.d.ts +0 -98
- package/build/adonis-typings/http-server.js +0 -8
- package/build/adonis-typings/index.d.ts +0 -16
- package/build/adonis-typings/index.js +0 -16
- package/build/adonis-typings/middleware.d.ts +0 -95
- package/build/adonis-typings/middleware.js +0 -8
- package/build/adonis-typings/request.d.ts +0 -556
- package/build/adonis-typings/request.js +0 -8
- package/build/adonis-typings/response.d.ts +0 -440
- package/build/adonis-typings/response.js +0 -8
- package/build/adonis-typings/route.d.ts +0 -559
- package/build/adonis-typings/route.js +0 -8
- package/build/exceptions.json +0 -110
- package/build/providers/HttpServerProvider.d.ts +0 -46
- package/build/providers/HttpServerProvider.js +0 -100
- package/build/src/Cookie/Client/index.d.ts +0 -39
- package/build/src/Cookie/Client/index.js +0 -108
- package/build/src/Cookie/Drivers/Encrypted.d.ts +0 -24
- package/build/src/Cookie/Drivers/Encrypted.js +0 -42
- package/build/src/Cookie/Drivers/Plain.d.ts +0 -23
- package/build/src/Cookie/Drivers/Plain.js +0 -40
- package/build/src/Cookie/Drivers/Signed.d.ts +0 -24
- package/build/src/Cookie/Drivers/Signed.js +0 -42
- package/build/src/Cookie/Parser/index.d.ts +0 -61
- package/build/src/Cookie/Parser/index.js +0 -174
- package/build/src/Cookie/Serializer/index.d.ts +0 -46
- package/build/src/Cookie/Serializer/index.js +0 -88
- package/build/src/Exceptions/HttpException.d.ts +0 -20
- package/build/src/Exceptions/HttpException.js +0 -36
- package/build/src/Exceptions/RouterException.d.ts +0 -36
- package/build/src/Exceptions/RouterException.js +0 -76
- package/build/src/HttpContext/LocalStorage/index.d.ts +0 -24
- package/build/src/HttpContext/LocalStorage/index.js +0 -28
- package/build/src/HttpContext/index.d.ts +0 -90
- package/build/src/HttpContext/index.js +0 -181
- package/build/src/MiddlewareStore/index.d.ts +0 -92
- package/build/src/MiddlewareStore/index.js +0 -133
- package/build/src/Redirect/index.d.ts +0 -71
- package/build/src/Redirect/index.js +0 -139
- package/build/src/Request/index.d.ts +0 -619
- package/build/src/Request/index.js +0 -862
- package/build/src/Response/index.d.ts +0 -414
- package/build/src/Response/index.js +0 -1010
- package/build/src/Router/BriskRoute.d.ts +0 -53
- package/build/src/Router/BriskRoute.js +0 -74
- package/build/src/Router/Group.d.ts +0 -101
- package/build/src/Router/Group.js +0 -165
- package/build/src/Router/LookupStore.d.ts +0 -122
- package/build/src/Router/LookupStore.js +0 -264
- package/build/src/Router/Matchers.d.ts +0 -31
- package/build/src/Router/Matchers.js +0 -43
- package/build/src/Router/Resource.d.ts +0 -95
- package/build/src/Router/Resource.js +0 -182
- package/build/src/Router/Route.d.ts +0 -138
- package/build/src/Router/Route.js +0 -204
- package/build/src/Router/Store.d.ts +0 -93
- package/build/src/Router/Store.js +0 -211
- package/build/src/Router/index.d.ts +0 -142
- package/build/src/Router/index.js +0 -333
- package/build/src/Server/ExceptionManager/index.d.ts +0 -49
- package/build/src/Server/ExceptionManager/index.js +0 -96
- package/build/src/Server/Hooks/index.d.ts +0 -43
- package/build/src/Server/Hooks/index.js +0 -77
- package/build/src/Server/PreCompiler/index.d.ts +0 -60
- package/build/src/Server/PreCompiler/index.js +0 -143
- package/build/src/Server/RequestHandler/index.d.ts +0 -39
- package/build/src/Server/RequestHandler/index.js +0 -87
- package/build/src/Server/index.d.ts +0 -90
- package/build/src/Server/index.js +0 -175
- package/build/standalone.d.ts +0 -14
- package/build/standalone.js +0 -23
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import string from '@poppinss/utils/string';
|
|
2
|
+
import { Macroable } from '@poppinss/macroable';
|
|
3
|
+
import { RuntimeException } from '@poppinss/utils';
|
|
4
|
+
import { Route } from './route.js';
|
|
5
|
+
export class RouteResource extends Macroable {
|
|
6
|
+
#resource;
|
|
7
|
+
#controller;
|
|
8
|
+
#shallow = false;
|
|
9
|
+
#globalMatchers;
|
|
10
|
+
#app;
|
|
11
|
+
#middlewareStore;
|
|
12
|
+
#params = {};
|
|
13
|
+
#routesBaseName;
|
|
14
|
+
routes = [];
|
|
15
|
+
constructor(app, middlewareStore, options) {
|
|
16
|
+
super();
|
|
17
|
+
this.#validateResourceName(options.resource);
|
|
18
|
+
this.#app = app;
|
|
19
|
+
this.#shallow = options.shallow;
|
|
20
|
+
this.#middlewareStore = middlewareStore;
|
|
21
|
+
this.#controller = options.controller;
|
|
22
|
+
this.#globalMatchers = options.globalMatchers;
|
|
23
|
+
this.#resource = this.#normalizeResourceName(options.resource);
|
|
24
|
+
this.#routesBaseName = this.#getRoutesBaseName();
|
|
25
|
+
this.#buildRoutes();
|
|
26
|
+
}
|
|
27
|
+
#normalizeResourceName(resource) {
|
|
28
|
+
return resource.replace(/^\//, '').replace(/\/$/, '');
|
|
29
|
+
}
|
|
30
|
+
#validateResourceName(resource) {
|
|
31
|
+
if (!resource || resource === '/') {
|
|
32
|
+
throw new RuntimeException(`Invalid resource name "${resource}"`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
#getRoutesBaseName() {
|
|
36
|
+
return this.#resource
|
|
37
|
+
.split('.')
|
|
38
|
+
.map((token) => string.snakeCase(token))
|
|
39
|
+
.join('.');
|
|
40
|
+
}
|
|
41
|
+
#createRoute(pattern, methods, action) {
|
|
42
|
+
const route = new Route(this.#app, this.#middlewareStore, {
|
|
43
|
+
pattern,
|
|
44
|
+
methods,
|
|
45
|
+
handler: `${this.#controller}.${action}`,
|
|
46
|
+
globalMatchers: this.#globalMatchers,
|
|
47
|
+
});
|
|
48
|
+
route.as(`${this.#routesBaseName}.${action}`);
|
|
49
|
+
this.routes.push(route);
|
|
50
|
+
}
|
|
51
|
+
#getResourceId(resource) {
|
|
52
|
+
return `${string.snakeCase(string.singular(resource))}_id`;
|
|
53
|
+
}
|
|
54
|
+
#buildRoutes() {
|
|
55
|
+
const resources = this.#resource.split('.');
|
|
56
|
+
const mainResource = resources.pop();
|
|
57
|
+
this.#params[mainResource] = ':id';
|
|
58
|
+
const baseURI = `${resources
|
|
59
|
+
.map((resource) => {
|
|
60
|
+
const paramName = `:${this.#getResourceId(resource)}`;
|
|
61
|
+
this.#params[resource] = paramName;
|
|
62
|
+
return `${resource}/${paramName}`;
|
|
63
|
+
})
|
|
64
|
+
.join('/')}/${mainResource}`;
|
|
65
|
+
this.#createRoute(baseURI, ['GET', 'HEAD'], 'index');
|
|
66
|
+
this.#createRoute(`${baseURI}/create`, ['GET', 'HEAD'], 'create');
|
|
67
|
+
this.#createRoute(baseURI, ['POST'], 'store');
|
|
68
|
+
this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id`, ['GET', 'HEAD'], 'show');
|
|
69
|
+
this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id/edit`, ['GET', 'HEAD'], 'edit');
|
|
70
|
+
this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id`, ['PUT', 'PATCH'], 'update');
|
|
71
|
+
this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id`, ['DELETE'], 'destroy');
|
|
72
|
+
}
|
|
73
|
+
#filter(names, inverse) {
|
|
74
|
+
const actions = Array.isArray(names) ? names : [names];
|
|
75
|
+
return this.routes.filter((route) => {
|
|
76
|
+
const match = actions.find((name) => route.getName().endsWith(name));
|
|
77
|
+
return inverse ? !match : match;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
only(names) {
|
|
81
|
+
this.#filter(names, true).forEach((route) => route.markAsDeleted());
|
|
82
|
+
return this;
|
|
83
|
+
}
|
|
84
|
+
except(names) {
|
|
85
|
+
this.#filter(names, false).forEach((route) => route.markAsDeleted());
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
apiOnly() {
|
|
89
|
+
return this.except(['create', 'edit']);
|
|
90
|
+
}
|
|
91
|
+
where(key, matcher) {
|
|
92
|
+
this.routes.forEach((route) => {
|
|
93
|
+
route.where(key, matcher);
|
|
94
|
+
});
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
tap(actions, callback) {
|
|
98
|
+
if (typeof actions === 'function') {
|
|
99
|
+
this.routes.forEach((route) => actions(route));
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
this.#filter(actions, false).forEach((route) => callback(route));
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
params(resources) {
|
|
106
|
+
Object.keys(resources).forEach((resource) => {
|
|
107
|
+
const param = resources[resource];
|
|
108
|
+
const existingParam = this.#params[resource];
|
|
109
|
+
this.#params[resource] = `:${param}`;
|
|
110
|
+
this.routes.forEach((route) => {
|
|
111
|
+
route.setPattern(route.getPattern().replace(`${resource}/${existingParam}`, `${resource}/:${param}`));
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
as(name) {
|
|
117
|
+
name = string.snakeCase(name);
|
|
118
|
+
this.routes.forEach((route) => {
|
|
119
|
+
route.as(route.getName().replace(this.#routesBaseName, name), false);
|
|
120
|
+
});
|
|
121
|
+
this.#routesBaseName = name;
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Macroable } from '@poppinss/macroable';
|
|
2
|
+
import type { Application } from '@adonisjs/application';
|
|
3
|
+
import type { MiddlewareStore } from '../middleware/store.js';
|
|
4
|
+
import type { LazyImport, UnWrapLazyImport } from '../types/base.js';
|
|
5
|
+
import type { GetMiddlewareArgs, MiddlewareAsClass, MiddlewareFn } from '../types/middleware.js';
|
|
6
|
+
import type { RouteFn, RouteJSON, RouteMatcher, RouteMatchers, StoreRouteMiddleware } from '../types/route.js';
|
|
7
|
+
export declare class Route<NamedMiddleware extends Record<string, LazyImport<MiddlewareAsClass>> = any> extends Macroable {
|
|
8
|
+
#private;
|
|
9
|
+
constructor(app: Application<any, any, any>, middlewareStore: MiddlewareStore<NamedMiddleware>, options: {
|
|
10
|
+
pattern: string;
|
|
11
|
+
methods: string[];
|
|
12
|
+
handler: RouteFn | string;
|
|
13
|
+
globalMatchers: RouteMatchers;
|
|
14
|
+
});
|
|
15
|
+
where(param: string, matcher: RouteMatcher | string | RegExp): this;
|
|
16
|
+
prefix(prefix: string): this;
|
|
17
|
+
domain(domain: string, overwrite?: boolean): this;
|
|
18
|
+
middleware<Name extends keyof NamedMiddleware>(middleware: Name, ...args: GetMiddlewareArgs<UnWrapLazyImport<NamedMiddleware[Name]>>): this;
|
|
19
|
+
middleware(middleware: MiddlewareFn): this;
|
|
20
|
+
as(name: string, prepend?: boolean): this;
|
|
21
|
+
isDeleted(): boolean;
|
|
22
|
+
markAsDeleted(): void;
|
|
23
|
+
getName(): string | undefined;
|
|
24
|
+
getPattern(): string;
|
|
25
|
+
setPattern(pattern: string): this;
|
|
26
|
+
getMiddleware(): StoreRouteMiddleware[][];
|
|
27
|
+
toJSON(): RouteJSON;
|
|
28
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import is from '@sindresorhus/is';
|
|
2
|
+
import Middleware from '@poppinss/middleware';
|
|
3
|
+
import { Macroable } from '@poppinss/macroable';
|
|
4
|
+
import { moduleExpression } from '@adonisjs/fold';
|
|
5
|
+
import { RuntimeException } from '@poppinss/utils';
|
|
6
|
+
import { execute } from './executor.js';
|
|
7
|
+
import { dropSlash } from '../helpers.js';
|
|
8
|
+
export class Route extends Macroable {
|
|
9
|
+
#pattern;
|
|
10
|
+
#methods;
|
|
11
|
+
#name;
|
|
12
|
+
#isDeleted = false;
|
|
13
|
+
#handler;
|
|
14
|
+
#globalMatchers;
|
|
15
|
+
#app;
|
|
16
|
+
#middlewareStore;
|
|
17
|
+
#routeDomain = 'root';
|
|
18
|
+
#matchers = {};
|
|
19
|
+
#prefixes = [];
|
|
20
|
+
#middleware = [];
|
|
21
|
+
constructor(app, middlewareStore, options) {
|
|
22
|
+
super();
|
|
23
|
+
this.#app = app;
|
|
24
|
+
this.#middlewareStore = middlewareStore;
|
|
25
|
+
this.#pattern = options.pattern;
|
|
26
|
+
this.#methods = options.methods;
|
|
27
|
+
this.#handler = this.#resolveRouteHandle(options.handler);
|
|
28
|
+
this.#globalMatchers = options.globalMatchers;
|
|
29
|
+
}
|
|
30
|
+
#resolveRouteHandle(handler) {
|
|
31
|
+
if (typeof handler === 'string') {
|
|
32
|
+
return {
|
|
33
|
+
name: handler,
|
|
34
|
+
...moduleExpression(handler, this.#app.appRoot).toHandleMethod(),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return handler;
|
|
38
|
+
}
|
|
39
|
+
#getMatchers() {
|
|
40
|
+
return { ...this.#globalMatchers, ...this.#matchers };
|
|
41
|
+
}
|
|
42
|
+
#computePattern() {
|
|
43
|
+
const pattern = dropSlash(this.#pattern);
|
|
44
|
+
const prefix = this.#prefixes
|
|
45
|
+
.slice()
|
|
46
|
+
.reverse()
|
|
47
|
+
.map((one) => dropSlash(one))
|
|
48
|
+
.join('');
|
|
49
|
+
return prefix ? `${prefix}${pattern === '/' ? '' : pattern}` : pattern;
|
|
50
|
+
}
|
|
51
|
+
where(param, matcher) {
|
|
52
|
+
if (this.#matchers[param]) {
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
if (typeof matcher === 'string') {
|
|
56
|
+
this.#matchers[param] = { match: new RegExp(matcher) };
|
|
57
|
+
}
|
|
58
|
+
else if (is.regExp(matcher)) {
|
|
59
|
+
this.#matchers[param] = { match: matcher };
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
this.#matchers[param] = matcher;
|
|
63
|
+
}
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
prefix(prefix) {
|
|
67
|
+
this.#prefixes.push(prefix);
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
domain(domain, overwrite = false) {
|
|
71
|
+
if (this.#routeDomain === 'root' || overwrite) {
|
|
72
|
+
this.#routeDomain = domain;
|
|
73
|
+
}
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
middleware(middleware, args) {
|
|
77
|
+
if (typeof middleware === 'string') {
|
|
78
|
+
this.#middleware.push([this.#middlewareStore.get(middleware, args)]);
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
if (typeof middleware === 'function') {
|
|
82
|
+
this.#middleware.push([middleware]);
|
|
83
|
+
}
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
as(name, prepend = false) {
|
|
87
|
+
if (prepend) {
|
|
88
|
+
if (!this.#name) {
|
|
89
|
+
throw new RuntimeException(`Routes inside a group must have names before calling "router.group.as"`);
|
|
90
|
+
}
|
|
91
|
+
this.#name = `${name}.${this.#name}`;
|
|
92
|
+
return this;
|
|
93
|
+
}
|
|
94
|
+
this.#name = name;
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
isDeleted() {
|
|
98
|
+
return this.#isDeleted;
|
|
99
|
+
}
|
|
100
|
+
markAsDeleted() {
|
|
101
|
+
this.#isDeleted = true;
|
|
102
|
+
}
|
|
103
|
+
getName() {
|
|
104
|
+
return this.#name;
|
|
105
|
+
}
|
|
106
|
+
getPattern() {
|
|
107
|
+
return this.#pattern;
|
|
108
|
+
}
|
|
109
|
+
setPattern(pattern) {
|
|
110
|
+
this.#pattern = pattern;
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
getMiddleware() {
|
|
114
|
+
return this.#middleware;
|
|
115
|
+
}
|
|
116
|
+
#getMiddlewareForStore() {
|
|
117
|
+
const middleware = new Middleware();
|
|
118
|
+
this.#middlewareStore.list().forEach((one) => middleware.add(one));
|
|
119
|
+
this.#middleware.flat().forEach((one) => middleware.add(one));
|
|
120
|
+
return middleware;
|
|
121
|
+
}
|
|
122
|
+
toJSON() {
|
|
123
|
+
return {
|
|
124
|
+
domain: this.#routeDomain,
|
|
125
|
+
pattern: this.#computePattern(),
|
|
126
|
+
matchers: this.#getMatchers(),
|
|
127
|
+
meta: {},
|
|
128
|
+
name: this.#name,
|
|
129
|
+
handler: this.#handler,
|
|
130
|
+
methods: this.#methods,
|
|
131
|
+
middleware: this.#getMiddlewareForStore(),
|
|
132
|
+
execute: execute,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RouteJSON, MatchedRoute, StoreRoutesTree, MatchItRouteToken } from '../types/route.js';
|
|
2
|
+
export declare class RoutesStore {
|
|
3
|
+
#private;
|
|
4
|
+
usingDomains: boolean;
|
|
5
|
+
tree: StoreRoutesTree;
|
|
6
|
+
add(route: RouteJSON): this;
|
|
7
|
+
match(url: string, method: string, domain?: {
|
|
8
|
+
tokens: MatchItRouteToken[];
|
|
9
|
+
hostname: string;
|
|
10
|
+
}): null | MatchedRoute;
|
|
11
|
+
matchDomain(hostname?: string | null): MatchItRouteToken[];
|
|
12
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import matchit from '@poppinss/matchit';
|
|
2
|
+
import lodash from '@poppinss/utils/lodash';
|
|
3
|
+
import { RuntimeException } from '@poppinss/utils';
|
|
4
|
+
export class RoutesStore {
|
|
5
|
+
usingDomains = false;
|
|
6
|
+
tree = { tokens: [], domains: {} };
|
|
7
|
+
#getDomainNode(domain) {
|
|
8
|
+
if (!this.tree.domains[domain]) {
|
|
9
|
+
this.tree.tokens.push(matchit.parse(domain));
|
|
10
|
+
this.tree.domains[domain] = {};
|
|
11
|
+
}
|
|
12
|
+
return this.tree.domains[domain];
|
|
13
|
+
}
|
|
14
|
+
#getMethodNode(domain, method) {
|
|
15
|
+
const domainNode = this.#getDomainNode(domain);
|
|
16
|
+
if (!domainNode[method]) {
|
|
17
|
+
domainNode[method] = { tokens: [], routes: {}, routeKeys: {} };
|
|
18
|
+
}
|
|
19
|
+
return domainNode[method];
|
|
20
|
+
}
|
|
21
|
+
#collectRouteParams(route, tokens) {
|
|
22
|
+
const collectedParams = new Set();
|
|
23
|
+
for (let token of tokens) {
|
|
24
|
+
if ([1, 3].includes(token.type)) {
|
|
25
|
+
if (collectedParams.has(token.val)) {
|
|
26
|
+
throw new RuntimeException(`Duplicate param "${token.val}" found in "${route.pattern}"`);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
collectedParams.add(token.val);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const params = [...collectedParams];
|
|
34
|
+
collectedParams.clear();
|
|
35
|
+
return params;
|
|
36
|
+
}
|
|
37
|
+
#registerRoute(domain, method, tokens, route) {
|
|
38
|
+
const methodRoutes = this.#getMethodNode(domain, method);
|
|
39
|
+
if (methodRoutes.routes[route.pattern]) {
|
|
40
|
+
throw new RuntimeException(`Duplicate route found. "${method}: ${route.pattern}" route already exists`);
|
|
41
|
+
}
|
|
42
|
+
methodRoutes.tokens.push(tokens);
|
|
43
|
+
methodRoutes.routes[route.pattern] = route;
|
|
44
|
+
methodRoutes.routeKeys[route.pattern] =
|
|
45
|
+
domain !== 'root' ? `${domain}-${method}-${route.pattern}` : `${method}-${route.pattern}`;
|
|
46
|
+
}
|
|
47
|
+
add(route) {
|
|
48
|
+
if (route.domain !== 'root') {
|
|
49
|
+
this.usingDomains = true;
|
|
50
|
+
}
|
|
51
|
+
const tokens = matchit.parse(route.pattern, route.matchers);
|
|
52
|
+
const routeNode = lodash.merge({ meta: {} }, lodash.pick(route, ['pattern', 'handler', 'meta', 'middleware', 'name', 'execute']));
|
|
53
|
+
routeNode.meta.params = this.#collectRouteParams(routeNode, tokens);
|
|
54
|
+
route.methods.forEach((method) => {
|
|
55
|
+
this.#registerRoute(route.domain, method, tokens, routeNode);
|
|
56
|
+
});
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
match(url, method, domain) {
|
|
60
|
+
const domainName = domain?.tokens[0]?.old || 'root';
|
|
61
|
+
const matchedDomain = this.tree.domains[domainName];
|
|
62
|
+
if (!matchedDomain) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const matchedMethod = this.tree.domains[domainName][method];
|
|
66
|
+
if (!matchedMethod) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
const matchedRoute = matchit.match(url, matchedMethod.tokens);
|
|
70
|
+
if (!matchedRoute.length) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const route = matchedMethod.routes[matchedRoute[0].old];
|
|
74
|
+
return {
|
|
75
|
+
route: route,
|
|
76
|
+
routeKey: matchedMethod.routeKeys[route.pattern],
|
|
77
|
+
params: matchit.exec(url, matchedRoute),
|
|
78
|
+
subdomains: domain?.hostname ? matchit.exec(domain.hostname, domain.tokens) : {},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
matchDomain(hostname) {
|
|
82
|
+
if (!hostname || !this.usingDomains) {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
return matchit.match(hostname, this.tree.tokens);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ContainerResolver } from '@adonisjs/fold';
|
|
2
|
+
import type { Router } from '../../router/main.js';
|
|
3
|
+
import type { HttpContext } from '../../http_context/main.js';
|
|
4
|
+
export declare function finalHandler(router: Router, resolver: ContainerResolver<any>, ctx: HttpContext): () => any;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RouteNotFoundException } from '../../exceptions/route_not_found.js';
|
|
2
|
+
export function finalHandler(router, resolver, ctx) {
|
|
3
|
+
return function () {
|
|
4
|
+
const url = ctx.request.url();
|
|
5
|
+
const method = ctx.request.method();
|
|
6
|
+
const hostname = router.usingDomains ? ctx.request.hostname() : undefined;
|
|
7
|
+
const route = router.match(url, method, hostname);
|
|
8
|
+
if (route) {
|
|
9
|
+
ctx.params = route.params;
|
|
10
|
+
ctx.subdomains = route.subdomains;
|
|
11
|
+
ctx.route = route.route;
|
|
12
|
+
ctx.routeKey = route.routeKey;
|
|
13
|
+
return route.route.execute(route.route, resolver, ctx);
|
|
14
|
+
}
|
|
15
|
+
throw new RouteNotFoundException(`Cannot ${method}:${url}`);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { NextFn } from '@poppinss/middleware/types';
|
|
2
|
+
import type { ContainerResolver } from '@adonisjs/fold';
|
|
3
|
+
import type { HttpContext } from '../../http_context/main.js';
|
|
4
|
+
import { ParsedGlobalMiddleware } from '../../types/middleware.js';
|
|
5
|
+
export declare function middlewareHandler(resolver: ContainerResolver<any>, ctx: HttpContext): (fn: ParsedGlobalMiddleware, next: NextFn) => any;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function writeResponse(ctx) {
|
|
2
|
+
return function () {
|
|
3
|
+
try {
|
|
4
|
+
ctx.response.finish();
|
|
5
|
+
}
|
|
6
|
+
catch (error) {
|
|
7
|
+
ctx.logger.fatal({ err: error }, 'Response serialization failed');
|
|
8
|
+
ctx.response.internalServerError(error.message);
|
|
9
|
+
ctx.response.finish();
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
3
|
+
import type { Encryption } from '@adonisjs/encryption';
|
|
4
|
+
import type { Application } from '@adonisjs/application';
|
|
5
|
+
import type { Server as HttpsServer } from 'node:https';
|
|
6
|
+
import type { ServerResponse, IncomingMessage, Server as HttpServer } from 'node:http';
|
|
7
|
+
import type { LazyImport } from '../types/base.js';
|
|
8
|
+
import type { MiddlewareAsClass } from '../types/middleware.js';
|
|
9
|
+
import type { ErrorHandlerAsAClass, ServerConfig } from '../types/server.js';
|
|
10
|
+
import { Router } from '../router/main.js';
|
|
11
|
+
export declare class Server<NamedMiddleware extends Record<string, LazyImport<MiddlewareAsClass>> = any> {
|
|
12
|
+
#private;
|
|
13
|
+
get usingAsyncLocalStorage(): boolean;
|
|
14
|
+
constructor(app: Application<any, any, any>, encryption: Encryption, config: ServerConfig);
|
|
15
|
+
use(serverMiddleware: LazyImport<MiddlewareAsClass>[], routerMiddleware: LazyImport<MiddlewareAsClass>[], namedMiddleware: NamedMiddleware): this;
|
|
16
|
+
errorHandler(handler: LazyImport<ErrorHandlerAsAClass>): this;
|
|
17
|
+
boot(): Promise<void>;
|
|
18
|
+
setNodeServer(server: HttpServer | HttpsServer): void;
|
|
19
|
+
close(): Promise<void>;
|
|
20
|
+
getNodeServer(): HttpServer<typeof IncomingMessage, typeof ServerResponse> | HttpsServer<typeof IncomingMessage, typeof ServerResponse> | undefined;
|
|
21
|
+
getRouter(): Router<any> | undefined;
|
|
22
|
+
handle(req: IncomingMessage, res: ServerResponse): Promise<any>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import Middleware from '@poppinss/middleware';
|
|
2
|
+
import { RuntimeException } from '@poppinss/utils';
|
|
3
|
+
import { Qs } from '../qs.js';
|
|
4
|
+
import debug from '../debug.js';
|
|
5
|
+
import { Request } from '../request.js';
|
|
6
|
+
import { Response } from '../response.js';
|
|
7
|
+
import { Router } from '../router/main.js';
|
|
8
|
+
import { HttpContext } from '../http_context/main.js';
|
|
9
|
+
import { MiddlewareStore } from '../middleware/store.js';
|
|
10
|
+
import { finalHandler } from './factories/final_handler.js';
|
|
11
|
+
import { writeResponse } from './factories/write_response.js';
|
|
12
|
+
import { useReturnValue } from './factories/use_return_value.js';
|
|
13
|
+
import { asyncLocalStorage } from '../http_context/local_storage.js';
|
|
14
|
+
import { middlewareHandler } from './factories/middleware_handler.js';
|
|
15
|
+
export class Server {
|
|
16
|
+
#errorHandler;
|
|
17
|
+
#resolvedErrorHandler = {
|
|
18
|
+
handle(error, ctx) {
|
|
19
|
+
ctx.response.status(error.status || 500).send(error.message || 'Internal server error');
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
#app;
|
|
23
|
+
#encryption;
|
|
24
|
+
#config;
|
|
25
|
+
#qsParser;
|
|
26
|
+
#serverMiddlewareStack;
|
|
27
|
+
#router;
|
|
28
|
+
#underlyingHttpServer;
|
|
29
|
+
get usingAsyncLocalStorage() {
|
|
30
|
+
return asyncLocalStorage.isEnabled;
|
|
31
|
+
}
|
|
32
|
+
constructor(app, encryption, config) {
|
|
33
|
+
this.#app = app;
|
|
34
|
+
this.#encryption = encryption;
|
|
35
|
+
this.#config = config;
|
|
36
|
+
this.#qsParser = new Qs(this.#config.qs);
|
|
37
|
+
this.#createAsyncLocalStore();
|
|
38
|
+
debug('server config: %O', this.#config);
|
|
39
|
+
}
|
|
40
|
+
#createAsyncLocalStore() {
|
|
41
|
+
if (this.#config.useAsyncLocalStorage) {
|
|
42
|
+
debug('creating http context async local storage');
|
|
43
|
+
asyncLocalStorage.create();
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
asyncLocalStorage.destroy();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
#createRouter(middlewareStore) {
|
|
50
|
+
this.#router = new Router(this.#app, this.#encryption, middlewareStore, this.#qsParser);
|
|
51
|
+
}
|
|
52
|
+
#createServerMiddlewareStack(middlewareStore) {
|
|
53
|
+
this.#serverMiddlewareStack = new Middleware();
|
|
54
|
+
middlewareStore.list().forEach((middleware) => this.#serverMiddlewareStack.add(middleware));
|
|
55
|
+
this.#serverMiddlewareStack.freeze();
|
|
56
|
+
}
|
|
57
|
+
#createContext(req, res) {
|
|
58
|
+
const request = new Request(req, res, this.#encryption, this.#config, this.#qsParser);
|
|
59
|
+
const response = new Response(req, res, this.#encryption, this.#config, this.#router, this.#qsParser);
|
|
60
|
+
return new HttpContext(request, response, this.#app.logger.child({}));
|
|
61
|
+
}
|
|
62
|
+
use(serverMiddleware, routerMiddleware, namedMiddleware) {
|
|
63
|
+
this.#createRouter(new MiddlewareStore(routerMiddleware, namedMiddleware));
|
|
64
|
+
this.#createServerMiddlewareStack(new MiddlewareStore(serverMiddleware));
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
errorHandler(handler) {
|
|
68
|
+
this.#errorHandler = handler;
|
|
69
|
+
return this;
|
|
70
|
+
}
|
|
71
|
+
async boot() {
|
|
72
|
+
debug('booting HTTP server');
|
|
73
|
+
if (!this.#router) {
|
|
74
|
+
throw new RuntimeException('Cannot boot HTTP server. Register middleware using "server.use" first');
|
|
75
|
+
}
|
|
76
|
+
this.#router.commit();
|
|
77
|
+
if (this.#errorHandler) {
|
|
78
|
+
if (debug.enabled) {
|
|
79
|
+
debug('using custom error handler "%s"', this.#errorHandler);
|
|
80
|
+
}
|
|
81
|
+
const moduleExports = await this.#errorHandler();
|
|
82
|
+
this.#resolvedErrorHandler = await this.#app.container.make(moduleExports.default);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
#handleRequest(ctx, resolver) {
|
|
86
|
+
return this.#serverMiddlewareStack.runner()
|
|
87
|
+
.finalHandler(finalHandler(this.#router, resolver, ctx))
|
|
88
|
+
.run(middlewareHandler(resolver, ctx))
|
|
89
|
+
.then(useReturnValue(ctx))
|
|
90
|
+
.catch((error) => this.#resolvedErrorHandler.handle(error, ctx))
|
|
91
|
+
.finally(writeResponse(ctx));
|
|
92
|
+
}
|
|
93
|
+
setNodeServer(server) {
|
|
94
|
+
this.#underlyingHttpServer = server;
|
|
95
|
+
}
|
|
96
|
+
close() {
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
if (!this.#underlyingHttpServer || !this.#underlyingHttpServer.listening) {
|
|
99
|
+
resolve();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
this.#underlyingHttpServer.close((error) => {
|
|
103
|
+
if (error) {
|
|
104
|
+
return reject(error);
|
|
105
|
+
}
|
|
106
|
+
resolve();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
getNodeServer() {
|
|
111
|
+
return this.#underlyingHttpServer;
|
|
112
|
+
}
|
|
113
|
+
getRouter() {
|
|
114
|
+
return this.#router;
|
|
115
|
+
}
|
|
116
|
+
handle(req, res) {
|
|
117
|
+
const ctx = this.#createContext(req, res);
|
|
118
|
+
const resolver = this.#app.container.createResolver();
|
|
119
|
+
if (this.usingAsyncLocalStorage) {
|
|
120
|
+
return asyncLocalStorage.storage.run(ctx, () => this.#handleRequest(ctx, resolver));
|
|
121
|
+
}
|
|
122
|
+
return this.#handleRequest(ctx, resolver);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ContainerResolver } from '@adonisjs/fold';
|
|
2
|
+
import type { NextFn } from '@poppinss/middleware/types';
|
|
3
|
+
import type { Constructor } from './base.js';
|
|
4
|
+
import type { HttpContext } from '../http_context/main.js';
|
|
5
|
+
export type MiddlewareAsClass = Constructor<{
|
|
6
|
+
handle: (ctx: HttpContext, next: NextFn, args?: any) => any;
|
|
7
|
+
}>;
|
|
8
|
+
type HasUndefined<T> = T extends NonNullable<T> ? true : false;
|
|
9
|
+
export type GetMiddlewareArgs<Middleware extends MiddlewareAsClass> = HasUndefined<Parameters<InstanceType<Middleware>['handle']>[2]> extends true ? [Parameters<InstanceType<Middleware>['handle']>[2]] : [Parameters<InstanceType<Middleware>['handle']>[2]?];
|
|
10
|
+
export type MiddlewareFn = (ctx: HttpContext, next: NextFn) => any;
|
|
11
|
+
export type ParsedGlobalMiddleware = {
|
|
12
|
+
handle: (resolver: ContainerResolver<any>, ...args: [ctx: HttpContext, next: NextFn, params?: any]) => any;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type QSParserConfig = {
|
|
2
|
+
parse: {
|
|
3
|
+
depth: number;
|
|
4
|
+
parameterLimit: number;
|
|
5
|
+
allowSparse: boolean;
|
|
6
|
+
arrayLimit: number;
|
|
7
|
+
comma: boolean;
|
|
8
|
+
};
|
|
9
|
+
stringify: {
|
|
10
|
+
encode: boolean;
|
|
11
|
+
encodeValuesOnly: boolean;
|
|
12
|
+
arrayFormat: 'indices' | 'brackets' | 'repeat' | 'comma';
|
|
13
|
+
skipNulls: boolean;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|