@dooboostore/simple-boot-http-server 1.0.23 → 1.0.25
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 +113 -0
- package/dist/cjs/SimpleBootHttpServer.js +80 -40
- package/dist/cjs/SimpleBootHttpServer.js.map +3 -3
- package/dist/cjs/codes/HttpHeaders.js +14 -3
- package/dist/cjs/codes/HttpHeaders.js.map +2 -2
- package/dist/cjs/codes/Mimes.js +2 -0
- package/dist/cjs/codes/Mimes.js.map +2 -2
- package/dist/cjs/decorators/MethodMapping.js +40 -9
- package/dist/cjs/decorators/MethodMapping.js.map +3 -3
- package/dist/cjs/endpoints/WebSocketEndPoint.js +16 -0
- package/dist/cjs/endpoints/WebSocketEndPoint.js.map +7 -0
- package/dist/cjs/errors/BadRequestError.js +2 -1
- package/dist/cjs/errors/BadRequestError.js.map +2 -2
- package/dist/cjs/errors/ForbiddenError.js +2 -1
- package/dist/cjs/errors/ForbiddenError.js.map +2 -2
- package/dist/cjs/errors/InternalServerError.js +2 -1
- package/dist/cjs/errors/InternalServerError.js.map +2 -2
- package/dist/cjs/errors/NotFoundError.js +2 -1
- package/dist/cjs/errors/NotFoundError.js.map +2 -2
- package/dist/cjs/errors/UnauthorizedError.js +2 -1
- package/dist/cjs/errors/UnauthorizedError.js.map +2 -2
- package/dist/cjs/filters/CacheFilter.js +75 -35
- package/dist/cjs/filters/CacheFilter.js.map +3 -3
- package/dist/cjs/filters/IntentSchemeFilter.js +97 -0
- package/dist/cjs/filters/IntentSchemeFilter.js.map +7 -0
- package/dist/cjs/filters/ResourceFilter.js +6 -2
- package/dist/cjs/filters/ResourceFilter.js.map +2 -2
- package/dist/cjs/filters/TopicProtocolFilter.js +343 -0
- package/dist/cjs/filters/TopicProtocolFilter.js.map +7 -0
- package/dist/cjs/filters/index.js +5 -1
- package/dist/cjs/filters/index.js.map +2 -2
- package/dist/cjs/index.js +30 -0
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/inject/InjectSituationType.js +1 -1
- package/dist/cjs/inject/InjectSituationType.js.map +2 -2
- package/dist/cjs/models/RequestResponse.js +70 -91
- package/dist/cjs/models/RequestResponse.js.map +3 -3
- package/dist/cjs/models/datas/body/index.js +28 -0
- package/dist/cjs/models/datas/body/index.js.map +7 -0
- package/dist/cjs/models/datas/index.js +32 -0
- package/dist/cjs/models/datas/index.js.map +7 -0
- package/dist/cjs/models/datas/path/ReqPathData.js +29 -0
- package/dist/cjs/models/datas/path/ReqPathData.js.map +7 -0
- package/dist/cjs/models/datas/{search → path}/ReqSearchParamsObj.js.map +1 -1
- package/dist/cjs/models/datas/path/index.js +24 -0
- package/dist/cjs/models/datas/path/index.js.map +7 -0
- package/dist/cjs/models/index.js +4 -16
- package/dist/cjs/models/index.js.map +2 -2
- package/dist/cjs/models/method/index.js +22 -0
- package/dist/cjs/models/method/index.js.map +7 -0
- package/dist/cjs/models/method/patch/index.js +22 -0
- package/dist/cjs/models/method/patch/index.js.map +7 -0
- package/dist/cjs/option/HttpServerOption.js +25 -5
- package/dist/cjs/option/HttpServerOption.js.map +2 -2
- package/dist/cjs/proxy/SymbolIntentApiServiceProxy.js +144 -0
- package/dist/cjs/proxy/SymbolIntentApiServiceProxy.js.map +7 -0
- package/dist/cjs/proxy/SymbolIntentApiServiceProxyBase.js +35 -0
- package/dist/cjs/proxy/SymbolIntentApiServiceProxyBase.js.map +7 -0
- package/dist/cjs/proxy/TopicProtocolApiServiceProxy.js +324 -0
- package/dist/cjs/proxy/TopicProtocolApiServiceProxy.js.map +7 -0
- package/dist/cjs/proxy/index.js +26 -0
- package/dist/cjs/proxy/index.js.map +7 -0
- package/dist/cjs/resolvers/ResourceResolver.js +2 -2
- package/dist/cjs/resolvers/ResourceResolver.js.map +2 -2
- package/dist/cjs/session/SessionManager.js +2 -2
- package/dist/cjs/session/SessionManager.js.map +2 -2
- package/dist/cjs/websocket/WebSocketClient.js +554 -0
- package/dist/cjs/websocket/WebSocketClient.js.map +7 -0
- package/dist/cjs/websocket/WebSocketManager.js +652 -0
- package/dist/cjs/websocket/WebSocketManager.js.map +7 -0
- package/dist/cjs/websocket/index.js +24 -0
- package/dist/cjs/websocket/index.js.map +7 -0
- package/dist/esm/SimpleBootHttpServer.js +60 -20
- package/dist/esm/SimpleBootHttpServer.js.map +2 -2
- package/dist/esm/codes/HttpHeaders.js +12 -2
- package/dist/esm/codes/HttpHeaders.js.map +2 -2
- package/dist/esm/codes/Mimes.js +2 -0
- package/dist/esm/codes/Mimes.js.map +2 -2
- package/dist/esm/decorators/MethodMapping.js +24 -3
- package/dist/esm/decorators/MethodMapping.js.map +2 -2
- package/dist/esm/endpoints/WebSocketEndPoint.js +1 -0
- package/dist/esm/endpoints/WebSocketEndPoint.js.map +7 -0
- package/dist/esm/errors/BadRequestError.js +2 -1
- package/dist/esm/errors/BadRequestError.js.map +2 -2
- package/dist/esm/errors/ForbiddenError.js +2 -1
- package/dist/esm/errors/ForbiddenError.js.map +2 -2
- package/dist/esm/errors/InternalServerError.js +2 -1
- package/dist/esm/errors/InternalServerError.js.map +2 -2
- package/dist/esm/errors/NotFoundError.js +2 -1
- package/dist/esm/errors/NotFoundError.js.map +2 -2
- package/dist/esm/errors/UnauthorizedError.js +2 -1
- package/dist/esm/errors/UnauthorizedError.js.map +2 -2
- package/dist/esm/filters/CacheFilter.js +67 -27
- package/dist/esm/filters/CacheFilter.js.map +2 -2
- package/dist/esm/filters/IntentSchemeFilter.js +74 -0
- package/dist/esm/filters/IntentSchemeFilter.js.map +7 -0
- package/dist/esm/filters/ResourceFilter.js +6 -2
- package/dist/esm/filters/ResourceFilter.js.map +2 -2
- package/dist/esm/filters/TopicProtocolFilter.js +310 -0
- package/dist/esm/filters/TopicProtocolFilter.js.map +7 -0
- package/dist/esm/filters/index.js +2 -0
- package/dist/esm/filters/index.js.map +2 -2
- package/dist/esm/index.js +13 -0
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/inject/InjectSituationType.js +1 -1
- package/dist/esm/inject/InjectSituationType.js.map +2 -2
- package/dist/esm/models/RequestResponse.js +65 -86
- package/dist/esm/models/RequestResponse.js.map +2 -2
- package/dist/esm/models/datas/body/index.js +5 -0
- package/dist/esm/models/datas/body/index.js.map +7 -0
- package/dist/esm/models/datas/index.js +7 -0
- package/dist/esm/models/datas/index.js.map +7 -0
- package/dist/esm/models/datas/path/ReqPathData.js +6 -0
- package/dist/esm/models/datas/path/ReqPathData.js.map +7 -0
- package/dist/esm/models/datas/{search → path}/ReqSearchParamsObj.js.map +1 -1
- package/dist/esm/models/datas/path/index.js +3 -0
- package/dist/esm/models/datas/path/index.js.map +7 -0
- package/dist/esm/models/index.js +2 -8
- package/dist/esm/models/index.js.map +2 -2
- package/dist/esm/models/method/index.js +2 -0
- package/dist/esm/models/method/index.js.map +7 -0
- package/dist/esm/models/method/patch/index.js +2 -0
- package/dist/esm/models/method/patch/index.js.map +7 -0
- package/dist/esm/option/HttpServerOption.js +24 -4
- package/dist/esm/option/HttpServerOption.js.map +2 -2
- package/dist/esm/proxy/SymbolIntentApiServiceProxy.js +121 -0
- package/dist/esm/proxy/SymbolIntentApiServiceProxy.js.map +7 -0
- package/dist/esm/proxy/SymbolIntentApiServiceProxyBase.js +12 -0
- package/dist/esm/proxy/SymbolIntentApiServiceProxyBase.js.map +7 -0
- package/dist/esm/proxy/TopicProtocolApiServiceProxy.js +301 -0
- package/dist/esm/proxy/TopicProtocolApiServiceProxy.js.map +7 -0
- package/dist/esm/proxy/index.js +4 -0
- package/dist/esm/proxy/index.js.map +7 -0
- package/dist/esm/resolvers/ResourceResolver.js +1 -1
- package/dist/esm/resolvers/ResourceResolver.js.map +1 -1
- package/dist/esm/session/SessionManager.js +1 -1
- package/dist/esm/session/SessionManager.js.map +1 -1
- package/dist/esm/websocket/WebSocketClient.js +529 -0
- package/dist/esm/websocket/WebSocketClient.js.map +7 -0
- package/dist/esm/websocket/WebSocketManager.js +622 -0
- package/dist/esm/websocket/WebSocketManager.js.map +7 -0
- package/dist/esm/websocket/index.js +3 -0
- package/dist/esm/websocket/index.js.map +7 -0
- package/dist/esm-bundle/dooboostore-simple-boot-http-server.esm.js +18209 -5299
- package/dist/esm-bundle/dooboostore-simple-boot-http-server.esm.js.map +4 -4
- package/dist/types/SimpleBootHttpServer.d.ts +5 -3
- package/dist/types/SimpleBootHttpServer.d.ts.map +1 -1
- package/dist/types/codes/HttpHeaders.d.ts +3 -0
- package/dist/types/codes/HttpHeaders.d.ts.map +1 -1
- package/dist/types/codes/Mimes.d.ts +3 -1
- package/dist/types/codes/Mimes.d.ts.map +1 -1
- package/dist/types/decorators/MethodMapping.d.ts +13 -2
- package/dist/types/decorators/MethodMapping.d.ts.map +1 -1
- package/dist/types/endpoints/WebSocketEndPoint.d.ts +17 -0
- package/dist/types/endpoints/WebSocketEndPoint.d.ts.map +1 -0
- package/dist/types/errors/BadRequestError.d.ts +2 -2
- package/dist/types/errors/BadRequestError.d.ts.map +1 -1
- package/dist/types/errors/ForbiddenError.d.ts +2 -2
- package/dist/types/errors/ForbiddenError.d.ts.map +1 -1
- package/dist/types/errors/InternalServerError.d.ts +2 -2
- package/dist/types/errors/InternalServerError.d.ts.map +1 -1
- package/dist/types/errors/NotFoundError.d.ts +2 -2
- package/dist/types/errors/NotFoundError.d.ts.map +1 -1
- package/dist/types/errors/UnauthorizedError.d.ts +2 -2
- package/dist/types/errors/UnauthorizedError.d.ts.map +1 -1
- package/dist/types/filters/CacheFilter.d.ts +6 -0
- package/dist/types/filters/CacheFilter.d.ts.map +1 -1
- package/dist/types/filters/IntentSchemeFilter.d.ts +20 -0
- package/dist/types/filters/IntentSchemeFilter.d.ts.map +1 -0
- package/dist/types/filters/ResourceFilter.d.ts.map +1 -1
- package/dist/types/filters/TopicProtocolFilter.d.ts +34 -0
- package/dist/types/filters/TopicProtocolFilter.d.ts.map +1 -0
- package/dist/types/filters/index.d.ts +2 -0
- package/dist/types/filters/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/inject/InjectSituationType.d.ts.map +1 -1
- package/dist/types/models/RequestResponse.d.ts +12 -7
- package/dist/types/models/RequestResponse.d.ts.map +1 -1
- package/dist/types/models/datas/body/index.d.ts +5 -0
- package/dist/types/models/datas/body/index.d.ts.map +1 -0
- package/dist/types/models/datas/index.d.ts +7 -0
- package/dist/types/models/datas/index.d.ts.map +1 -0
- package/dist/types/models/datas/path/ReqPathData.d.ts +4 -0
- package/dist/types/models/datas/path/ReqPathData.d.ts.map +1 -0
- package/dist/types/models/datas/path/ReqSearchParamsObj.d.ts.map +1 -0
- package/dist/types/models/datas/path/index.d.ts +3 -0
- package/dist/types/models/datas/path/index.d.ts.map +1 -0
- package/dist/types/models/index.d.ts +2 -8
- package/dist/types/models/index.d.ts.map +1 -1
- package/dist/types/models/method/index.d.ts +2 -0
- package/dist/types/models/method/index.d.ts.map +1 -0
- package/dist/types/models/method/patch/index.d.ts +2 -0
- package/dist/types/models/method/patch/index.d.ts.map +1 -0
- package/dist/types/option/HttpServerOption.d.ts +30 -20
- package/dist/types/option/HttpServerOption.d.ts.map +1 -1
- package/dist/types/proxy/SymbolIntentApiServiceProxy.d.ts +16 -0
- package/dist/types/proxy/SymbolIntentApiServiceProxy.d.ts.map +1 -0
- package/dist/types/proxy/SymbolIntentApiServiceProxyBase.d.ts +5 -0
- package/dist/types/proxy/SymbolIntentApiServiceProxyBase.d.ts.map +1 -0
- package/dist/types/proxy/TopicProtocolApiServiceProxy.d.ts +28 -0
- package/dist/types/proxy/TopicProtocolApiServiceProxy.d.ts.map +1 -0
- package/dist/types/proxy/index.d.ts +4 -0
- package/dist/types/proxy/index.d.ts.map +1 -0
- package/dist/types/session/SessionManager.d.ts +2 -17
- package/dist/types/session/SessionManager.d.ts.map +1 -1
- package/dist/types/websocket/WebSocketClient.d.ts +88 -0
- package/dist/types/websocket/WebSocketClient.d.ts.map +1 -0
- package/dist/types/websocket/WebSocketManager.d.ts +163 -0
- package/dist/types/websocket/WebSocketManager.d.ts.map +1 -0
- package/dist/types/websocket/index.d.ts +3 -0
- package/dist/types/websocket/index.d.ts.map +1 -0
- package/dist/umd-bundle/dooboostore-simple-boot-http-server.umd.js +18108 -5198
- package/dist/umd-bundle/dooboostore-simple-boot-http-server.umd.js.map +4 -4
- package/dist/umd-bundle/websocket-client.umd.js +11374 -0
- package/dist/umd-bundle/websocket-client.umd.js.map +7 -0
- package/package.json +24 -15
- package/src/SimpleBootHttpServer.ts +367 -313
- package/src/codes/HttpHeaders.ts +13 -2
- package/src/codes/Mimes.ts +27 -25
- package/src/decorators/MethodMapping.ts +17 -4
- package/src/endpoints/WebSocketEndPoint.ts +12 -0
- package/src/errors/BadRequestError.ts +7 -3
- package/src/errors/ForbiddenError.ts +7 -3
- package/src/errors/InternalServerError.ts +7 -3
- package/src/errors/NotFoundError.ts +7 -3
- package/src/errors/UnauthorizedError.ts +7 -3
- package/src/filters/CacheFilter.ts +112 -67
- package/src/filters/IntentSchemeFilter.ts +69 -0
- package/src/filters/ResourceFilter.ts +10 -2
- package/src/filters/TopicProtocolFilter.ts +349 -0
- package/src/filters/index.ts +2 -0
- package/src/index.ts +13 -12
- package/src/inject/InjectSituationType.ts +1 -1
- package/src/models/RequestResponse.ts +136 -242
- package/src/models/datas/body/index.ts +4 -0
- package/src/models/datas/index.ts +6 -0
- package/src/models/datas/path/ReqPathData.ts +3 -0
- package/src/models/datas/path/index.ts +2 -0
- package/src/models/index.ts +2 -8
- package/src/models/method/index.ts +1 -0
- package/src/models/method/patch/index.ts +1 -0
- package/src/option/HttpServerOption.ts +73 -23
- package/src/proxy/SymbolIntentApiServiceProxy.ts +126 -0
- package/src/proxy/SymbolIntentApiServiceProxyBase.ts +16 -0
- package/src/proxy/TopicProtocolApiServiceProxy.ts +328 -0
- package/src/proxy/index.ts +3 -0
- package/src/resolvers/ResourceResolver.ts +1 -1
- package/src/session/SessionManager.ts +3 -3
- package/src/websocket/WebSocketClient.ts +637 -0
- package/src/websocket/WebSocketManager.ts +713 -0
- package/src/websocket/index.ts +2 -0
- package/tsconfig.json +3 -1
- package/README.MD +0 -36
- package/dist/types/models/datas/search/ReqSearchParamsObj.d.ts.map +0 -1
- /package/dist/cjs/models/datas/{search → path}/ReqSearchParamsObj.js +0 -0
- /package/dist/esm/models/datas/{search → path}/ReqSearchParamsObj.js +0 -0
- /package/dist/types/models/datas/{search → path}/ReqSearchParamsObj.d.ts +0 -0
- /package/src/models/datas/{search → path}/ReqSearchParamsObj.ts +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IncomingMessage, OutgoingHttpHeader, OutgoingHttpHeaders, ServerResponse } from 'http';
|
|
2
2
|
import { HttpHeaders, HttpHeadersType } from '../codes/HttpHeaders';
|
|
3
3
|
import { Mimes } from '../codes/Mimes';
|
|
4
|
-
import { Intent } from '@dooboostore/simple-boot
|
|
4
|
+
import { Intent } from '@dooboostore/simple-boot';
|
|
5
5
|
import { URL, URLSearchParams } from 'url';
|
|
6
6
|
import { Buffer } from 'buffer';
|
|
7
7
|
import { MultipartData } from './datas/MultipartData';
|
|
@@ -16,45 +16,30 @@ import { HttpServerOption } from '../option/HttpServerOption';
|
|
|
16
16
|
import { Blob } from 'node:buffer';
|
|
17
17
|
import * as fs from 'fs';
|
|
18
18
|
import * as os from 'os';
|
|
19
|
-
import { RandomUtils } from '@dooboostore/core
|
|
20
|
-
import { FileUtils } from '@dooboostore/core-node
|
|
21
|
-
import { ConvertUtils as CoreConvertUtils} from '@dooboostore/core
|
|
22
|
-
import { ConvertUtils } from '@dooboostore/core-node
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
import { RandomUtils } from '@dooboostore/core';
|
|
20
|
+
import { FileUtils } from '@dooboostore/core-node';
|
|
21
|
+
import { ConvertUtils as CoreConvertUtils } from '@dooboostore/core';
|
|
22
|
+
import { ConvertUtils } from '@dooboostore/core-node';
|
|
23
|
+
import {HttpMethod} from "../codes";
|
|
24
|
+
|
|
25
|
+
type Config = { sessionManager?: SessionManager; option: HttpServerOption };
|
|
26
|
+
|
|
27
27
|
export class RequestResponse {
|
|
28
28
|
protected resWriteChunk: string | Buffer | undefined;
|
|
29
29
|
protected reqBodyChunk?: Buffer;
|
|
30
30
|
protected req: IncomingMessage;
|
|
31
31
|
protected res: ServerResponse;
|
|
32
32
|
protected config: Config;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
// constructor(req: IncomingMessage, res: ServerResponse, sessionManager?: SessionManager);
|
|
38
|
-
// constructor(req: IncomingMessage | RequestResponse, res?: ServerResponse, sessionManager?: SessionManager) {
|
|
39
|
-
// // this.req = req;
|
|
40
|
-
// // this.res = res;
|
|
41
|
-
// if (req instanceof RequestResponse) {
|
|
42
|
-
// this.req = req.req;
|
|
43
|
-
// this.res = req.res;
|
|
44
|
-
// this.sessionManager = req.sessionManager;
|
|
45
|
-
// } else {
|
|
46
|
-
// this.req = req;
|
|
47
|
-
// this.res = res!;
|
|
48
|
-
// this.sessionManager = sessionManager;
|
|
49
|
-
// }
|
|
50
|
-
// }
|
|
33
|
+
|
|
34
|
+
// [아키텍트님의 정석] RequestResponse 객체 고유의 속성 저장소 (트랜잭션 생명주기)
|
|
35
|
+
protected attributes = new Map<string, any>();
|
|
36
|
+
|
|
51
37
|
constructor(req: IncomingMessage | RequestResponse, res: ServerResponse, config: Config) {
|
|
52
|
-
// this.req = req;
|
|
53
|
-
// this.res = res;
|
|
54
38
|
if (req instanceof RequestResponse) {
|
|
55
39
|
this.req = req.req;
|
|
56
40
|
this.res = req.res;
|
|
57
41
|
this.config = config;
|
|
42
|
+
this.attributes = req.attributes;
|
|
58
43
|
} else {
|
|
59
44
|
this.req = req;
|
|
60
45
|
this.res = res!;
|
|
@@ -62,6 +47,16 @@ export class RequestResponse {
|
|
|
62
47
|
}
|
|
63
48
|
}
|
|
64
49
|
|
|
50
|
+
// --- RequestResponse Attributes (Transaction Life-cycle) ---
|
|
51
|
+
|
|
52
|
+
setAttribute(key: string, value: any): void {
|
|
53
|
+
this.attributes.set(key, value);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
getAttribute<T = any>(key: string): T | undefined {
|
|
57
|
+
return this.attributes.get(key) as T;
|
|
58
|
+
}
|
|
59
|
+
|
|
65
60
|
get reqSocket() {
|
|
66
61
|
return this.req.socket;
|
|
67
62
|
}
|
|
@@ -69,13 +64,16 @@ export class RequestResponse {
|
|
|
69
64
|
get reqCookieMap() {
|
|
70
65
|
let cookies = this.reqHeader(HttpHeaders.Cookie) ?? '';
|
|
71
66
|
if (Array.isArray(cookies)) {
|
|
72
|
-
cookies = cookies.join(';')
|
|
67
|
+
cookies = cookies.join(';');
|
|
73
68
|
}
|
|
74
69
|
|
|
75
70
|
const map = new Map<string, string>();
|
|
76
|
-
cookies
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
cookies
|
|
72
|
+
.split(';')
|
|
73
|
+
.map(it => it.trim().split('='))
|
|
74
|
+
.forEach(it => {
|
|
75
|
+
if (it[0]) map.set(it[0], it[1]);
|
|
76
|
+
});
|
|
79
77
|
return map;
|
|
80
78
|
}
|
|
81
79
|
|
|
@@ -95,11 +93,10 @@ export class RequestResponse {
|
|
|
95
93
|
}
|
|
96
94
|
|
|
97
95
|
get reqUrlObject(): URL {
|
|
98
|
-
return new URL(this.reqUrl, `${this.reqSocket ? 'https://' : 'http'}${this.reqHost ?? 'localhost'}`);
|
|
96
|
+
return new URL(this.reqUrl, `${this.reqSocket ? 'https://' : 'http://'}${this.reqHost ?? 'localhost'}`);
|
|
99
97
|
}
|
|
100
98
|
|
|
101
99
|
get reqUrlPathName(): string {
|
|
102
|
-
// parse(rr.reqUrl ?? '', true)
|
|
103
100
|
return this.reqUrlObj().pathname ?? '';
|
|
104
101
|
}
|
|
105
102
|
|
|
@@ -107,8 +104,8 @@ export class RequestResponse {
|
|
|
107
104
|
return this.req.url ?? '';
|
|
108
105
|
}
|
|
109
106
|
|
|
110
|
-
reqUrlObj(config?:{scheme?: string
|
|
111
|
-
return new URL(`${config?.scheme??'http'
|
|
107
|
+
reqUrlObj(config?: { scheme?: string; host?: string }): URL {
|
|
108
|
+
return new URL(`${config?.scheme ?? 'http'}://${config?.host ? config?.host : (this.reqHeaderFirst(HttpHeaders.Host) ?? 'localhost')}${this.req.url ?? ''}`);
|
|
112
109
|
}
|
|
113
110
|
|
|
114
111
|
get reqUrlSearchParamTuples(): [string, string][] {
|
|
@@ -119,16 +116,14 @@ export class RequestResponse {
|
|
|
119
116
|
return this.reqUrlObj().searchParams;
|
|
120
117
|
}
|
|
121
118
|
|
|
122
|
-
get reqUrlSearchParamsObj(): {[p: string]: string | string[]} {
|
|
119
|
+
get reqUrlSearchParamsObj(): { [p: string]: string | string[] } {
|
|
123
120
|
const entries = this.reqUrlObj().searchParams;
|
|
124
121
|
return CoreConvertUtils.toObject(entries);
|
|
125
|
-
// return obj;
|
|
126
|
-
// return Object.fromEntries(entries as any)
|
|
127
122
|
}
|
|
128
123
|
|
|
129
124
|
get reqPathSearchParamUrl(): string {
|
|
130
125
|
const reqUrlObj = this.reqUrlObj();
|
|
131
|
-
return reqUrlObj.pathname + (reqUrlObj.searchParams.toString() ? '?' + reqUrlObj.searchParams.toString() : '')
|
|
126
|
+
return reqUrlObj.pathname + (reqUrlObj.searchParams.toString() ? '?' + reqUrlObj.searchParams.toString() : '');
|
|
132
127
|
}
|
|
133
128
|
|
|
134
129
|
get reqReadable() {
|
|
@@ -140,18 +135,39 @@ export class RequestResponse {
|
|
|
140
135
|
}
|
|
141
136
|
|
|
142
137
|
reqHasContentTypeHeader(mime: Mimes | string): boolean {
|
|
143
|
-
|
|
138
|
+
const contentType = this.reqHeader(HttpHeaders.ContentType);
|
|
139
|
+
if (!contentType) return false;
|
|
140
|
+
|
|
141
|
+
const targetMime = mime.toString().toLowerCase();
|
|
142
|
+
const contentTypes = Array.isArray(contentType) ? contentType : [contentType];
|
|
143
|
+
|
|
144
|
+
// 모든 Content-Type 헤더를 확인
|
|
145
|
+
return contentTypes.some(ct => {
|
|
146
|
+
// Content-Type은 보통 단일 값이지만, 파라미터가 붙을 수 있음 (charset=utf-8 등)
|
|
147
|
+
// 세미콜론으로 split해서 앞 부분(MIME 타입)만 비교
|
|
148
|
+
const [mimeType] = ct.split(';').map(m => m.trim());
|
|
149
|
+
return mimeType.toLowerCase() === targetMime || mimeType.toLowerCase().includes(targetMime);
|
|
150
|
+
});
|
|
144
151
|
}
|
|
145
152
|
|
|
146
153
|
reqHasAcceptHeader(mime: Mimes | string): boolean {
|
|
147
|
-
|
|
154
|
+
const accept = this.reqHeader(HttpHeaders.Accept);
|
|
155
|
+
if (!accept) return false;
|
|
156
|
+
|
|
157
|
+
const targetMime = mime.toString().toLowerCase();
|
|
158
|
+
const acceptHeaders = Array.isArray(accept) ? accept : [accept];
|
|
159
|
+
|
|
160
|
+
return acceptHeaders.some(acceptHeader => {
|
|
161
|
+
const acceptMimes = acceptHeader.split(',').map(m => m.split(';')[0].trim().toLowerCase());
|
|
162
|
+
return acceptMimes.some(acceptMime => acceptMime.includes(targetMime));
|
|
163
|
+
});
|
|
148
164
|
}
|
|
149
165
|
|
|
150
166
|
reqBodyData(): Promise<Buffer> {
|
|
151
167
|
return new Promise<Buffer>((resolve, reject) => {
|
|
152
168
|
if (this.reqReadable) {
|
|
153
169
|
const data: Uint8Array[] = [];
|
|
154
|
-
this.req.on('data',
|
|
170
|
+
this.req.on('data', chunk => data.push(chunk));
|
|
155
171
|
this.req.on('error', err => reject(err));
|
|
156
172
|
this.req.on('end', () => {
|
|
157
173
|
this.reqBodyChunk = Buffer.concat(data);
|
|
@@ -162,31 +178,29 @@ export class RequestResponse {
|
|
|
162
178
|
}
|
|
163
179
|
});
|
|
164
180
|
}
|
|
165
|
-
|
|
166
|
-
resBodyData(): string | Buffer | undefined{
|
|
181
|
+
|
|
182
|
+
resBodyData(): string | Buffer | undefined {
|
|
167
183
|
return this.resWriteChunk;
|
|
168
184
|
}
|
|
169
185
|
|
|
170
|
-
|
|
171
|
-
|
|
172
186
|
async reqBodyMultipartFormDataObject<T>(): Promise<T> {
|
|
173
187
|
const m = await this.reqBodyMultipartFormData();
|
|
174
188
|
const formData = {} as any;
|
|
175
189
|
|
|
176
190
|
for (const it of m) {
|
|
177
191
|
if (it.isFile) {
|
|
178
|
-
formData[it.name] = await FileUtils.writeFile(it.value, {originalName: it.filename, etcData: it });
|
|
192
|
+
formData[it.name] = await FileUtils.writeFile(it.value, { originalName: it.filename, etcData: it });
|
|
179
193
|
} else {
|
|
180
194
|
const target = formData[it.name];
|
|
181
195
|
if (Array.isArray(target)) {
|
|
182
196
|
target.push(it.value);
|
|
183
197
|
} else if (typeof target === 'string') {
|
|
184
|
-
formData[it.name] = [target, it.value]
|
|
198
|
+
formData[it.name] = [target, it.value];
|
|
185
199
|
} else {
|
|
186
200
|
formData[it.name] = it.value;
|
|
187
201
|
}
|
|
188
202
|
}
|
|
189
|
-
}
|
|
203
|
+
}
|
|
190
204
|
return formData;
|
|
191
205
|
}
|
|
192
206
|
|
|
@@ -201,14 +215,14 @@ export class RequestResponse {
|
|
|
201
215
|
if (!boundaryMatch) {
|
|
202
216
|
return reject(new Error('Boundary not found in Content-Type header.'));
|
|
203
217
|
}
|
|
204
|
-
const boundary = boundaryMatch[1] || boundaryMatch[2];
|
|
218
|
+
const boundary = boundaryMatch[1] || boundaryMatch[2];
|
|
205
219
|
if (!boundary) {
|
|
206
220
|
return reject(new Error('Failed to extract boundary.'));
|
|
207
221
|
}
|
|
208
222
|
|
|
209
223
|
const boundaryBuffer = Buffer.from(`--${boundary}`);
|
|
210
224
|
const crlfBuffer = Buffer.from('\r\n');
|
|
211
|
-
const doubleCrlfBuffer = Buffer.from('\r\n\r\n');
|
|
225
|
+
const doubleCrlfBuffer = Buffer.from('\r\n\r\n');
|
|
212
226
|
|
|
213
227
|
const chunks: Buffer[] = [];
|
|
214
228
|
let totalLength = 0;
|
|
@@ -218,65 +232,54 @@ export class RequestResponse {
|
|
|
218
232
|
totalLength += chunk.length;
|
|
219
233
|
});
|
|
220
234
|
|
|
221
|
-
this.req.on('error',
|
|
235
|
+
this.req.on('error', err => {
|
|
222
236
|
reject(err);
|
|
223
237
|
});
|
|
224
238
|
|
|
225
239
|
this.req.on('end', () => {
|
|
226
240
|
if (totalLength === 0) {
|
|
227
|
-
return resolve([]);
|
|
241
|
+
return resolve([]);
|
|
228
242
|
}
|
|
229
243
|
|
|
230
244
|
const fullBuffer = Buffer.concat(chunks, totalLength);
|
|
231
245
|
const parsedParts: MultipartData[] = [];
|
|
232
246
|
let currentPosition = 0;
|
|
233
247
|
|
|
234
|
-
// 첫 번째 boundary 찾기 (보통 시작 부분에 있음)
|
|
235
248
|
let boundaryStartIndex = fullBuffer.indexOf(boundaryBuffer, currentPosition);
|
|
236
249
|
if (boundaryStartIndex === -1) {
|
|
237
250
|
return reject(new Error('Initial boundary not found.'));
|
|
238
251
|
}
|
|
239
|
-
// boundary 바로 다음 \r\n 건너뛰기
|
|
240
252
|
currentPosition = boundaryStartIndex + boundaryBuffer.length;
|
|
241
253
|
if (fullBuffer.slice(currentPosition, currentPosition + crlfBuffer.length).equals(crlfBuffer)) {
|
|
242
254
|
currentPosition += crlfBuffer.length;
|
|
243
255
|
}
|
|
244
256
|
|
|
245
|
-
|
|
246
257
|
while (currentPosition < fullBuffer.length) {
|
|
247
|
-
// 다음 boundary 찾기 (파트의 끝)
|
|
248
258
|
const nextBoundaryIndex = fullBuffer.indexOf(boundaryBuffer, currentPosition);
|
|
249
259
|
if (nextBoundaryIndex === -1) {
|
|
250
|
-
// 마지막 boundary (--)인지 확인 필요하나, 여기서는 단순하게 처리
|
|
251
|
-
// console.warn('Next boundary not found, assuming end of data or malformed.');
|
|
252
260
|
break;
|
|
253
261
|
}
|
|
254
262
|
|
|
255
|
-
// 현재 파트 데이터 추출 (boundary 이전까지)
|
|
256
|
-
// 실제 파트 데이터는 다음 boundary 바로 앞의 \r\n을 제외해야 함
|
|
257
263
|
let partEndIndex = nextBoundaryIndex;
|
|
258
264
|
if (partEndIndex > crlfBuffer.length && fullBuffer.slice(partEndIndex - crlfBuffer.length, partEndIndex).equals(crlfBuffer)) {
|
|
259
265
|
partEndIndex -= crlfBuffer.length;
|
|
260
266
|
}
|
|
261
267
|
const partBuffer = fullBuffer.slice(currentPosition, partEndIndex);
|
|
262
268
|
|
|
263
|
-
// 헤더와 바디 분리
|
|
264
269
|
const headerBodySeparatorIndex = partBuffer.indexOf(doubleCrlfBuffer);
|
|
265
270
|
if (headerBodySeparatorIndex === -1) {
|
|
266
|
-
console.warn('Skipping malformed part: no header/body separator found.');
|
|
267
271
|
currentPosition = nextBoundaryIndex + boundaryBuffer.length;
|
|
268
272
|
if (fullBuffer.slice(currentPosition, currentPosition + crlfBuffer.length).equals(crlfBuffer)) {
|
|
269
273
|
currentPosition += crlfBuffer.length;
|
|
270
274
|
}
|
|
271
|
-
if (fullBuffer.slice(currentPosition, currentPosition + 2).toString() === '--') break;
|
|
275
|
+
if (fullBuffer.slice(currentPosition, currentPosition + 2).toString() === '--') break;
|
|
272
276
|
continue;
|
|
273
277
|
}
|
|
274
278
|
|
|
275
279
|
const headerBuffer = partBuffer.slice(0, headerBodySeparatorIndex);
|
|
276
280
|
const bodyBuffer = partBuffer.slice(headerBodySeparatorIndex + doubleCrlfBuffer.length);
|
|
277
|
-
const headersStr = headerBuffer.toString('utf-8');
|
|
281
|
+
const headersStr = headerBuffer.toString('utf-8');
|
|
278
282
|
|
|
279
|
-
// 헤더 파싱
|
|
280
283
|
const headers: { [key: string]: string } = {};
|
|
281
284
|
headersStr.split('\r\n').forEach(line => {
|
|
282
285
|
const colonIndex = line.indexOf(':');
|
|
@@ -289,7 +292,6 @@ export class RequestResponse {
|
|
|
289
292
|
|
|
290
293
|
const contentDisposition = headers['content-disposition'];
|
|
291
294
|
if (!contentDisposition) {
|
|
292
|
-
console.warn('Skipping part: no Content-Disposition header.');
|
|
293
295
|
currentPosition = nextBoundaryIndex + boundaryBuffer.length;
|
|
294
296
|
if (fullBuffer.slice(currentPosition, currentPosition + crlfBuffer.length).equals(crlfBuffer)) {
|
|
295
297
|
currentPosition += crlfBuffer.length;
|
|
@@ -306,113 +308,39 @@ export class RequestResponse {
|
|
|
306
308
|
const contentType = headers['content-type'] || null;
|
|
307
309
|
|
|
308
310
|
if (name) {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
311
|
+
if (filename) {
|
|
312
|
+
parsedParts.push({
|
|
313
|
+
isFile: true,
|
|
314
|
+
name: name,
|
|
315
|
+
filename: filename,
|
|
316
|
+
contentType: contentType ?? 'application/octet-stream',
|
|
317
|
+
value: bodyBuffer
|
|
318
|
+
});
|
|
319
|
+
} else {
|
|
320
|
+
parsedParts.push({
|
|
321
|
+
isFile: false,
|
|
322
|
+
name: name,
|
|
323
|
+
value: bodyBuffer.toString('utf-8')
|
|
324
|
+
});
|
|
318
325
|
}
|
|
319
|
-
parsedParts.push(multipartData);
|
|
320
|
-
} else {
|
|
321
|
-
console.warn("Skipping part: 'name' not found in Content-Disposition.");
|
|
322
326
|
}
|
|
323
327
|
|
|
324
|
-
// 다음 파트 시작 위치로 이동
|
|
325
328
|
currentPosition = nextBoundaryIndex + boundaryBuffer.length;
|
|
326
|
-
// boundary 바로 다음 \r\n 건너뛰기
|
|
327
329
|
if (fullBuffer.slice(currentPosition, currentPosition + crlfBuffer.length).equals(crlfBuffer)) {
|
|
328
330
|
currentPosition += crlfBuffer.length;
|
|
329
331
|
}
|
|
330
332
|
|
|
331
|
-
// 마지막 boundary (--)인지 확인하고 루프 종료
|
|
332
333
|
if (fullBuffer.slice(currentPosition, currentPosition + 2).toString() === '--') {
|
|
333
334
|
break;
|
|
334
335
|
}
|
|
335
336
|
}
|
|
336
337
|
resolve(parsedParts);
|
|
337
338
|
});
|
|
338
|
-
})
|
|
339
|
-
// const form = formidable({});
|
|
340
|
-
// return new Promise((resolve, reject) => {
|
|
341
|
-
// form.parse(this.req, (err, fields, files) => {
|
|
342
|
-
// if (err) {
|
|
343
|
-
// reject(err);
|
|
344
|
-
// return;
|
|
345
|
-
// }
|
|
346
|
-
//
|
|
347
|
-
// console.log('----', files)
|
|
348
|
-
// // this.res.set('Content-Type', 'application/json');
|
|
349
|
-
// // ctx.status = 200;
|
|
350
|
-
// // ctx.state = { fields, files };
|
|
351
|
-
// // ctx.body = JSON.stringify(ctx.state, null, 2);
|
|
352
|
-
// resolve(' ' as any);
|
|
353
|
-
// });
|
|
354
|
-
// });
|
|
355
|
-
|
|
356
|
-
// return new Promise<MultipartData<any>[]>((resolve, reject) => {
|
|
357
|
-
//
|
|
358
|
-
//
|
|
359
|
-
// const contentType = this.req.headers['content-type'];
|
|
360
|
-
// const boundary = contentType.split('boundary=')[1];
|
|
361
|
-
//
|
|
362
|
-
// let body: Uint8Array[] = [];
|
|
363
|
-
// this.req.on('data', chunk => body.push(chunk));
|
|
364
|
-
// this.req.on('end', async () => {
|
|
365
|
-
// const buffer = Buffer.concat(body);
|
|
366
|
-
// // Boundary로 파트 분리
|
|
367
|
-
// const parts = buffer.toString().split(`--${boundary}`).slice(1, -1);
|
|
368
|
-
// let jsonData = {};
|
|
369
|
-
// let fileData = null;
|
|
370
|
-
//
|
|
371
|
-
// for (let part of parts) {
|
|
372
|
-
// const [headerPart, ...bodyParts] = part.split('\r\n\r\n');
|
|
373
|
-
// const headers = headerPart.split('\r\n').reduce((acc, line) => {
|
|
374
|
-
// const [key, value] = line.split(': ').map(s => s.trim().toLowerCase());
|
|
375
|
-
// if (key) acc[key] = value;
|
|
376
|
-
// return acc;
|
|
377
|
-
// }, {});
|
|
378
|
-
//
|
|
379
|
-
// const content = bodyParts.join('\r\n\r\n').trim();
|
|
380
|
-
// const disposition = headers['content-disposition'];
|
|
381
|
-
// const name = disposition?.match(/name="([^"]+)"/)?.[1];
|
|
382
|
-
// const filename = disposition?.match(/filename="([^"]+)"/)?.[1];
|
|
383
|
-
//
|
|
384
|
-
// if (filename) {
|
|
385
|
-
// // 파일 데이터 (Blob)
|
|
386
|
-
// fileData = { filename, contentType: headers['content-type'], data: Buffer.from(content, 'binary') };
|
|
387
|
-
// } else if (name) {
|
|
388
|
-
// // 텍스트 데이터
|
|
389
|
-
// if (name === 'metadata') jsonData = JSON.parse(content);
|
|
390
|
-
// }
|
|
391
|
-
// }
|
|
392
|
-
//
|
|
393
|
-
// // 파일 저장
|
|
394
|
-
// if (fileData) {
|
|
395
|
-
//
|
|
396
|
-
//
|
|
397
|
-
//
|
|
398
|
-
//
|
|
399
|
-
// const uploadPath = this.config.option.fileUploadTempPath || os.tmpdir();
|
|
400
|
-
// fs.mkdirSync(uploadPath, { recursive: true }); // 폴더가 없으면 생성
|
|
401
|
-
// const saveTempPath = `${uploadPath}/${RandomUtils.uuid4()}${fileData.filename}`;
|
|
402
|
-
// console.log('saveTempPathsaveTempPath', saveTempPath)
|
|
403
|
-
// await fs.promises.writeFile(saveTempPath, fileData.data);
|
|
404
|
-
// this.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
405
|
-
// this.res.end(JSON.stringify({ message: '업로드 성공', jsonData, filename: fileData?.filename }));
|
|
406
|
-
// // const uploadPath = this.config.option.fileUploadTempPath ;
|
|
407
|
-
// // fs.mkdirSync(uploadPath, { recursive: true }); // 폴더가 없으면 생성
|
|
408
|
-
// // await fs.writeFile(`${uploadPath}/${fileData.filename}`, fileData.data);
|
|
409
|
-
// }
|
|
410
|
-
// });
|
|
411
|
-
// });
|
|
339
|
+
});
|
|
412
340
|
}
|
|
413
341
|
|
|
414
342
|
async reqBodyStringData(): Promise<string> {
|
|
415
|
-
const data = (await this.reqBodyData()).toString()
|
|
343
|
+
const data = (await this.reqBodyData()).toString();
|
|
416
344
|
return data;
|
|
417
345
|
}
|
|
418
346
|
|
|
@@ -421,14 +349,14 @@ export class RequestResponse {
|
|
|
421
349
|
}
|
|
422
350
|
|
|
423
351
|
async reqBodyFormUrlData<T>(): Promise<T> {
|
|
424
|
-
const data =
|
|
352
|
+
const data = await this.reqBodyStringData();
|
|
425
353
|
const formData = {} as any;
|
|
426
354
|
Array.from(new URLSearchParams(data).entries()).forEach(([k, v]) => {
|
|
427
355
|
const target = formData[k];
|
|
428
356
|
if (Array.isArray(target)) {
|
|
429
357
|
target.push(v);
|
|
430
358
|
} else if (typeof target === 'string') {
|
|
431
|
-
formData[k] = [target, v]
|
|
359
|
+
formData[k] = [target, v];
|
|
432
360
|
} else {
|
|
433
361
|
formData[k] = v;
|
|
434
362
|
}
|
|
@@ -437,20 +365,16 @@ export class RequestResponse {
|
|
|
437
365
|
}
|
|
438
366
|
|
|
439
367
|
async reqBodyReqFormUrlBody() {
|
|
440
|
-
const data = await this.reqBodyFormUrlData()
|
|
368
|
+
const data = await this.reqBodyFormUrlData();
|
|
441
369
|
return Object.assign(new ReqFormUrlBody(), data);
|
|
442
370
|
}
|
|
443
371
|
|
|
444
372
|
async reqBodyReqJsonBody(): Promise<ReqJsonBody> {
|
|
445
|
-
const data =
|
|
446
|
-
return Object.assign(new ReqJsonBody(), data ? JSON.parse(data) : {})
|
|
373
|
+
const data = await this.reqBodyStringData();
|
|
374
|
+
return Object.assign(new ReqJsonBody(), data ? JSON.parse(data) : {});
|
|
447
375
|
}
|
|
448
376
|
|
|
449
|
-
|
|
450
|
-
// return this.reqBodyMultipartFormData().then(it => new ReqMultipartFormBody(it))
|
|
451
|
-
// }
|
|
452
|
-
|
|
453
|
-
resBodyJsonData<T>(): (T | null) {
|
|
377
|
+
resBodyJsonData<T>(): T | null {
|
|
454
378
|
const data = ConvertUtils.toString(this.resBodyData());
|
|
455
379
|
return data ? JSON.parse(data) : null;
|
|
456
380
|
}
|
|
@@ -463,12 +387,16 @@ export class RequestResponse {
|
|
|
463
387
|
return this.req.method?.toUpperCase();
|
|
464
388
|
}
|
|
465
389
|
|
|
390
|
+
reqIsMethod(method: HttpMethod | string) {
|
|
391
|
+
return this.reqMethod().toUpperCase() === (method as string).toUpperCase();
|
|
392
|
+
}
|
|
393
|
+
|
|
466
394
|
reqHeader(key: keyof typeof HttpHeaders | string) {
|
|
467
|
-
return this.req.headers[key.toLowerCase()];
|
|
395
|
+
return this.req.headers[(key as string).toLowerCase()];
|
|
468
396
|
}
|
|
469
397
|
|
|
470
398
|
get reqHost() {
|
|
471
|
-
return this.reqHeaderFirst(HttpHeaders.Host)
|
|
399
|
+
return this.reqHeaderFirst(HttpHeaders.Host);
|
|
472
400
|
}
|
|
473
401
|
|
|
474
402
|
get reqHeaderObj(): ReqHeader {
|
|
@@ -480,7 +408,7 @@ export class RequestResponse {
|
|
|
480
408
|
}
|
|
481
409
|
|
|
482
410
|
reqHeaderFirst(key: HttpHeadersType | string, defaultValue?: string) {
|
|
483
|
-
const header = this.req.headers[key.toLowerCase()];
|
|
411
|
+
const header = this.req.headers[(key as string).toLowerCase()];
|
|
484
412
|
if (header && Array.isArray(header)) {
|
|
485
413
|
return header[0] ?? defaultValue;
|
|
486
414
|
} else {
|
|
@@ -497,9 +425,7 @@ export class RequestResponse {
|
|
|
497
425
|
}
|
|
498
426
|
|
|
499
427
|
resStatusCode(code?: undefined): number;
|
|
500
|
-
// eslint-disable-next-line no-dupe-class-members
|
|
501
428
|
resStatusCode(code: number | HttpStatus): RequestResponseChain<number>;
|
|
502
|
-
// eslint-disable-next-line no-dupe-class-members
|
|
503
429
|
resStatusCode(code: number | undefined | HttpStatus): number | RequestResponseChain<number> {
|
|
504
430
|
if (code) {
|
|
505
431
|
this.res.statusCode = code;
|
|
@@ -510,11 +436,11 @@ export class RequestResponse {
|
|
|
510
436
|
}
|
|
511
437
|
|
|
512
438
|
resHeader(key: HttpHeadersType | string) {
|
|
513
|
-
return this.res.getHeader(key.toLowerCase());
|
|
439
|
+
return this.res.getHeader((key as string).toLowerCase());
|
|
514
440
|
}
|
|
515
441
|
|
|
516
442
|
resHeaderFirst(key: HttpHeadersType | string, defaultValue?: string) {
|
|
517
|
-
const header = this.res.getHeader(key.toLowerCase());
|
|
443
|
+
const header = this.res.getHeader((key as string).toLowerCase());
|
|
518
444
|
if (header && Array.isArray(header)) {
|
|
519
445
|
return header[0] ?? defaultValue;
|
|
520
446
|
} else {
|
|
@@ -524,21 +450,22 @@ export class RequestResponse {
|
|
|
524
450
|
|
|
525
451
|
async reqSession(): Promise<{ [key: string]: any }> {
|
|
526
452
|
if (this.config.sessionManager) {
|
|
527
|
-
|
|
453
|
+
const session = await this.config.sessionManager.session(this);
|
|
454
|
+
session.dataSet.data ??= {};
|
|
455
|
+
return session.dataSet.data;
|
|
528
456
|
} else {
|
|
529
457
|
return Promise.reject(new Error('Not SessionManager'));
|
|
530
458
|
}
|
|
531
459
|
}
|
|
532
460
|
|
|
533
|
-
reqSessionSet(key: string, value: any): void {
|
|
534
|
-
|
|
461
|
+
async reqSessionSet(key: string, value: any): Promise<void> {
|
|
462
|
+
const sessionData = await this.reqSession();
|
|
463
|
+
sessionData[key] = value;
|
|
535
464
|
}
|
|
536
465
|
|
|
537
|
-
reqSessionGet<T = any>(key: string): T | undefined {
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
return session[key] as T;
|
|
541
|
-
}
|
|
466
|
+
async reqSessionGet<T = any>(key: string): Promise<T | undefined> {
|
|
467
|
+
const sessionData = await this.reqSession();
|
|
468
|
+
return sessionData[key] as T;
|
|
542
469
|
}
|
|
543
470
|
|
|
544
471
|
resSetStatusCode(statusCode: number) {
|
|
@@ -546,33 +473,25 @@ export class RequestResponse {
|
|
|
546
473
|
return this.createRequestResponseChain(this.res.statusCode);
|
|
547
474
|
}
|
|
548
475
|
|
|
549
|
-
// resEnd() {
|
|
550
|
-
// this.res.end();
|
|
551
|
-
// }
|
|
552
|
-
|
|
553
|
-
// eslint-disable-next-line no-undef
|
|
554
476
|
resWrite(chunk: string | Buffer | any, encoding: BufferEncoding = 'utf8') {
|
|
555
477
|
this.resWriteChunk = chunk;
|
|
556
478
|
return this.createRequestResponseChain(this.resWriteChunk);
|
|
557
479
|
}
|
|
558
480
|
|
|
559
|
-
// eslint-disable-next-line no-undef
|
|
560
481
|
resWriteJson(chunk: any, encoding: BufferEncoding = 'utf8') {
|
|
561
482
|
return this.resWrite(JSON.stringify(chunk), encoding);
|
|
562
483
|
}
|
|
563
484
|
|
|
564
485
|
resSetHeader(key: HttpHeadersType | string, value: string | string[]) {
|
|
565
|
-
|
|
486
|
+
this.res.setHeader((key as string).toLowerCase(), value);
|
|
487
|
+
return this.createRequestResponseChain();
|
|
566
488
|
}
|
|
567
489
|
|
|
568
490
|
resAddHeader(key: HttpHeadersType | string, value: string | string[]) {
|
|
569
|
-
const existingValue = this.res.getHeader(key.toLowerCase());
|
|
570
|
-
const newValue = Array.isArray(existingValue)
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
? [existingValue.toString(), ...[].concat(value)]
|
|
574
|
-
: value;
|
|
575
|
-
return this.createRequestResponseChain(this.res.setHeader(key.toLowerCase(), newValue));
|
|
491
|
+
const existingValue = this.res.getHeader((key as string).toLowerCase());
|
|
492
|
+
const newValue = Array.isArray(existingValue) ? existingValue.concat(value) : existingValue ? [existingValue.toString(), ...[].concat(value as any)] : value;
|
|
493
|
+
this.res.setHeader((key as string).toLowerCase(), newValue as any);
|
|
494
|
+
return this.createRequestResponseChain();
|
|
576
495
|
}
|
|
577
496
|
|
|
578
497
|
resSetHeaders(headers: { [key: string]: string | string[] }) {
|
|
@@ -581,15 +500,14 @@ export class RequestResponse {
|
|
|
581
500
|
}
|
|
582
501
|
|
|
583
502
|
resAddHeaders(headers: { [key: string]: string | string[] }) {
|
|
584
|
-
|
|
585
|
-
|
|
503
|
+
Object.entries(headers).forEach(([key, value]) => this.resAddHeader(key, value));
|
|
504
|
+
return this.createRequestResponseChain();
|
|
586
505
|
}
|
|
587
506
|
|
|
588
|
-
// 마지막 종료될때 타는거.
|
|
589
507
|
private async resEndChunk() {
|
|
590
508
|
const encoding = this.reqHeaderFirst(HttpHeaders.AcceptEncoding);
|
|
591
509
|
let data = this.resWriteChunk;
|
|
592
|
-
if (encoding?.includes('gzip')) {
|
|
510
|
+
if (encoding?.includes('gzip') && data) {
|
|
593
511
|
data = await gzip(data);
|
|
594
512
|
this.resSetHeader(HttpHeaders.ContentEncoding, 'gzip');
|
|
595
513
|
}
|
|
@@ -598,27 +516,24 @@ export class RequestResponse {
|
|
|
598
516
|
|
|
599
517
|
async resEnd(chunk?: string | Buffer | Blob | ArrayBuffer | Response) {
|
|
600
518
|
if (chunk instanceof Response) {
|
|
601
|
-
// 헤더를 직접 설정하여 체이닝 오버헤드 제거
|
|
602
519
|
chunk.headers.forEach((value, key) => {
|
|
603
520
|
this.res.setHeader(`ORIGIN-${key}`, value);
|
|
604
521
|
});
|
|
605
522
|
if (!this.resHeader(HttpHeaders.ContentType)) {
|
|
606
523
|
const contentType = chunk.headers.get(HttpHeaders.ContentType);
|
|
607
|
-
if (contentType)
|
|
608
|
-
this.res.setHeader(HttpHeaders.ContentType, contentType);
|
|
609
|
-
}
|
|
524
|
+
if (contentType) this.res.setHeader(HttpHeaders.ContentType, contentType);
|
|
610
525
|
}
|
|
611
526
|
this.res.statusCode = chunk.status;
|
|
612
527
|
this.resWriteChunk = Buffer.from(await chunk.arrayBuffer());
|
|
613
528
|
} else if (chunk instanceof Blob) {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
529
|
+
this.resWriteChunk = Buffer.from(await chunk.arrayBuffer());
|
|
530
|
+
if (!this.resHeader(HttpHeaders.ContentType)) {
|
|
531
|
+
this.res.setHeader(HttpHeaders.ContentType, chunk.type);
|
|
532
|
+
}
|
|
618
533
|
} else if (chunk instanceof ArrayBuffer) {
|
|
619
|
-
|
|
534
|
+
this.resWriteChunk = Buffer.from(chunk);
|
|
620
535
|
} else {
|
|
621
|
-
|
|
536
|
+
this.resWriteChunk = chunk ?? this.resWriteChunk;
|
|
622
537
|
}
|
|
623
538
|
|
|
624
539
|
if (this.req.readable) {
|
|
@@ -629,33 +544,21 @@ export class RequestResponse {
|
|
|
629
544
|
}
|
|
630
545
|
}
|
|
631
546
|
|
|
632
|
-
// writeContinue(callback?: () => void) {
|
|
633
|
-
// this.res.writeContinue(callback);
|
|
634
|
-
// return new RequestResponseChain(this.req, this.res);
|
|
635
|
-
// }
|
|
636
|
-
|
|
637
|
-
// reqWrite(chunk?: any) {
|
|
638
|
-
// this.resWriteChunk = chunk;
|
|
639
|
-
// // this.res.write(chunk);
|
|
640
|
-
// return this.createRequestResponseChain();
|
|
641
|
-
// }
|
|
642
|
-
|
|
643
547
|
resRedirect(statusCode: number, location: string) {
|
|
644
548
|
this.res.statusCode = statusCode;
|
|
645
549
|
this.res.setHeader(HttpHeaders.Location, location);
|
|
646
550
|
this.res.end();
|
|
647
551
|
}
|
|
648
552
|
resWriteHead(statusCode: number, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[] | { [key: string]: string | string[] }) {
|
|
649
|
-
return this.createRequestResponseChain(this.res.writeHead(statusCode, headers));
|
|
553
|
+
return this.createRequestResponseChain(this.res.writeHead(statusCode, headers as any));
|
|
650
554
|
}
|
|
651
555
|
resWriteHeadEnd(statusCode: number, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[] | { [key: string]: string | string[] }) {
|
|
652
|
-
this.createRequestResponseChain(this.res.writeHead(statusCode, headers));
|
|
556
|
+
this.createRequestResponseChain(this.res.writeHead(statusCode, headers as any));
|
|
653
557
|
this.res.end();
|
|
654
558
|
}
|
|
655
559
|
|
|
656
560
|
resIsDone() {
|
|
657
561
|
return this.res.finished || this.res.writableEnded || this.res.headersSent;
|
|
658
|
-
// return new RequestResponseChain(this.req, this.res, this.res.finished || this.res.writableEnded);
|
|
659
562
|
}
|
|
660
563
|
|
|
661
564
|
createRequestResponseChain<T = any>(data?: T) {
|
|
@@ -664,24 +567,15 @@ export class RequestResponse {
|
|
|
664
567
|
requestResponseChain.reqBodyChunk = this.reqBodyChunk;
|
|
665
568
|
return requestResponseChain;
|
|
666
569
|
}
|
|
667
|
-
|
|
668
|
-
// res.on("readable", () => {
|
|
669
|
-
// console.log('readable???')
|
|
670
|
-
// });
|
|
671
|
-
// res.on('complete', function (details) {
|
|
672
|
-
// var size = details.req.bytes;
|
|
673
|
-
// console.log('complete-->', size)
|
|
674
|
-
// });
|
|
675
|
-
// res.on('finish', function() {
|
|
676
|
-
// console.log('finish??');
|
|
677
|
-
// });
|
|
678
|
-
// res.on('end', () => {
|
|
679
|
-
// console.log('end--?')
|
|
680
|
-
// });
|
|
681
570
|
}
|
|
682
571
|
|
|
683
572
|
export class RequestResponseChain<T> extends RequestResponse {
|
|
684
|
-
constructor(
|
|
573
|
+
constructor(
|
|
574
|
+
req: IncomingMessage,
|
|
575
|
+
res: ServerResponse,
|
|
576
|
+
config: Config,
|
|
577
|
+
public result?: T
|
|
578
|
+
) {
|
|
685
579
|
super(req, res, config);
|
|
686
580
|
}
|
|
687
|
-
}
|
|
581
|
+
}
|