@deepkit/http 1.0.1-alpha.16 → 1.0.1-alpha.160
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/CHANGELOG.md +236 -0
- package/dist/cjs/index.d.ts +14 -10
- package/dist/cjs/index.js +19 -11
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/src/controllers.d.ts +10 -3
- package/dist/cjs/src/controllers.js +7 -3
- package/dist/cjs/src/controllers.js.map +1 -1
- package/dist/cjs/src/decorator.d.ts +144 -70
- package/dist/cjs/src/decorator.js +277 -102
- package/dist/cjs/src/decorator.js.map +1 -1
- package/dist/cjs/src/filter.d.ts +49 -0
- package/dist/cjs/src/filter.js +215 -0
- package/dist/cjs/src/filter.js.map +1 -0
- package/dist/cjs/src/http-app.d.ts +8 -0
- package/dist/cjs/src/http-app.js +16 -0
- package/dist/cjs/src/http-app.js.map +1 -0
- package/dist/cjs/src/http.d.ts +131 -32
- package/dist/cjs/src/http.js +523 -122
- package/dist/cjs/src/http.js.map +1 -1
- package/dist/cjs/src/kernel.d.ts +50 -9
- package/dist/cjs/src/kernel.js +109 -98
- package/dist/cjs/src/kernel.js.map +1 -1
- package/dist/cjs/src/logger.d.ts +3 -3
- package/dist/cjs/src/logger.js +9 -12
- package/dist/cjs/src/logger.js.map +1 -1
- package/dist/cjs/src/middleware.d.ts +61 -0
- package/dist/cjs/src/middleware.js +95 -0
- package/dist/cjs/src/middleware.js.map +1 -0
- package/dist/cjs/src/model.d.ts +270 -4
- package/dist/cjs/src/model.js +401 -3
- package/dist/cjs/src/model.js.map +1 -1
- package/dist/cjs/src/module.config.d.ts +149 -4
- package/dist/cjs/src/module.config.js +11 -6
- package/dist/cjs/src/module.config.js.map +1 -1
- package/dist/cjs/src/module.d.ts +14 -32
- package/dist/cjs/src/module.js +122 -7
- package/dist/cjs/src/module.js.map +1 -1
- package/dist/cjs/src/request-parser.d.ts +37 -0
- package/dist/cjs/src/request-parser.js +382 -0
- package/dist/cjs/src/request-parser.js.map +1 -0
- package/dist/cjs/src/router.d.ts +174 -75
- package/dist/cjs/src/router.js +469 -288
- package/dist/cjs/src/router.js.map +1 -1
- package/dist/cjs/src/static-serving.d.ts +32 -4
- package/dist/cjs/src/static-serving.js +115 -71
- package/dist/cjs/src/static-serving.js.map +1 -1
- package/dist/cjs/src/utils.js +2 -2
- package/dist/cjs/src/utils.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -2916
- package/dist/esm/index.d.ts +14 -10
- package/dist/esm/index.js +14 -10
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/src/controllers.d.ts +10 -3
- package/dist/esm/src/controllers.js +7 -3
- package/dist/esm/src/controllers.js.map +1 -1
- package/dist/esm/src/decorator.d.ts +144 -70
- package/dist/esm/src/decorator.js +272 -99
- package/dist/esm/src/decorator.js.map +1 -1
- package/dist/esm/src/filter.d.ts +49 -0
- package/dist/esm/src/filter.js +209 -0
- package/dist/esm/src/filter.js.map +1 -0
- package/dist/esm/src/http-app.d.ts +8 -0
- package/dist/esm/src/http-app.js +12 -0
- package/dist/esm/src/http-app.js.map +1 -0
- package/dist/esm/src/http.d.ts +131 -32
- package/dist/esm/src/http.js +504 -121
- package/dist/esm/src/http.js.map +1 -1
- package/dist/esm/src/kernel.d.ts +50 -9
- package/dist/esm/src/kernel.js +110 -100
- package/dist/esm/src/kernel.js.map +1 -1
- package/dist/esm/src/logger.d.ts +3 -3
- package/dist/esm/src/logger.js +7 -11
- package/dist/esm/src/logger.js.map +1 -1
- package/dist/esm/src/middleware.d.ts +61 -0
- package/dist/esm/src/middleware.js +90 -0
- package/dist/esm/src/middleware.js.map +1 -0
- package/dist/esm/src/model.d.ts +270 -4
- package/dist/esm/src/model.js +357 -1
- package/dist/esm/src/model.js.map +1 -1
- package/dist/esm/src/module.config.d.ts +149 -4
- package/dist/esm/src/module.config.js +9 -5
- package/dist/esm/src/module.config.js.map +1 -1
- package/dist/esm/src/module.d.ts +14 -32
- package/dist/esm/src/module.js +121 -7
- package/dist/esm/src/module.js.map +1 -1
- package/dist/esm/src/request-parser.d.ts +37 -0
- package/dist/esm/src/request-parser.js +372 -0
- package/dist/esm/src/request-parser.js.map +1 -0
- package/dist/esm/src/router.d.ts +174 -75
- package/dist/esm/src/router.js +463 -285
- package/dist/esm/src/router.js.map +1 -1
- package/dist/esm/src/static-serving.d.ts +32 -4
- package/dist/esm/src/static-serving.js +107 -65
- package/dist/esm/src/static-serving.js.map +1 -1
- package/dist/esm/src/utils.js +1 -0
- package/dist/esm/src/utils.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -2916
- package/index.ts +14 -10
- package/package.json +30 -19
- package/src/controllers.ts +4 -3
- package/src/decorator.ts +242 -104
- package/src/filter.ts +224 -0
- package/src/http-app.ts +11 -0
- package/src/http.ts +501 -100
- package/src/kernel.ts +128 -80
- package/src/logger.ts +4 -6
- package/src/middleware.ts +116 -0
- package/src/model.ts +516 -5
- package/src/module.config.ts +168 -5
- package/src/module.ts +120 -7
- package/src/request-parser.ts +430 -0
- package/src/router.ts +546 -317
- package/src/static-serving.ts +120 -50
- package/src/utils.ts +0 -2
- package/tsconfig.esm.json +7 -7
- package/tsconfig.json +18 -11
- package/tsconfig.spec.json +8 -0
- package/dist/cjs/tests/router.spec.d.ts +0 -1
- package/dist/cjs/tests/router.spec.js +0 -481
- package/dist/cjs/tests/router.spec.js.map +0 -1
- package/dist/esm/tests/router.spec.d.ts +0 -1
- package/dist/esm/tests/router.spec.js +0 -479
- package/dist/esm/tests/router.spec.js.map +0 -1
- package/tests/router.spec.ts +0 -347
package/src/module.config.ts
CHANGED
|
@@ -1,6 +1,169 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export interface HttpParserOptions {
|
|
2
|
+
/**
|
|
3
|
+
* sets encoding for incoming form fields
|
|
4
|
+
*
|
|
5
|
+
* @default 'utf-8'
|
|
6
|
+
*/
|
|
7
|
+
encoding?: string | undefined;
|
|
3
8
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
/**
|
|
10
|
+
* the directory for placing file uploads in. You can move them later by using fs.rename()
|
|
11
|
+
*
|
|
12
|
+
* @default os.tmpdir()
|
|
13
|
+
*/
|
|
14
|
+
uploadDir?: string | undefined;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* to include the extensions of the original files or not
|
|
18
|
+
*
|
|
19
|
+
* @default false
|
|
20
|
+
*/
|
|
21
|
+
keepExtensions?: boolean | undefined;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* allow upload empty files
|
|
25
|
+
*
|
|
26
|
+
* @default true
|
|
27
|
+
*/
|
|
28
|
+
allowEmptyFiles?: boolean | undefined;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* the minium size of uploaded file
|
|
32
|
+
*
|
|
33
|
+
* @default 1
|
|
34
|
+
*/
|
|
35
|
+
minFileSize?: number | undefined;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* limit the amount of uploaded files, set Infinity for unlimited
|
|
39
|
+
*
|
|
40
|
+
* @default Infinity
|
|
41
|
+
*/
|
|
42
|
+
maxFiles?: number | undefined;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* limit the size of uploaded file
|
|
46
|
+
*
|
|
47
|
+
* @default 200 * 1024 * 1024
|
|
48
|
+
*/
|
|
49
|
+
maxFileSize?: number | undefined;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* limit the size of the batch of uploaded files
|
|
53
|
+
*
|
|
54
|
+
* @default options.maxFileSize
|
|
55
|
+
*/
|
|
56
|
+
maxTotalFileSize?: number | undefined;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* limit the number of fields, set 0 for unlimited
|
|
60
|
+
*
|
|
61
|
+
* @default 1000
|
|
62
|
+
*/
|
|
63
|
+
maxFields?: number | undefined;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* limit the amount of memory all fields together (except files) can allocate in bytes
|
|
67
|
+
*
|
|
68
|
+
* @default 20 * 1024 * 1024
|
|
69
|
+
*/
|
|
70
|
+
maxFieldsSize?: number | undefined;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* include checksums calculated for incoming files, set this to some hash algorithm, see
|
|
74
|
+
* crypto.createHash for available algorithms
|
|
75
|
+
*
|
|
76
|
+
* @default false
|
|
77
|
+
*/
|
|
78
|
+
hashAlgorithm?: string | false | undefined;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* when you call the .parse method, the files argument (of the callback) will contain arrays of
|
|
82
|
+
* files for inputs which submit multiple files using the HTML5 multiple attribute. Also, the
|
|
83
|
+
* fields argument will contain arrays of values for fields that have names ending with '[]'
|
|
84
|
+
*
|
|
85
|
+
* @default false
|
|
86
|
+
*/
|
|
87
|
+
multiples?: boolean | undefined;
|
|
88
|
+
|
|
89
|
+
enabledPlugins?: string[] | undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export class HttpConfig {
|
|
93
|
+
|
|
94
|
+
debug: boolean = false;
|
|
95
|
+
|
|
96
|
+
parser: HttpParserOptions = {};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Limits maximum incoming headers count. If set to 0, no limit will be applied.
|
|
100
|
+
*/
|
|
101
|
+
maxHeadersCount?: number;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The maximum number of requests socket can handle
|
|
105
|
+
* before closing keep alive connection.
|
|
106
|
+
*
|
|
107
|
+
* A value of `0` will disable the limit.
|
|
108
|
+
*
|
|
109
|
+
* When the limit is reached it will set the `Connection` header value to `close`,
|
|
110
|
+
* but will not actually close the connection, subsequent requests sent
|
|
111
|
+
* after the limit is reached will get `503 Service Unavailable` as a response.
|
|
112
|
+
*/
|
|
113
|
+
maxRequestsPerSocket?: number;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The number of milliseconds of inactivity before a socket is presumed
|
|
117
|
+
* to have timed out.
|
|
118
|
+
*
|
|
119
|
+
* A value of `0` will disable the timeout behavior on incoming connections.
|
|
120
|
+
*
|
|
121
|
+
* The socket timeout logic is set up on connection, so changing this
|
|
122
|
+
* value only affects new connections to the server, not any existing connections.
|
|
123
|
+
*/
|
|
124
|
+
timeout?: number;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Limit the amount of time the parser will wait to receive the complete HTTP
|
|
128
|
+
* headers.
|
|
129
|
+
*
|
|
130
|
+
* If the timeout expires, the server responds with status 408 without
|
|
131
|
+
* forwarding the request to the request listener and then closes the connection.
|
|
132
|
+
*
|
|
133
|
+
* It must be set to a non-zero value (e.g. 120 seconds) to protect against
|
|
134
|
+
* potential Denial-of-Service attacks in case the server is deployed without a
|
|
135
|
+
* reverse proxy in front.
|
|
136
|
+
*/
|
|
137
|
+
headersTimeout?: number;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The number of milliseconds of inactivity a server needs to wait for additional
|
|
141
|
+
* incoming data, after it has finished writing the last response, before a socket
|
|
142
|
+
* will be destroyed. If the server receives new data before the keep-alive
|
|
143
|
+
* timeout has fired, it will reset the regular inactivity timeout, i.e., `server.timeout`.
|
|
144
|
+
*
|
|
145
|
+
* A value of `0` will disable the keep-alive timeout behavior on incoming
|
|
146
|
+
* connections.
|
|
147
|
+
* A value of `0` makes the http server behave similarly to Node.js versions prior
|
|
148
|
+
* to 8.0.0, which did not have a keep-alive timeout.
|
|
149
|
+
*
|
|
150
|
+
* The socket timeout logic is set up on connection, so changing this value only
|
|
151
|
+
* affects new connections to the server, not any existing connections.
|
|
152
|
+
*/
|
|
153
|
+
keepAliveTimeout?: number;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Sets the timeout value in milliseconds for receiving the entire request from
|
|
157
|
+
* the client.
|
|
158
|
+
*
|
|
159
|
+
* If the timeout expires, the server responds with status 408 without
|
|
160
|
+
* forwarding the request to the request listener and then closes the connection.
|
|
161
|
+
*
|
|
162
|
+
* It must be set to a non-zero value (e.g. 120 seconds) to protect against
|
|
163
|
+
* potential Denial-of-Service attacks in case the server is deployed without a
|
|
164
|
+
* reverse proxy in front.
|
|
165
|
+
*
|
|
166
|
+
* Default is 5 minutes.
|
|
167
|
+
*/
|
|
168
|
+
requestTimeout?: number;
|
|
169
|
+
}
|
package/src/module.ts
CHANGED
|
@@ -1,11 +1,124 @@
|
|
|
1
|
-
import { httpWorkflow } from './http';
|
|
2
|
-
import {
|
|
3
|
-
import { AppModule } from '@deepkit/app';
|
|
1
|
+
import { HttpListener, HttpResultFormatter, httpWorkflow } from './http.js';
|
|
2
|
+
import { HttpConfig } from './module.config.js';
|
|
3
|
+
import { AddedListener, AppModule, ControllerConfig, createModuleClass, stringifyListener } from '@deepkit/app';
|
|
4
|
+
import { HttpRouter, HttpRouterRegistry, RouteConfig } from './router.js';
|
|
5
|
+
import { HttpKernel } from './kernel.js';
|
|
6
|
+
import { HttpRouterFilterResolver } from './filter.js';
|
|
7
|
+
import { HttpControllers } from './controllers.js';
|
|
8
|
+
import { ConsoleTransport, Logger } from '@deepkit/logger';
|
|
9
|
+
import { HttpRequest, HttpResponse } from './model.js';
|
|
10
|
+
import '@deepkit/type';
|
|
11
|
+
import { httpClass } from './decorator.js';
|
|
12
|
+
import { EventToken } from '@deepkit/event';
|
|
13
|
+
import { ReflectionKind, ReflectionParameter, Type, typeAnnotation } from '@deepkit/type';
|
|
14
|
+
import { buildRequestParser } from './request-parser.js';
|
|
15
|
+
import { InjectorContext } from '@deepkit/injector';
|
|
4
16
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
17
|
+
function parameterRequiresRequest(parameter: ReflectionParameter): boolean {
|
|
18
|
+
return Boolean(typeAnnotation.getType(parameter.type, 'httpQueries')
|
|
19
|
+
|| typeAnnotation.getType(parameter.type, 'httpQuery')
|
|
20
|
+
|| typeAnnotation.getType(parameter.type, 'httpBody')
|
|
21
|
+
|| typeAnnotation.getType(parameter.type, 'httpRequestParser')
|
|
22
|
+
|| typeAnnotation.getType(parameter.type, 'httpPath')
|
|
23
|
+
|| typeAnnotation.getType(parameter.type, 'httpHeader'));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
export class HttpModule extends createModuleClass({
|
|
28
|
+
config: HttpConfig,
|
|
29
|
+
providers: [
|
|
30
|
+
HttpRouter,
|
|
31
|
+
HttpKernel,
|
|
32
|
+
HttpResultFormatter,
|
|
33
|
+
HttpRouterRegistry,
|
|
34
|
+
HttpRouterFilterResolver,
|
|
35
|
+
{ provide: HttpResponse, scope: 'http' },
|
|
36
|
+
{ provide: HttpRequest, scope: 'http' },
|
|
37
|
+
{ provide: RouteConfig, useValue: undefined, scope: 'http' },
|
|
38
|
+
{ provide: Logger, useValue: new Logger([new ConsoleTransport()]) },
|
|
39
|
+
],
|
|
40
|
+
listeners: [
|
|
41
|
+
HttpListener,
|
|
42
|
+
],
|
|
8
43
|
workflows: [
|
|
9
44
|
httpWorkflow
|
|
10
45
|
],
|
|
11
|
-
|
|
46
|
+
exports: [
|
|
47
|
+
HttpRouter,
|
|
48
|
+
HttpRouterRegistry,
|
|
49
|
+
HttpKernel,
|
|
50
|
+
HttpResultFormatter,
|
|
51
|
+
HttpRouterFilterResolver,
|
|
52
|
+
HttpResponse,
|
|
53
|
+
HttpRequest,
|
|
54
|
+
HttpControllers,
|
|
55
|
+
RouteConfig,
|
|
56
|
+
Logger,
|
|
57
|
+
]
|
|
58
|
+
}) {
|
|
59
|
+
protected httpControllers = new HttpControllers;
|
|
60
|
+
|
|
61
|
+
process() {
|
|
62
|
+
this.addProvider({ provide: HttpControllers, useValue: this.httpControllers });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
protected patchEventsForHttpRequestAccess: EventToken<any>[] = [httpWorkflow.onRequest, httpWorkflow.onAuth, httpWorkflow.onController];
|
|
66
|
+
|
|
67
|
+
processListener(module: AppModule<any>, listener: AddedListener) {
|
|
68
|
+
if (!this.patchEventsForHttpRequestAccess.includes(listener.eventToken)) return;
|
|
69
|
+
|
|
70
|
+
let requiresHttpRequest = false;
|
|
71
|
+
let needsAsync = false;
|
|
72
|
+
const params = listener.reflection.getParameters().slice(1);
|
|
73
|
+
|
|
74
|
+
for (const parameter of params) {
|
|
75
|
+
if (typeAnnotation.getType(parameter.type, 'httpBody')) needsAsync = true;
|
|
76
|
+
if (parameterRequiresRequest(parameter)) requiresHttpRequest = true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (needsAsync) {
|
|
80
|
+
//not yet supported since we have to patch the listener to be async and redirect the call (as the DI container is sync).
|
|
81
|
+
throw new Error(`Listener ${stringifyListener(listener)} requires async HttpBody. This is not yet supported. You have to parse the request manually by injecting HttpRequest.`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const parserCache = new Map<RouteConfig, Function>();
|
|
85
|
+
|
|
86
|
+
for (let index = 0; index < params.length; index++) {
|
|
87
|
+
const parameter = params[index];
|
|
88
|
+
if (!parameterRequiresRequest(parameter)) continue;
|
|
89
|
+
|
|
90
|
+
//change the reflection type so that we create a unique injection token for that type.
|
|
91
|
+
const unique = Symbol('event.parameter:' + parameter.name);
|
|
92
|
+
const uniqueType: Type = { kind: ReflectionKind.literal, literal: unique };
|
|
93
|
+
typeAnnotation.registerType(parameter.type, { name: 'inject', options: uniqueType });
|
|
94
|
+
let i = index;
|
|
95
|
+
|
|
96
|
+
this.addProvider({
|
|
97
|
+
provide: uniqueType, useFactory: (httpConfig: HttpConfig, request: HttpRequest, injector: InjectorContext, config?: RouteConfig) => {
|
|
98
|
+
let build = config && parserCache.get(config);
|
|
99
|
+
if (!build) {
|
|
100
|
+
const params = listener.reflection.getParameters().slice(1);
|
|
101
|
+
build = buildRequestParser(httpConfig.parser, params, config);
|
|
102
|
+
if (config) parserCache.set(config, build);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const parser = build(request);
|
|
106
|
+
const result = parser(injector);
|
|
107
|
+
return result.arguments[i];
|
|
108
|
+
}, scope: 'http'
|
|
109
|
+
});
|
|
110
|
+
this.addExport(uniqueType);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
processController(module: AppModule<any>, config: ControllerConfig) {
|
|
115
|
+
const controller = config.controller;
|
|
116
|
+
if (!controller) return;
|
|
117
|
+
|
|
118
|
+
const httpConfig = httpClass._fetch(controller);
|
|
119
|
+
if (!httpConfig) return;
|
|
120
|
+
|
|
121
|
+
if (!module.isProvided(controller)) module.addProvider({ provide: controller, scope: 'http' });
|
|
122
|
+
this.httpControllers.add(controller, module);
|
|
123
|
+
}
|
|
124
|
+
}
|