@dooboostore/simple-boot-http-server 1.0.14
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 +269 -0
- package/SimpleBootHttpServer.d.ts +16 -0
- package/SimpleBootHttpServer.js +313 -0
- package/codes/HttpHeaders.d.ts +42 -0
- package/codes/HttpHeaders.js +43 -0
- package/codes/HttpMethod.d.ts +12 -0
- package/codes/HttpMethod.js +13 -0
- package/codes/HttpStatus.d.ts +20 -0
- package/codes/HttpStatus.js +21 -0
- package/codes/Mimes.d.ts +28 -0
- package/codes/Mimes.js +29 -0
- package/decorators/MethodMapping.d.ts +74 -0
- package/decorators/MethodMapping.js +198 -0
- package/endpoints/CrossDomainHeaderEndPoint.d.ts +16 -0
- package/endpoints/CrossDomainHeaderEndPoint.js +37 -0
- package/endpoints/EndPoint.d.ts +7 -0
- package/endpoints/EndPoint.js +2 -0
- package/endpoints/HeaderEndPoint.d.ts +12 -0
- package/endpoints/HeaderEndPoint.js +26 -0
- package/errors/BadRequestError.d.ts +8 -0
- package/errors/BadRequestError.js +8 -0
- package/errors/ForbiddenError.d.ts +8 -0
- package/errors/ForbiddenError.js +8 -0
- package/errors/HttpError.d.ts +12 -0
- package/errors/HttpError.js +8 -0
- package/errors/InternalServerError.d.ts +8 -0
- package/errors/InternalServerError.js +8 -0
- package/errors/NotFoundError.d.ts +8 -0
- package/errors/NotFoundError.js +8 -0
- package/errors/UnauthorizedError.d.ts +8 -0
- package/errors/UnauthorizedError.js +8 -0
- package/filters/CacheFilter.d.ts +45 -0
- package/filters/CacheFilter.js +145 -0
- package/filters/Filter.d.ts +17 -0
- package/filters/Filter.js +2 -0
- package/filters/HttpStatusFilter.d.ts +20 -0
- package/filters/HttpStatusFilter.js +31 -0
- package/filters/OpenApi3Filter.d.ts +142 -0
- package/filters/OpenApi3Filter.js +57 -0
- package/filters/ResourceFilter.d.ts +24 -0
- package/filters/ResourceFilter.js +72 -0
- package/filters/ThrowFilter.d.ts +19 -0
- package/filters/ThrowFilter.js +34 -0
- package/inject/InjectSituationType.d.ts +4 -0
- package/inject/InjectSituationType.js +5 -0
- package/lifecycle/OnInit.d.ts +5 -0
- package/lifecycle/OnInit.js +2 -0
- package/models/RequestResponse.d.ts +107 -0
- package/models/RequestResponse.js +467 -0
- package/models/datas/HeaderData.d.ts +10 -0
- package/models/datas/HeaderData.js +7 -0
- package/models/datas/MultipartData.d.ts +14 -0
- package/models/datas/MultipartData.js +2 -0
- package/models/datas/ReqHeader.d.ts +69 -0
- package/models/datas/ReqHeader.js +3 -0
- package/models/datas/Resource.d.ts +11 -0
- package/models/datas/Resource.js +55 -0
- package/models/datas/body/ReqFormUrlBody.d.ts +4 -0
- package/models/datas/body/ReqFormUrlBody.js +3 -0
- package/models/datas/body/ReqJsonBody.d.ts +4 -0
- package/models/datas/body/ReqJsonBody.js +3 -0
- package/models/datas/body/ReqMultipartFormBody.d.ts +6 -0
- package/models/datas/body/ReqMultipartFormBody.js +6 -0
- package/models/method/patch/PatchJson.d.ts +8 -0
- package/models/method/patch/PatchJson.js +11 -0
- package/option/HttpServerOption.d.ts +85 -0
- package/option/HttpServerOption.js +35 -0
- package/package.json +83 -0
- package/resolvers/Resolver.d.ts +5 -0
- package/resolvers/Resolver.js +2 -0
- package/resolvers/ResourceResorver.d.ts +6 -0
- package/resolvers/ResourceResorver.js +18 -0
- package/session/SessionManager.d.ts +57 -0
- package/session/SessionManager.js +108 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
/// <reference types="node" />
|
|
4
|
+
/// <reference types="node" />
|
|
5
|
+
/// <reference types="node" />
|
|
6
|
+
import { IncomingMessage, OutgoingHttpHeader, OutgoingHttpHeaders, ServerResponse } from 'http';
|
|
7
|
+
import { HttpHeaders } from '../codes/HttpHeaders';
|
|
8
|
+
import { Mimes } from '../codes/Mimes';
|
|
9
|
+
import { Intent } from '@dooboostore/simple-boot/intent/Intent';
|
|
10
|
+
import { URL, URLSearchParams } from 'url';
|
|
11
|
+
import { Buffer } from 'buffer';
|
|
12
|
+
import { MultipartData } from './datas/MultipartData';
|
|
13
|
+
import { ReqFormUrlBody } from './datas/body/ReqFormUrlBody';
|
|
14
|
+
import { ReqJsonBody } from './datas/body/ReqJsonBody';
|
|
15
|
+
import { ReqHeader } from './datas/ReqHeader';
|
|
16
|
+
import { HttpStatus } from '../codes/HttpStatus';
|
|
17
|
+
import { SessionManager } from '../session/SessionManager';
|
|
18
|
+
import { HttpServerOption } from '../option/HttpServerOption';
|
|
19
|
+
type Config = {
|
|
20
|
+
sessionManager?: SessionManager;
|
|
21
|
+
option: HttpServerOption;
|
|
22
|
+
};
|
|
23
|
+
export declare class RequestResponse {
|
|
24
|
+
protected resWriteChunk: string | Buffer | undefined;
|
|
25
|
+
protected reqBodyChunk?: Buffer;
|
|
26
|
+
protected req: IncomingMessage;
|
|
27
|
+
protected res: ServerResponse;
|
|
28
|
+
protected config: Config;
|
|
29
|
+
constructor(req: IncomingMessage | RequestResponse, res: ServerResponse, config: Config);
|
|
30
|
+
get reqSocket(): import("net").Socket;
|
|
31
|
+
get reqCookieMap(): Map<string, string>;
|
|
32
|
+
reqCookieGet(key: string): string;
|
|
33
|
+
get reqRemoteAddress(): string | undefined;
|
|
34
|
+
get reqUrlObject(): URL;
|
|
35
|
+
get reqUrlPathName(): string;
|
|
36
|
+
get reqUrl(): string;
|
|
37
|
+
reqUrlObj(config?: {
|
|
38
|
+
scheme?: string;
|
|
39
|
+
host?: string;
|
|
40
|
+
}): URL;
|
|
41
|
+
get reqUrlSearchParamTuples(): [string, string][];
|
|
42
|
+
get reqUrlSearchParams(): URLSearchParams;
|
|
43
|
+
get reqUrlSearchParamsObj(): {
|
|
44
|
+
[p: string]: {
|
|
45
|
+
[p: string]: any;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
get reqPathSearchParamUrl(): string;
|
|
49
|
+
get reqReadable(): boolean;
|
|
50
|
+
get reqIntent(): Intent<any, any>;
|
|
51
|
+
reqHasContentTypeHeader(mime: Mimes | string): boolean;
|
|
52
|
+
reqHasAcceptHeader(mime: Mimes | string): boolean;
|
|
53
|
+
reqBodyData(): Promise<Buffer>;
|
|
54
|
+
resBodyData(): string | Buffer | undefined;
|
|
55
|
+
reqBodyMultipartFormDataObject<T>(): Promise<T>;
|
|
56
|
+
reqBodyMultipartFormData(): Promise<MultipartData[]>;
|
|
57
|
+
reqBodyStringData(): Promise<string>;
|
|
58
|
+
reqBodyJsonData<T>(): Promise<T>;
|
|
59
|
+
reqBodyFormUrlData<T>(): Promise<T>;
|
|
60
|
+
reqBodyReqFormUrlBody(): Promise<ReqFormUrlBody>;
|
|
61
|
+
reqBodyReqJsonBody(): Promise<ReqJsonBody>;
|
|
62
|
+
resBodyJsonData<T>(): (T | null);
|
|
63
|
+
resBodyStringData(): string;
|
|
64
|
+
reqMethod(): string;
|
|
65
|
+
reqHeader(key: HttpHeaders | string): string | string[];
|
|
66
|
+
get reqHost(): string;
|
|
67
|
+
get reqHeaderObj(): ReqHeader;
|
|
68
|
+
reqHeaderFirst(key: HttpHeaders | string, defaultValue?: string): string;
|
|
69
|
+
reqAuthorizationHeader(): string;
|
|
70
|
+
reqRefreshTokenHeader(): string;
|
|
71
|
+
resStatusCode(code?: undefined): number;
|
|
72
|
+
resStatusCode(code: number | HttpStatus): RequestResponseChain<number>;
|
|
73
|
+
resHeader(key: HttpHeaders | string): string | number | string[];
|
|
74
|
+
resHeaderFirst(key: HttpHeaders | string, defaultValue?: string): string | number | string[];
|
|
75
|
+
reqSession(): Promise<{
|
|
76
|
+
[key: string]: any;
|
|
77
|
+
}>;
|
|
78
|
+
reqSessionSet(key: string, value: any): void;
|
|
79
|
+
reqSessionGet<T = any>(key: string): T | undefined;
|
|
80
|
+
resSetStatusCode(statusCode: number): RequestResponseChain<number>;
|
|
81
|
+
resWrite(chunk: string | Buffer | any, encoding?: BufferEncoding): RequestResponseChain<string | Buffer>;
|
|
82
|
+
resWriteJson(chunk: any, encoding?: BufferEncoding): RequestResponseChain<string | Buffer>;
|
|
83
|
+
resSetHeader(key: HttpHeaders | string, value: string | string[]): RequestResponseChain<ServerResponse<IncomingMessage>>;
|
|
84
|
+
resAddHeader(key: HttpHeaders | string, value: string | string[]): RequestResponseChain<ServerResponse<IncomingMessage>>;
|
|
85
|
+
resSetHeaders(headers: {
|
|
86
|
+
[key: string]: string | string[];
|
|
87
|
+
}): RequestResponseChain<any>;
|
|
88
|
+
resAddHeaders(headers: {
|
|
89
|
+
[key: string]: string | string[];
|
|
90
|
+
}): RequestResponseChain<any>;
|
|
91
|
+
private resEndChunk;
|
|
92
|
+
resEnd(chunk?: string | Buffer): Promise<void>;
|
|
93
|
+
resWriteHead(statusCode: number, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[] | {
|
|
94
|
+
[key: string]: string | string[];
|
|
95
|
+
}): RequestResponseChain<ServerResponse<IncomingMessage>>;
|
|
96
|
+
resWriteHeadEnd(statusCode: number, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[] | {
|
|
97
|
+
[key: string]: string | string[];
|
|
98
|
+
}): void;
|
|
99
|
+
resIsDone(): boolean;
|
|
100
|
+
createRequestResponseChain<T = any>(data?: T): RequestResponseChain<T>;
|
|
101
|
+
}
|
|
102
|
+
export declare class RequestResponseChain<T> extends RequestResponse {
|
|
103
|
+
result?: T;
|
|
104
|
+
constructor(req: IncomingMessage, res: ServerResponse, config: Config, result?: T);
|
|
105
|
+
}
|
|
106
|
+
export {};
|
|
107
|
+
//# sourceMappingURL=RequestResponse.d.ts.map
|
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { HttpHeaders } from '../codes/HttpHeaders';
|
|
11
|
+
import { Intent } from '@dooboostore/simple-boot/intent/Intent';
|
|
12
|
+
import { URL, URLSearchParams } from 'url';
|
|
13
|
+
import { Buffer } from 'buffer';
|
|
14
|
+
import { ReqFormUrlBody } from './datas/body/ReqFormUrlBody';
|
|
15
|
+
import { ReqJsonBody } from './datas/body/ReqJsonBody';
|
|
16
|
+
import { ReqHeader } from './datas/ReqHeader';
|
|
17
|
+
import { gzip } from 'node-gzip';
|
|
18
|
+
import { FileUtils } from '@dooboostore/core-node/file/FileUtils';
|
|
19
|
+
import { ConvertUtils } from '@dooboostore/core-node/convert/ConvertUtils';
|
|
20
|
+
export class RequestResponse {
|
|
21
|
+
constructor(req, res, config) {
|
|
22
|
+
if (req instanceof RequestResponse) {
|
|
23
|
+
this.req = req.req;
|
|
24
|
+
this.res = req.res;
|
|
25
|
+
this.config = config;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
this.req = req;
|
|
29
|
+
this.res = res;
|
|
30
|
+
this.config = config;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
get reqSocket() {
|
|
34
|
+
return this.req.socket;
|
|
35
|
+
}
|
|
36
|
+
get reqCookieMap() {
|
|
37
|
+
var _a;
|
|
38
|
+
let cookies = (_a = this.reqHeader(HttpHeaders.Cookie)) !== null && _a !== void 0 ? _a : '';
|
|
39
|
+
if (Array.isArray(cookies)) {
|
|
40
|
+
cookies = cookies.join(';');
|
|
41
|
+
}
|
|
42
|
+
const map = new Map();
|
|
43
|
+
cookies.split(';').map(it => it.trim().split('=')).forEach(it => {
|
|
44
|
+
map.set(it[0], it[1]);
|
|
45
|
+
});
|
|
46
|
+
return map;
|
|
47
|
+
}
|
|
48
|
+
reqCookieGet(key) {
|
|
49
|
+
return this.reqCookieMap.get(key);
|
|
50
|
+
}
|
|
51
|
+
get reqRemoteAddress() {
|
|
52
|
+
const ipHeader = this.req.headers['x-forwarded-for'];
|
|
53
|
+
let ip = this.req.socket.remoteAddress;
|
|
54
|
+
if (Array.isArray(ipHeader)) {
|
|
55
|
+
ip = ipHeader.join(',').split(',').shift();
|
|
56
|
+
}
|
|
57
|
+
else if (typeof ipHeader === 'string') {
|
|
58
|
+
ip = ipHeader.split(',').shift();
|
|
59
|
+
}
|
|
60
|
+
return ip;
|
|
61
|
+
}
|
|
62
|
+
get reqUrlObject() {
|
|
63
|
+
var _a;
|
|
64
|
+
return new URL(this.reqUrl, `${this.reqSocket ? 'https://' : 'http'}${(_a = this.reqHost) !== null && _a !== void 0 ? _a : 'localhost'}`);
|
|
65
|
+
}
|
|
66
|
+
get reqUrlPathName() {
|
|
67
|
+
var _a;
|
|
68
|
+
return (_a = this.reqUrlObj().pathname) !== null && _a !== void 0 ? _a : '';
|
|
69
|
+
}
|
|
70
|
+
get reqUrl() {
|
|
71
|
+
var _a;
|
|
72
|
+
return (_a = this.req.url) !== null && _a !== void 0 ? _a : '';
|
|
73
|
+
}
|
|
74
|
+
reqUrlObj(config) {
|
|
75
|
+
var _a, _b, _c;
|
|
76
|
+
return new URL(`${(_a = config === null || config === void 0 ? void 0 : config.scheme) !== null && _a !== void 0 ? _a : 'http'}://${(config === null || config === void 0 ? void 0 : config.host) ? config === null || config === void 0 ? void 0 : config.host : ((_b = this.reqHeaderFirst(HttpHeaders.Host)) !== null && _b !== void 0 ? _b : 'localhost')}${(_c = this.req.url) !== null && _c !== void 0 ? _c : ''}`);
|
|
77
|
+
}
|
|
78
|
+
get reqUrlSearchParamTuples() {
|
|
79
|
+
return Array.from(this.reqUrlObj().searchParams);
|
|
80
|
+
}
|
|
81
|
+
get reqUrlSearchParams() {
|
|
82
|
+
return this.reqUrlObj().searchParams;
|
|
83
|
+
}
|
|
84
|
+
get reqUrlSearchParamsObj() {
|
|
85
|
+
const entries = this.reqUrlObj().searchParams;
|
|
86
|
+
return Object.fromEntries(entries);
|
|
87
|
+
}
|
|
88
|
+
get reqPathSearchParamUrl() {
|
|
89
|
+
const reqUrlObj = this.reqUrlObj();
|
|
90
|
+
return reqUrlObj.pathname + (reqUrlObj.searchParams.toString() ? '?' + reqUrlObj.searchParams.toString() : '');
|
|
91
|
+
}
|
|
92
|
+
get reqReadable() {
|
|
93
|
+
return this.req.readable;
|
|
94
|
+
}
|
|
95
|
+
get reqIntent() {
|
|
96
|
+
return new Intent(this.reqPathSearchParamUrl);
|
|
97
|
+
}
|
|
98
|
+
reqHasContentTypeHeader(mime) {
|
|
99
|
+
var _a;
|
|
100
|
+
return ((_a = this.reqHeaderFirst(HttpHeaders.ContentType)) !== null && _a !== void 0 ? _a : '').toLowerCase().indexOf(mime.toLocaleLowerCase()) > -1;
|
|
101
|
+
}
|
|
102
|
+
reqHasAcceptHeader(mime) {
|
|
103
|
+
var _a;
|
|
104
|
+
return ((_a = this.reqHeaderFirst(HttpHeaders.Accept)) !== null && _a !== void 0 ? _a : '').toLowerCase().indexOf(mime.toLocaleLowerCase()) > -1;
|
|
105
|
+
}
|
|
106
|
+
reqBodyData() {
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
var _a;
|
|
109
|
+
if (this.reqReadable) {
|
|
110
|
+
const data = [];
|
|
111
|
+
this.req.on('data', (chunk) => data.push(chunk));
|
|
112
|
+
this.req.on('error', err => reject(err));
|
|
113
|
+
this.req.on('end', () => {
|
|
114
|
+
this.reqBodyChunk = Buffer.concat(data);
|
|
115
|
+
resolve(this.reqBodyChunk);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
resolve((_a = this.reqBodyChunk) !== null && _a !== void 0 ? _a : Buffer.alloc(0));
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
resBodyData() {
|
|
124
|
+
return this.resWriteChunk;
|
|
125
|
+
}
|
|
126
|
+
reqBodyMultipartFormDataObject() {
|
|
127
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
+
const m = yield this.reqBodyMultipartFormData();
|
|
129
|
+
const formData = {};
|
|
130
|
+
for (const it of m) {
|
|
131
|
+
if (it.isFile) {
|
|
132
|
+
formData[it.name] = yield FileUtils.writeFile(it.value, { originalName: it.filename });
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const target = formData[it.name];
|
|
136
|
+
if (Array.isArray(target)) {
|
|
137
|
+
target.push(it.value);
|
|
138
|
+
}
|
|
139
|
+
else if (typeof target === 'string') {
|
|
140
|
+
formData[it.name] = [target, it.value];
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
formData[it.name] = it.value;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
;
|
|
148
|
+
return formData;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
reqBodyMultipartFormData() {
|
|
152
|
+
return new Promise((resolve, reject) => {
|
|
153
|
+
const contentTypeHeader = this.req.headers['content-type'];
|
|
154
|
+
if (!contentTypeHeader || !contentTypeHeader.startsWith('multipart/form-data')) {
|
|
155
|
+
return reject(new Error('Invalid Content-Type. Expected multipart/form-data.'));
|
|
156
|
+
}
|
|
157
|
+
const boundaryMatch = contentTypeHeader.match(/boundary=(?:"([^"]+)"|([^;]+))/i);
|
|
158
|
+
if (!boundaryMatch) {
|
|
159
|
+
return reject(new Error('Boundary not found in Content-Type header.'));
|
|
160
|
+
}
|
|
161
|
+
const boundary = boundaryMatch[1] || boundaryMatch[2];
|
|
162
|
+
if (!boundary) {
|
|
163
|
+
return reject(new Error('Failed to extract boundary.'));
|
|
164
|
+
}
|
|
165
|
+
const boundaryBuffer = Buffer.from(`--${boundary}`);
|
|
166
|
+
const crlfBuffer = Buffer.from('\r\n');
|
|
167
|
+
const doubleCrlfBuffer = Buffer.from('\r\n\r\n');
|
|
168
|
+
const chunks = [];
|
|
169
|
+
let totalLength = 0;
|
|
170
|
+
this.req.on('data', (chunk) => {
|
|
171
|
+
chunks.push(chunk);
|
|
172
|
+
totalLength += chunk.length;
|
|
173
|
+
});
|
|
174
|
+
this.req.on('error', (err) => {
|
|
175
|
+
reject(err);
|
|
176
|
+
});
|
|
177
|
+
this.req.on('end', () => {
|
|
178
|
+
if (totalLength === 0) {
|
|
179
|
+
return resolve([]);
|
|
180
|
+
}
|
|
181
|
+
const fullBuffer = Buffer.concat(chunks, totalLength);
|
|
182
|
+
const parsedParts = [];
|
|
183
|
+
let currentPosition = 0;
|
|
184
|
+
let boundaryStartIndex = fullBuffer.indexOf(boundaryBuffer, currentPosition);
|
|
185
|
+
if (boundaryStartIndex === -1) {
|
|
186
|
+
return reject(new Error('Initial boundary not found.'));
|
|
187
|
+
}
|
|
188
|
+
currentPosition = boundaryStartIndex + boundaryBuffer.length;
|
|
189
|
+
if (fullBuffer.slice(currentPosition, currentPosition + crlfBuffer.length).equals(crlfBuffer)) {
|
|
190
|
+
currentPosition += crlfBuffer.length;
|
|
191
|
+
}
|
|
192
|
+
while (currentPosition < fullBuffer.length) {
|
|
193
|
+
const nextBoundaryIndex = fullBuffer.indexOf(boundaryBuffer, currentPosition);
|
|
194
|
+
if (nextBoundaryIndex === -1) {
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
let partEndIndex = nextBoundaryIndex;
|
|
198
|
+
if (partEndIndex > crlfBuffer.length && fullBuffer.slice(partEndIndex - crlfBuffer.length, partEndIndex).equals(crlfBuffer)) {
|
|
199
|
+
partEndIndex -= crlfBuffer.length;
|
|
200
|
+
}
|
|
201
|
+
const partBuffer = fullBuffer.slice(currentPosition, partEndIndex);
|
|
202
|
+
const headerBodySeparatorIndex = partBuffer.indexOf(doubleCrlfBuffer);
|
|
203
|
+
if (headerBodySeparatorIndex === -1) {
|
|
204
|
+
console.warn('Skipping malformed part: no header/body separator found.');
|
|
205
|
+
currentPosition = nextBoundaryIndex + boundaryBuffer.length;
|
|
206
|
+
if (fullBuffer.slice(currentPosition, currentPosition + crlfBuffer.length).equals(crlfBuffer)) {
|
|
207
|
+
currentPosition += crlfBuffer.length;
|
|
208
|
+
}
|
|
209
|
+
if (fullBuffer.slice(currentPosition, currentPosition + 2).toString() === '--')
|
|
210
|
+
break;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const headerBuffer = partBuffer.slice(0, headerBodySeparatorIndex);
|
|
214
|
+
const bodyBuffer = partBuffer.slice(headerBodySeparatorIndex + doubleCrlfBuffer.length);
|
|
215
|
+
const headersStr = headerBuffer.toString('utf-8');
|
|
216
|
+
const headers = {};
|
|
217
|
+
headersStr.split('\r\n').forEach(line => {
|
|
218
|
+
const colonIndex = line.indexOf(':');
|
|
219
|
+
if (colonIndex > 0) {
|
|
220
|
+
const key = line.substring(0, colonIndex).trim().toLowerCase();
|
|
221
|
+
const value = line.substring(colonIndex + 1).trim();
|
|
222
|
+
headers[key] = value;
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
const contentDisposition = headers['content-disposition'];
|
|
226
|
+
if (!contentDisposition) {
|
|
227
|
+
console.warn('Skipping part: no Content-Disposition header.');
|
|
228
|
+
currentPosition = nextBoundaryIndex + boundaryBuffer.length;
|
|
229
|
+
if (fullBuffer.slice(currentPosition, currentPosition + crlfBuffer.length).equals(crlfBuffer)) {
|
|
230
|
+
currentPosition += crlfBuffer.length;
|
|
231
|
+
}
|
|
232
|
+
if (fullBuffer.slice(currentPosition, currentPosition + 2).toString() === '--')
|
|
233
|
+
break;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const nameMatch = contentDisposition.match(/name="([^"]+)"/i);
|
|
237
|
+
const filenameMatch = contentDisposition.match(/filename="([^"]+)"/i);
|
|
238
|
+
const name = nameMatch ? nameMatch[1] : null;
|
|
239
|
+
const filename = filenameMatch ? filenameMatch[1] : null;
|
|
240
|
+
const contentType = headers['content-type'] || null;
|
|
241
|
+
if (name) {
|
|
242
|
+
const isFile = !!filename;
|
|
243
|
+
const multipartData = {
|
|
244
|
+
name: name,
|
|
245
|
+
isFile: isFile,
|
|
246
|
+
filename: filename,
|
|
247
|
+
contentType: contentType,
|
|
248
|
+
value: isFile ? bodyBuffer : bodyBuffer.toString('utf-8'),
|
|
249
|
+
};
|
|
250
|
+
parsedParts.push(multipartData);
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
console.warn("Skipping part: 'name' not found in Content-Disposition.");
|
|
254
|
+
}
|
|
255
|
+
currentPosition = nextBoundaryIndex + boundaryBuffer.length;
|
|
256
|
+
if (fullBuffer.slice(currentPosition, currentPosition + crlfBuffer.length).equals(crlfBuffer)) {
|
|
257
|
+
currentPosition += crlfBuffer.length;
|
|
258
|
+
}
|
|
259
|
+
if (fullBuffer.slice(currentPosition, currentPosition + 2).toString() === '--') {
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
resolve(parsedParts);
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
reqBodyStringData() {
|
|
268
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
269
|
+
const data = (yield this.reqBodyData()).toString();
|
|
270
|
+
return data;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
reqBodyJsonData() {
|
|
274
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
275
|
+
return JSON.parse(yield this.reqBodyStringData());
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
reqBodyFormUrlData() {
|
|
279
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
280
|
+
const data = (yield this.reqBodyStringData());
|
|
281
|
+
const formData = {};
|
|
282
|
+
Array.from(new URLSearchParams(data).entries()).forEach(([k, v]) => {
|
|
283
|
+
const target = formData[k];
|
|
284
|
+
if (Array.isArray(target)) {
|
|
285
|
+
target.push(v);
|
|
286
|
+
}
|
|
287
|
+
else if (typeof target === 'string') {
|
|
288
|
+
formData[k] = [target, v];
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
formData[k] = v;
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
return formData;
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
reqBodyReqFormUrlBody() {
|
|
298
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
299
|
+
const data = yield this.reqBodyFormUrlData();
|
|
300
|
+
return Object.assign(new ReqFormUrlBody(), data);
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
reqBodyReqJsonBody() {
|
|
304
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
305
|
+
const data = (yield this.reqBodyStringData());
|
|
306
|
+
return Object.assign(new ReqJsonBody(), data ? JSON.parse(data) : {});
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
resBodyJsonData() {
|
|
310
|
+
const data = ConvertUtils.toString(this.resBodyData());
|
|
311
|
+
return data ? JSON.parse(data) : null;
|
|
312
|
+
}
|
|
313
|
+
resBodyStringData() {
|
|
314
|
+
return ConvertUtils.toString(this.resBodyData());
|
|
315
|
+
}
|
|
316
|
+
reqMethod() {
|
|
317
|
+
var _a;
|
|
318
|
+
return (_a = this.req.method) === null || _a === void 0 ? void 0 : _a.toUpperCase();
|
|
319
|
+
}
|
|
320
|
+
reqHeader(key) {
|
|
321
|
+
return this.req.headers[key.toLowerCase()];
|
|
322
|
+
}
|
|
323
|
+
get reqHost() {
|
|
324
|
+
return this.reqHeaderFirst(HttpHeaders.Host);
|
|
325
|
+
}
|
|
326
|
+
get reqHeaderObj() {
|
|
327
|
+
const h = new ReqHeader();
|
|
328
|
+
Object.entries(this.req.headers).forEach(([k, v]) => {
|
|
329
|
+
h[k] = v;
|
|
330
|
+
});
|
|
331
|
+
return h;
|
|
332
|
+
}
|
|
333
|
+
reqHeaderFirst(key, defaultValue) {
|
|
334
|
+
var _a, _b;
|
|
335
|
+
const header = this.req.headers[key.toLowerCase()];
|
|
336
|
+
if (header && Array.isArray(header)) {
|
|
337
|
+
return (_a = header[0]) !== null && _a !== void 0 ? _a : defaultValue;
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
return (_b = header) !== null && _b !== void 0 ? _b : defaultValue;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
reqAuthorizationHeader() {
|
|
344
|
+
return this.reqHeaderFirst(HttpHeaders.Authorization);
|
|
345
|
+
}
|
|
346
|
+
reqRefreshTokenHeader() {
|
|
347
|
+
return this.reqHeaderFirst(HttpHeaders.Authorization);
|
|
348
|
+
}
|
|
349
|
+
resStatusCode(code) {
|
|
350
|
+
if (code) {
|
|
351
|
+
this.res.statusCode = code;
|
|
352
|
+
return new RequestResponseChain(this.req, this.res, this.config, this.res.statusCode);
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
return this.res.statusCode;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
resHeader(key) {
|
|
359
|
+
return this.res.getHeader(key.toLowerCase());
|
|
360
|
+
}
|
|
361
|
+
resHeaderFirst(key, defaultValue) {
|
|
362
|
+
var _a;
|
|
363
|
+
const header = this.res.getHeader(key.toLowerCase());
|
|
364
|
+
if (header && Array.isArray(header)) {
|
|
365
|
+
return (_a = header[0]) !== null && _a !== void 0 ? _a : defaultValue;
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
return header !== null && header !== void 0 ? header : defaultValue;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
reqSession() {
|
|
372
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
373
|
+
if (this.config.sessionManager) {
|
|
374
|
+
return (yield this.config.sessionManager.session(this)).dataSet.data;
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
return Promise.reject(new Error('Not SessionManager'));
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
reqSessionSet(key, value) {
|
|
382
|
+
this.reqSession[key] = value;
|
|
383
|
+
}
|
|
384
|
+
reqSessionGet(key) {
|
|
385
|
+
const session = this.reqSession;
|
|
386
|
+
if (session) {
|
|
387
|
+
return session[key];
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
resSetStatusCode(statusCode) {
|
|
391
|
+
this.res.statusCode = statusCode;
|
|
392
|
+
return this.createRequestResponseChain(this.res.statusCode);
|
|
393
|
+
}
|
|
394
|
+
resWrite(chunk, encoding = 'utf8') {
|
|
395
|
+
this.resWriteChunk = chunk;
|
|
396
|
+
return this.createRequestResponseChain(this.resWriteChunk);
|
|
397
|
+
}
|
|
398
|
+
resWriteJson(chunk, encoding = 'utf8') {
|
|
399
|
+
return this.resWrite(JSON.stringify(chunk), encoding);
|
|
400
|
+
}
|
|
401
|
+
resSetHeader(key, value) {
|
|
402
|
+
return this.createRequestResponseChain(this.res.setHeader(key.toLowerCase(), value));
|
|
403
|
+
}
|
|
404
|
+
resAddHeader(key, value) {
|
|
405
|
+
const existingValue = this.res.getHeader(key.toLowerCase());
|
|
406
|
+
const newValue = Array.isArray(existingValue)
|
|
407
|
+
? existingValue.concat(value)
|
|
408
|
+
: existingValue
|
|
409
|
+
? [existingValue.toString(), ...[].concat(value)]
|
|
410
|
+
: value;
|
|
411
|
+
return this.createRequestResponseChain(this.res.setHeader(key.toLowerCase(), newValue));
|
|
412
|
+
}
|
|
413
|
+
resSetHeaders(headers) {
|
|
414
|
+
Object.entries(headers).forEach(([key, value]) => this.resSetHeader(key, value));
|
|
415
|
+
return this.createRequestResponseChain();
|
|
416
|
+
}
|
|
417
|
+
resAddHeaders(headers) {
|
|
418
|
+
Object.entries(headers).forEach(([key, value]) => this.resAddHeader(key, value));
|
|
419
|
+
return this.createRequestResponseChain();
|
|
420
|
+
}
|
|
421
|
+
resEndChunk() {
|
|
422
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
423
|
+
const encoding = this.reqHeaderFirst(HttpHeaders.AcceptEncoding);
|
|
424
|
+
let data = this.resWriteChunk;
|
|
425
|
+
if (encoding === null || encoding === void 0 ? void 0 : encoding.includes('gzip')) {
|
|
426
|
+
data = yield gzip(data);
|
|
427
|
+
this.resSetHeader(HttpHeaders.ContentEncoding, 'gzip');
|
|
428
|
+
}
|
|
429
|
+
this.res.end(data);
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
resEnd(chunk) {
|
|
433
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
434
|
+
this.resWriteChunk = chunk !== null && chunk !== void 0 ? chunk : this.resWriteChunk;
|
|
435
|
+
if (this.req.readable) {
|
|
436
|
+
yield this.reqBodyData();
|
|
437
|
+
yield this.resEndChunk();
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
yield this.resEndChunk();
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
resWriteHead(statusCode, headers) {
|
|
445
|
+
return this.createRequestResponseChain(this.res.writeHead(statusCode, headers));
|
|
446
|
+
}
|
|
447
|
+
resWriteHeadEnd(statusCode, headers) {
|
|
448
|
+
this.createRequestResponseChain(this.res.writeHead(statusCode, headers));
|
|
449
|
+
this.res.end();
|
|
450
|
+
}
|
|
451
|
+
resIsDone() {
|
|
452
|
+
return this.res.finished || this.res.writableEnded || this.res.headersSent;
|
|
453
|
+
}
|
|
454
|
+
createRequestResponseChain(data) {
|
|
455
|
+
const requestResponseChain = new RequestResponseChain(this.req, this.res, this.config, data);
|
|
456
|
+
requestResponseChain.resWriteChunk = this.resWriteChunk;
|
|
457
|
+
requestResponseChain.reqBodyChunk = this.reqBodyChunk;
|
|
458
|
+
return requestResponseChain;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
export class RequestResponseChain extends RequestResponse {
|
|
462
|
+
constructor(req, res, config, result) {
|
|
463
|
+
super(req, res, config);
|
|
464
|
+
this.result = result;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
//# sourceMappingURL=RequestResponse.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
export type MultipartData = {
|
|
4
|
+
isFile: true;
|
|
5
|
+
name: string;
|
|
6
|
+
filename: string;
|
|
7
|
+
contentType: string;
|
|
8
|
+
value: Buffer;
|
|
9
|
+
} | {
|
|
10
|
+
isFile: false;
|
|
11
|
+
name: string;
|
|
12
|
+
value: string;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=MultipartData.d.ts.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { IncomingHttpHeaders } from 'http';
|
|
3
|
+
export declare class ReqHeader implements IncomingHttpHeaders {
|
|
4
|
+
[key: string]: string | string[] | undefined;
|
|
5
|
+
'accept-language': string | undefined;
|
|
6
|
+
'accept-patch': string | undefined;
|
|
7
|
+
'accept-ranges': string | undefined;
|
|
8
|
+
'access-control-allow-credentials': string | undefined;
|
|
9
|
+
'access-control-allow-headers': string | undefined;
|
|
10
|
+
'access-control-allow-methods': string | undefined;
|
|
11
|
+
'access-control-allow-origin': string | undefined;
|
|
12
|
+
'access-control-expose-headers': string | undefined;
|
|
13
|
+
'access-control-max-age': string | undefined;
|
|
14
|
+
'access-control-request-headers': string | undefined;
|
|
15
|
+
'access-control-request-method': string | undefined;
|
|
16
|
+
'alt-svc': string | undefined;
|
|
17
|
+
'cache-control': string | undefined;
|
|
18
|
+
'content-disposition': string | undefined;
|
|
19
|
+
'content-encoding': string | undefined;
|
|
20
|
+
'content-language': string | undefined;
|
|
21
|
+
'content-length': string | undefined;
|
|
22
|
+
'content-location': string | undefined;
|
|
23
|
+
'content-range': string | undefined;
|
|
24
|
+
'content-type': string | undefined;
|
|
25
|
+
'if-match': string | undefined;
|
|
26
|
+
'if-modified-since': string | undefined;
|
|
27
|
+
'if-none-match': string | undefined;
|
|
28
|
+
'if-unmodified-since': string | undefined;
|
|
29
|
+
'last-modified': string | undefined;
|
|
30
|
+
'proxy-authenticate': string | undefined;
|
|
31
|
+
'proxy-authorization': string | undefined;
|
|
32
|
+
'public-key-pins': string | undefined;
|
|
33
|
+
'retry-after': string | undefined;
|
|
34
|
+
'sec-websocket-accept': string | undefined;
|
|
35
|
+
'sec-websocket-extensions': string | undefined;
|
|
36
|
+
'sec-websocket-key': string | undefined;
|
|
37
|
+
'sec-websocket-protocol': string | undefined;
|
|
38
|
+
'sec-websocket-version': string | undefined;
|
|
39
|
+
'set-cookie': string[] | undefined;
|
|
40
|
+
'strict-transport-security': string | undefined;
|
|
41
|
+
'transfer-encoding': string | undefined;
|
|
42
|
+
'user-agent': string | undefined;
|
|
43
|
+
'www-authenticate': string | undefined;
|
|
44
|
+
accept: string | undefined;
|
|
45
|
+
age: string | undefined;
|
|
46
|
+
allow: string | undefined;
|
|
47
|
+
authorization: string | undefined;
|
|
48
|
+
connection: string | undefined;
|
|
49
|
+
cookie: string | undefined;
|
|
50
|
+
date: string | undefined;
|
|
51
|
+
etag: string | undefined;
|
|
52
|
+
expect: string | undefined;
|
|
53
|
+
expires: string | undefined;
|
|
54
|
+
forwarded: string | undefined;
|
|
55
|
+
from: string | undefined;
|
|
56
|
+
host: string | undefined;
|
|
57
|
+
location: string | undefined;
|
|
58
|
+
origin: string | undefined;
|
|
59
|
+
pragma: string | undefined;
|
|
60
|
+
range: string | undefined;
|
|
61
|
+
referer: string | undefined;
|
|
62
|
+
tk: string | undefined;
|
|
63
|
+
trailer: string | undefined;
|
|
64
|
+
upgrade: string | undefined;
|
|
65
|
+
vary: string | undefined;
|
|
66
|
+
via: string | undefined;
|
|
67
|
+
warning: string | undefined;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=ReqHeader.d.ts.map
|