@deepkit/http 1.0.1-alpha.85 → 1.0.1-alpha.86
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/dist/cjs/src/controllers.js +1 -0
- package/dist/cjs/src/controllers.js.map +1 -1
- package/dist/cjs/src/decorator.js +12 -0
- package/dist/cjs/src/decorator.js.map +1 -1
- package/dist/cjs/src/filter.js +1 -0
- package/dist/cjs/src/filter.js.map +1 -1
- package/dist/cjs/src/http.d.ts +2 -0
- package/dist/cjs/src/http.js +31 -4
- package/dist/cjs/src/http.js.map +1 -1
- package/dist/cjs/src/kernel.js +1 -0
- package/dist/cjs/src/kernel.js.map +1 -1
- package/dist/cjs/src/logger.js +1 -0
- package/dist/cjs/src/logger.js.map +1 -1
- package/dist/cjs/src/middleware.js +1 -0
- package/dist/cjs/src/middleware.js.map +1 -1
- package/dist/cjs/src/model.d.ts +12 -5
- package/dist/cjs/src/model.js +79 -37
- package/dist/cjs/src/model.js.map +1 -1
- package/dist/cjs/src/module.js +1 -0
- package/dist/cjs/src/module.js.map +1 -1
- package/dist/cjs/src/router.js +28 -6
- package/dist/cjs/src/router.js.map +1 -1
- package/dist/cjs/src/static-serving.js +1 -0
- package/dist/cjs/src/static-serving.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/src/controllers.js +1 -0
- package/dist/esm/src/controllers.js.map +1 -1
- package/dist/esm/src/decorator.js +12 -0
- package/dist/esm/src/decorator.js.map +1 -1
- package/dist/esm/src/filter.js +1 -0
- package/dist/esm/src/filter.js.map +1 -1
- package/dist/esm/src/http.d.ts +2 -0
- package/dist/esm/src/http.js +33 -6
- package/dist/esm/src/http.js.map +1 -1
- package/dist/esm/src/kernel.js +1 -0
- package/dist/esm/src/kernel.js.map +1 -1
- package/dist/esm/src/logger.js +1 -0
- package/dist/esm/src/logger.js.map +1 -1
- package/dist/esm/src/middleware.js +1 -0
- package/dist/esm/src/middleware.js.map +1 -1
- package/dist/esm/src/model.d.ts +12 -5
- package/dist/esm/src/model.js +77 -37
- package/dist/esm/src/model.js.map +1 -1
- package/dist/esm/src/module.js +1 -0
- package/dist/esm/src/module.js.map +1 -1
- package/dist/esm/src/router.js +29 -7
- package/dist/esm/src/router.js.map +1 -1
- package/dist/esm/src/static-serving.js +1 -0
- package/dist/esm/src/static-serving.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/src/http.ts +57 -12
- package/src/model.ts +74 -36
- package/src/router.ts +25 -8
package/src/model.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { UploadedFile } from './router';
|
|
|
13
13
|
import * as querystring from 'querystring';
|
|
14
14
|
import { Writable } from 'stream';
|
|
15
15
|
import { metaAnnotation, ReflectionKind, Type, ValidationErrorItem } from '@deepkit/type';
|
|
16
|
-
import { isArray } from '@deepkit/core';
|
|
16
|
+
import { asyncOperation, isArray } from '@deepkit/core';
|
|
17
17
|
|
|
18
18
|
export class HttpResponse extends ServerResponse {
|
|
19
19
|
status(code: number) {
|
|
@@ -22,6 +22,62 @@ export class HttpResponse extends ServerResponse {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Reads the body of the request and returns it as a Buffer.
|
|
27
|
+
* The result will be cached in the request object as `request.body`.
|
|
28
|
+
*
|
|
29
|
+
* Deepkit's router will automatically use `request.body` if available.
|
|
30
|
+
*/
|
|
31
|
+
export function readBody(request: IncomingMessage): Promise<Buffer> {
|
|
32
|
+
return asyncOperation((resolve, reject) => {
|
|
33
|
+
const chunks: Buffer[] = [];
|
|
34
|
+
request.on('data', (chunk: Buffer) => {
|
|
35
|
+
chunks.push(chunk);
|
|
36
|
+
});
|
|
37
|
+
request.on('end', () => {
|
|
38
|
+
const body = Buffer.concat(chunks);
|
|
39
|
+
//the router uses this now instead of trying to read the body again
|
|
40
|
+
(request as HttpRequest).body = body;
|
|
41
|
+
resolve(body);
|
|
42
|
+
});
|
|
43
|
+
request.on('error', (error: Error) => {
|
|
44
|
+
reject(error);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function createRequestWithCachedBody(request: Partial<IncomingMessage>, body: Buffer): HttpRequest {
|
|
50
|
+
const headers = request.headers;
|
|
51
|
+
const method = request.method;
|
|
52
|
+
const url = request.url;
|
|
53
|
+
|
|
54
|
+
const writable = new Writable({
|
|
55
|
+
write(chunk, encoding, callback) {
|
|
56
|
+
callback();
|
|
57
|
+
},
|
|
58
|
+
writev(chunks, callback) {
|
|
59
|
+
callback();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return new (class extends HttpRequest {
|
|
63
|
+
url = url;
|
|
64
|
+
method = method;
|
|
65
|
+
position = 0;
|
|
66
|
+
|
|
67
|
+
headers = headers as any;
|
|
68
|
+
|
|
69
|
+
_read(size: number) {
|
|
70
|
+
if (this.complete) {
|
|
71
|
+
this.push(null);
|
|
72
|
+
} else {
|
|
73
|
+
//in Node 18 this seems to be necessary to not trigger the abort event
|
|
74
|
+
this.complete = true;
|
|
75
|
+
this.push(body);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
})(writable as any);
|
|
79
|
+
}
|
|
80
|
+
|
|
25
81
|
export type HttpRequestQuery = { [name: string]: string };
|
|
26
82
|
export type HttpRequestResolvedParameters = { [name: string]: any };
|
|
27
83
|
|
|
@@ -107,37 +163,11 @@ export class RequestBuilder {
|
|
|
107
163
|
}
|
|
108
164
|
|
|
109
165
|
build(): HttpRequest {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const writable = new Writable({
|
|
116
|
-
write(chunk, encoding, callback) {
|
|
117
|
-
callback();
|
|
118
|
-
},
|
|
119
|
-
writev(chunks, callback) {
|
|
120
|
-
callback();
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
const request = new (class extends HttpRequest {
|
|
124
|
-
url = url;
|
|
125
|
-
method = method;
|
|
126
|
-
position = 0;
|
|
127
|
-
|
|
128
|
-
headers = headers;
|
|
129
|
-
|
|
130
|
-
_read(size: number) {
|
|
131
|
-
if (this.complete) {
|
|
132
|
-
this.push(null);
|
|
133
|
-
} else {
|
|
134
|
-
//in Node 18 this seems to be necessary to not trigger the abort event
|
|
135
|
-
this.complete = true;
|
|
136
|
-
this.push(bodyContent);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
})(writable as any);
|
|
140
|
-
return request;
|
|
166
|
+
return createRequestWithCachedBody({
|
|
167
|
+
method: this.method,
|
|
168
|
+
url: this.getUrl(),
|
|
169
|
+
headers: this._headers,
|
|
170
|
+
}, this.contentBuffer);
|
|
141
171
|
}
|
|
142
172
|
|
|
143
173
|
headers(headers: { [name: string]: string }): this {
|
|
@@ -182,10 +212,18 @@ export class HttpRequest extends IncomingMessage {
|
|
|
182
212
|
public uploadedFiles: { [name: string]: UploadedFile } = {};
|
|
183
213
|
|
|
184
214
|
/**
|
|
185
|
-
*
|
|
186
|
-
* Deepkit will re-use it.
|
|
215
|
+
* The router sets the body when it was read.
|
|
187
216
|
*/
|
|
188
|
-
public body?:
|
|
217
|
+
public body?: Buffer;
|
|
218
|
+
|
|
219
|
+
async readBody(): Promise<Buffer> {
|
|
220
|
+
if (this.body) return this.body;
|
|
221
|
+
return await readBody(this);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async readBodyText(): Promise<string> {
|
|
225
|
+
return (await this.readBody()).toString('utf8');
|
|
226
|
+
}
|
|
189
227
|
|
|
190
228
|
static GET(path: string): RequestBuilder {
|
|
191
229
|
return new RequestBuilder(path);
|
|
@@ -234,7 +272,7 @@ export class HttpRequest extends IncomingMessage {
|
|
|
234
272
|
|
|
235
273
|
export class MemoryHttpResponse extends HttpResponse {
|
|
236
274
|
public body: Buffer = Buffer.alloc(0);
|
|
237
|
-
public headers: {[name: string]: number | string | string[] | undefined} = Object.create(null);
|
|
275
|
+
public headers: { [name: string]: number | string | string[] | undefined } = Object.create(null);
|
|
238
276
|
|
|
239
277
|
setHeader(name: string, value: number | string | ReadonlyArray<string>): this {
|
|
240
278
|
this.headers[name] = value as any;
|
package/src/router.ts
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
// @ts-ignore
|
|
32
32
|
import formidable from 'formidable';
|
|
33
33
|
import { HttpAction, httpClass, HttpController, HttpDecorator } from './decorator';
|
|
34
|
-
import { BodyValidationError, getRegExp, HttpRequest, HttpRequestQuery, HttpRequestResolvedParameters, ValidatedBody } from './model';
|
|
34
|
+
import { BodyValidationError, createRequestWithCachedBody, getRegExp, HttpRequest, HttpRequestQuery, HttpRequestResolvedParameters, ValidatedBody } from './model';
|
|
35
35
|
import { InjectorContext, InjectorModule, TagRegistry } from '@deepkit/injector';
|
|
36
36
|
import { Logger, LoggerInterface } from '@deepkit/logger';
|
|
37
37
|
import { HttpControllers } from './controllers';
|
|
@@ -628,10 +628,7 @@ export class HttpRouter {
|
|
|
628
628
|
hash: 'sha1',
|
|
629
629
|
});
|
|
630
630
|
return asyncOperation((resolve, reject) => {
|
|
631
|
-
|
|
632
|
-
return resolve(req.body);
|
|
633
|
-
}
|
|
634
|
-
form.parse(req, (err: any, fields: any, files: any) => {
|
|
631
|
+
function parseData(err: any, fields: any, files: any) {
|
|
635
632
|
if (err) {
|
|
636
633
|
reject(err);
|
|
637
634
|
} else {
|
|
@@ -643,12 +640,32 @@ export class HttpRouter {
|
|
|
643
640
|
name: file.originalFilename,
|
|
644
641
|
type: file.mimetype,
|
|
645
642
|
lastModifiedDate: file.lastModifiedDate,
|
|
646
|
-
}
|
|
643
|
+
};
|
|
647
644
|
}
|
|
648
|
-
const body =
|
|
645
|
+
const body = { ...fields, ...foundFiles };
|
|
649
646
|
resolve(body);
|
|
650
647
|
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
if (req.body) {
|
|
651
|
+
form.parse(createRequestWithCachedBody(req, req.body), parseData);
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
const chunks: Buffer[] = [];
|
|
656
|
+
|
|
657
|
+
function read(chunk: Buffer) {
|
|
658
|
+
chunks.push(chunk);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
req.on('data', read);
|
|
662
|
+
req.once('end', () => {
|
|
663
|
+
req.body = Buffer.concat(chunks);
|
|
664
|
+
req.off('data', read);
|
|
651
665
|
});
|
|
666
|
+
req.once('error', () => req.off('data', read));
|
|
667
|
+
|
|
668
|
+
form.parse(req, parseData);
|
|
652
669
|
});
|
|
653
670
|
}
|
|
654
671
|
|
|
@@ -683,7 +700,7 @@ export class HttpRouter {
|
|
|
683
700
|
const routeConfigVar = compiler.reserveVariable('routeConfigVar', routeConfig);
|
|
684
701
|
const parsedRoute = parseRouteControllerAction(routeConfig);
|
|
685
702
|
const path = routeConfig.getFullPath();
|
|
686
|
-
const pathParamStarter = path.indexOf(':')
|
|
703
|
+
const pathParamStarter = path.indexOf(':');
|
|
687
704
|
const prefix = path.substr(0, pathParamStarter);
|
|
688
705
|
|
|
689
706
|
const regexVar = compiler.reserveVariable('regex', new RegExp('^' + parsedRoute.regex + '$'));
|