@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
package/README.MD
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# SIMPLE-BOOT-HTTP-SERVER
|
|
2
|
+
|
|
3
|
+
### A lightweight and powerful HTTP web server framework for Node.js.
|
|
4
|
+
 [](https://www.npmjs.com/package/simple-boot-http-server) [](LICENSE.md)
|
|
5
|
+
|
|
6
|
+
- **Declarative Routing**: Use decorators (`@Router`, `@Route`) to map URLs to classes and methods.
|
|
7
|
+
- **HTTP Method Mapping**: Decorators for all standard HTTP methods (`@GET`, `@POST`, `@PUT`, `@DELETE`, etc.).
|
|
8
|
+
- **Request/Response Handling**: A unified `RequestResponse` object to manage the HTTP transaction.
|
|
9
|
+
- **Middleware/Filters**: Intercept requests and responses for cross-cutting concerns like logging, authentication, or CORS.
|
|
10
|
+
- **Endpoints**: Define logic to be executed at different stages of the request lifecycle (e.g., on request start, close, or error).
|
|
11
|
+
- **Global Exception Handling**: Centralized error handling using `@Sim` advice classes.
|
|
12
|
+
- **Session Management**: Built-in session management with customizable storage providers.
|
|
13
|
+
- **HTTPS and HTTP/2 Support**: Configure the server to run over HTTPS.
|
|
14
|
+
|
|
15
|
+
### Dependencies
|
|
16
|
+
|
|
17
|
+
- **simple-boot**: The core dependency injection and application framework.
|
|
18
|
+
|
|
19
|
+
## 🚀 Quick Start
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
npm init -y
|
|
23
|
+
npm install @dooboostore/simple-boot @dooboostore/simple-boot-http-server reflect-metadata
|
|
24
|
+
tsc --init --experimentalDecorators --emitDecoratorMetadata
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// index.ts
|
|
29
|
+
import 'reflect-metadata';
|
|
30
|
+
import { SimpleBootHttpServer, HttpServerOption, RequestResponse, GET, Mimes } from '@dooboostore/simple-boot-http-server';
|
|
31
|
+
import { Sim, Router, Route, RouterModule } from '@dooboostore/simple-boot';
|
|
32
|
+
import { ReqHeader } from '@dooboostore/simple-boot-http-server/models/datas/ReqHeader';
|
|
33
|
+
|
|
34
|
+
@Sim
|
|
35
|
+
@Router({ path: '' })
|
|
36
|
+
export class AppRouter {
|
|
37
|
+
@Route({ path: '/' })
|
|
38
|
+
@GET({ res: { contentType: Mimes.ApplicationJson } })
|
|
39
|
+
index(rr: RequestResponse, header: ReqHeader, routerModule: RouterModule) {
|
|
40
|
+
console.log('Request from:', header['user-agent']);
|
|
41
|
+
return { message: 'Welcome to Simple Boot HTTP Server!' };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const httpServerOption = new HttpServerOption({
|
|
46
|
+
listen: {
|
|
47
|
+
port: 3000,
|
|
48
|
+
listeningListener: (server, httpServer) => {
|
|
49
|
+
const address = httpServer.address();
|
|
50
|
+
console.log(`Server is running on http://localhost:${address.port}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const app = new SimpleBootHttpServer(httpServerOption);
|
|
56
|
+
app.run();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```shell
|
|
60
|
+
# Run the server
|
|
61
|
+
npx ts-node index.ts
|
|
62
|
+
# Server is running on http://localhost:3000
|
|
63
|
+
|
|
64
|
+
# In another terminal
|
|
65
|
+
curl http://localhost:3000
|
|
66
|
+
# {"message":"Welcome to Simple Boot HTTP Server!"}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
# 😃 Examples
|
|
70
|
+
|
|
71
|
+
- [More examples](./examples)
|
|
72
|
+
|
|
73
|
+
## URL & Method Mapping
|
|
74
|
+
|
|
75
|
+
Simple Boot provides decorators for all standard HTTP methods to map incoming requests to your class methods. These are combined with `@Route` from `@dooboostore/simple-boot` to define endpoints.
|
|
76
|
+
|
|
77
|
+
### Available Method Decorators
|
|
78
|
+
|
|
79
|
+
- `@GET`
|
|
80
|
+
- `@POST`
|
|
81
|
+
- `@PUT`
|
|
82
|
+
- `@DELETE`
|
|
83
|
+
- `@PATCH`
|
|
84
|
+
- `@OPTIONS`
|
|
85
|
+
- `@HEAD`
|
|
86
|
+
- `@TRACE`
|
|
87
|
+
- `@CONNECT`
|
|
88
|
+
- `@UrlMapping`: A generic decorator where you can specify the method as a string.
|
|
89
|
+
|
|
90
|
+
### Example Usage
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { Sim, Router, Route, RouterModule } from '@dooboostore/simple-boot';
|
|
94
|
+
import {
|
|
95
|
+
GET, POST, PUT, DELETE,
|
|
96
|
+
Mimes,
|
|
97
|
+
RequestResponse,
|
|
98
|
+
ReqJsonBody
|
|
99
|
+
} from '@dooboostore/simple-boot-http-server';
|
|
100
|
+
|
|
101
|
+
@Sim
|
|
102
|
+
@Router({ path: '/api/items' })
|
|
103
|
+
export class ItemApi {
|
|
104
|
+
|
|
105
|
+
@Route({ path: '' })
|
|
106
|
+
@GET({ res: { contentType: Mimes.ApplicationJson } })
|
|
107
|
+
getAllItems() {
|
|
108
|
+
// Logic to get all items
|
|
109
|
+
return [{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@Route({ path: '/{id}' })
|
|
113
|
+
@GET({ res: { contentType: Mimes.ApplicationJson } })
|
|
114
|
+
getItemById(routerModule: RouterModule) {
|
|
115
|
+
const itemId = routerModule.pathData?.id;
|
|
116
|
+
// Logic to get item by ID
|
|
117
|
+
return { id: itemId, name: `Item ${itemId}` };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@Route({ path: '' })
|
|
121
|
+
@POST({
|
|
122
|
+
req: { contentType: [Mimes.ApplicationJson] },
|
|
123
|
+
res: { status: 201, contentType: Mimes.ApplicationJson }
|
|
124
|
+
})
|
|
125
|
+
createItem(body: ReqJsonBody) {
|
|
126
|
+
console.log('Creating new item:', body);
|
|
127
|
+
// Logic to create a new item
|
|
128
|
+
return { success: true, id: 3, ...body };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@Route({ path: '/{id}' })
|
|
132
|
+
@PUT({ req: { contentType: [Mimes.ApplicationJson] } })
|
|
133
|
+
updateItem(routerModule: RouterModule, body: ReqJsonBody) {
|
|
134
|
+
const itemId = routerModule.pathData?.id;
|
|
135
|
+
console.log(`Updating item ${itemId}:`, body);
|
|
136
|
+
// Logic to update an item
|
|
137
|
+
return { success: true, id: itemId, ...body };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@Route({ path: '/{id}' })
|
|
141
|
+
@DELETE({ res: { status: 204 } })
|
|
142
|
+
deleteItem(routerModule: RouterModule) {
|
|
143
|
+
const itemId = routerModule.pathData?.id;
|
|
144
|
+
console.log(`Deleting item ${itemId}`);
|
|
145
|
+
// Logic to delete an item
|
|
146
|
+
// No content returned for 204
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Decorator Options
|
|
152
|
+
|
|
153
|
+
The method decorators accept a `MappingConfig` object to control request and response properties.
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
export type MappingConfig = {
|
|
157
|
+
method: HttpMethod | string;
|
|
158
|
+
description?: { name?: string; detail?: string; };
|
|
159
|
+
req?: {
|
|
160
|
+
contentType?: (Mimes | string)[];
|
|
161
|
+
accept?: (Mimes | string)[];
|
|
162
|
+
};
|
|
163
|
+
res?: {
|
|
164
|
+
status?: number;
|
|
165
|
+
header?: { [key: string]: string };
|
|
166
|
+
contentType?: Mimes | string;
|
|
167
|
+
}
|
|
168
|
+
resolver?: Resolver | ConstructorType<Resolver>;
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Filters
|
|
173
|
+
|
|
174
|
+
Filters allow you to intercept the request-response cycle. The `before` method runs before the route handler, and `after` runs after. Returning `false` from `before` will stop the chain.
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { Filter, RequestResponse, SimpleBootHttpServer } from '@dooboostore/simple-boot-http-server';
|
|
178
|
+
|
|
179
|
+
export class LoggingFilter implements Filter {
|
|
180
|
+
async before(rr: RequestResponse, app: SimpleBootHttpServer): Promise<boolean> {
|
|
181
|
+
console.log(`[${new Date().toISOString()}] Received ${rr.reqMethod()} request for ${rr.reqUrl}`);
|
|
182
|
+
return true; // Continue the chain
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async after(rr: RequestResponse, app: SimpleBootHttpServer, sw: boolean): Promise<boolean> {
|
|
186
|
+
console.log(`Request finished with status ${rr.resStatusCode()}`);
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// In HttpServerOption
|
|
192
|
+
const option = new HttpServerOption({
|
|
193
|
+
filters: [LoggingFilter]
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Global Advice & Exception Handling
|
|
198
|
+
|
|
199
|
+
Define global exception handlers in an `Advice` class. This class is managed by `@Sim` and can catch errors thrown from anywhere in the application.
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { Sim, ExceptionHandler } from '@dooboostore/simple-boot';
|
|
203
|
+
import { RequestResponse, NotFoundError } from '@dooboostore/simple-boot-http-server';
|
|
204
|
+
|
|
205
|
+
@Sim
|
|
206
|
+
export class GlobalErrorHandler {
|
|
207
|
+
@ExceptionHandler({ type: NotFoundError })
|
|
208
|
+
handleNotFound(rr: RequestResponse, e: NotFoundError) {
|
|
209
|
+
rr.resStatusCode(404).resSetHeader('X-Error-Message', 'Resource not found');
|
|
210
|
+
console.error(`Not found error for URL: ${rr.reqUrl}`, e);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@ExceptionHandler()
|
|
214
|
+
handleAll(rr: RequestResponse, e: any) {
|
|
215
|
+
console.error('An unexpected error occurred:', e);
|
|
216
|
+
// Avoid sending detailed error in production
|
|
217
|
+
rr.resStatusCode(500).resWriteJson({ error: 'Internal Server Error' });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// In HttpServerOption
|
|
222
|
+
const option = new HttpServerOption({
|
|
223
|
+
globalAdvice: GlobalErrorHandler,
|
|
224
|
+
noSuchRouteEndPointMappingThrow: (rr) => new NotFoundError({ message: `No route for ${rr.reqUrl}` }),
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Endpoints
|
|
229
|
+
|
|
230
|
+
Endpoints are hooks that run at specific points in the request lifecycle.
|
|
231
|
+
|
|
232
|
+
- **`requestEndPoints`**: Run as soon as a request is received.
|
|
233
|
+
- **`closeEndPoints`**: Run when the client connection is closed.
|
|
234
|
+
- **`errorEndPoints`**: Run if an error occurs on the response stream.
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { EndPoint, RequestResponse, SimpleBootHttpServer } from '@dooboostore/simple-boot-http-server';
|
|
238
|
+
|
|
239
|
+
@Sim
|
|
240
|
+
class ConnectionLogger implements EndPoint {
|
|
241
|
+
async endPoint(rr: RequestResponse, app: SimpleBootHttpServer) {
|
|
242
|
+
console.log(`Connection closed for ${rr.reqRemoteAddress}`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// In HttpServerOption
|
|
247
|
+
const option = new HttpServerOption({
|
|
248
|
+
closeEndPoints: [ConnectionLogger]
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Session Management
|
|
253
|
+
|
|
254
|
+
The server has built-in session management. It automatically creates a session ID cookie and provides a `SessionManager` to store and retrieve session data.
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { RequestResponse } from '@dooboostore/simple-boot-http-server';
|
|
258
|
+
|
|
259
|
+
// In a route handler
|
|
260
|
+
async function handleSession(rr: RequestResponse) {
|
|
261
|
+
const session = await rr.reqSession();
|
|
262
|
+
|
|
263
|
+
let visitCount = session.visitCount || 0;
|
|
264
|
+
visitCount++;
|
|
265
|
+
session.visitCount = visitCount;
|
|
266
|
+
|
|
267
|
+
return { message: `You have visited ${visitCount} times.` };
|
|
268
|
+
}
|
|
269
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { SimpleApplication } from '@dooboostore/simple-boot/SimpleApplication';
|
|
4
|
+
import { HttpServerOption } from './option/HttpServerOption';
|
|
5
|
+
import { ConstructorType } from '@dooboostore/core/types';
|
|
6
|
+
import { Server as HttpServer } from 'http';
|
|
7
|
+
import { Server as HttpsServer } from 'https';
|
|
8
|
+
export declare class SimpleBootHttpServer extends SimpleApplication {
|
|
9
|
+
option: HttpServerOption;
|
|
10
|
+
server?: HttpServer | HttpsServer;
|
|
11
|
+
private sessionManager;
|
|
12
|
+
constructor(option?: HttpServerOption);
|
|
13
|
+
run(otherInstanceSim?: Map<ConstructorType<any>, any>): import("@dooboostore/simple-boot/simstance/SimstanceManager").SimstanceManager;
|
|
14
|
+
private startServer;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=SimpleBootHttpServer.d.ts.map
|
|
@@ -0,0 +1,313 @@
|
|
|
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 { SimpleApplication } from '@dooboostore/simple-boot/SimpleApplication';
|
|
11
|
+
import { HttpServerOption } from './option/HttpServerOption';
|
|
12
|
+
import { IncomingMessage, Server as HttpServer, ServerResponse } from 'http';
|
|
13
|
+
import { Server as HttpsServer } from 'https';
|
|
14
|
+
import { RequestResponse } from './models/RequestResponse';
|
|
15
|
+
import { getUrlMapping, getUrlMappings, UrlMappingSituationType } from './decorators/MethodMapping';
|
|
16
|
+
import { HttpStatus } from './codes/HttpStatus';
|
|
17
|
+
import { HttpHeaders } from './codes/HttpHeaders';
|
|
18
|
+
import { Mimes } from './codes/Mimes';
|
|
19
|
+
import { ExceptionHandlerSituationType, targetExceptionHandler } from '@dooboostore/simple-boot/decorators/exception/ExceptionDecorator';
|
|
20
|
+
import { getInject, SituationTypeContainer, SituationTypeContainers } from '@dooboostore/simple-boot/decorators/inject/Inject';
|
|
21
|
+
import { ReflectUtils } from '@dooboostore/simple-boot/utils/reflect/ReflectUtils';
|
|
22
|
+
import { ReqFormUrlBody } from './models/datas/body/ReqFormUrlBody';
|
|
23
|
+
import { ReqJsonBody } from './models/datas/body/ReqJsonBody';
|
|
24
|
+
import { ReqHeader } from './models/datas/ReqHeader';
|
|
25
|
+
import { RouterModule } from '@dooboostore/simple-boot/route/RouterModule';
|
|
26
|
+
import { ReqMultipartFormBody } from './models/datas/body/ReqMultipartFormBody';
|
|
27
|
+
import { execValidationInValid, getValidIndex } from '@dooboostore/simple-boot/decorators/validate/Validation';
|
|
28
|
+
import { ValidException } from '@dooboostore/simple-boot/errors/ValidException';
|
|
29
|
+
import { HttpError } from './errors/HttpError';
|
|
30
|
+
import { getRoute } from '@dooboostore/simple-boot/decorators/route/Router';
|
|
31
|
+
import { URLSearchParams } from 'url';
|
|
32
|
+
import { HttpMethod } from './codes/HttpMethod';
|
|
33
|
+
import { SessionManager } from './session/SessionManager';
|
|
34
|
+
import { InjectSituationType } from './inject/InjectSituationType';
|
|
35
|
+
export class SimpleBootHttpServer extends SimpleApplication {
|
|
36
|
+
constructor(option = new HttpServerOption()) {
|
|
37
|
+
super(option);
|
|
38
|
+
this.option = option;
|
|
39
|
+
this.sessionManager = new SessionManager(this.option);
|
|
40
|
+
}
|
|
41
|
+
run(otherInstanceSim) {
|
|
42
|
+
var _a, _b, _c, _d;
|
|
43
|
+
const simstanceManager = super.run(otherInstanceSim);
|
|
44
|
+
const targets = [...(_a = this.option.closeEndPoints) !== null && _a !== void 0 ? _a : [], ...(_b = this.option.errorEndPoints) !== null && _b !== void 0 ? _b : [], ...(_c = this.option.requestEndPoints) !== null && _c !== void 0 ? _c : [], ...(_d = this.option.filters) !== null && _d !== void 0 ? _d : []];
|
|
45
|
+
Promise.all(targets.map(it => (typeof it === 'function' ? this.simstanceManager.getOrNewSim({ target: it }) : it)).map(it => it.onInit(this))).then(it => {
|
|
46
|
+
this.startServer();
|
|
47
|
+
});
|
|
48
|
+
return simstanceManager;
|
|
49
|
+
}
|
|
50
|
+
startServer() {
|
|
51
|
+
const _super = Object.create(null, {
|
|
52
|
+
routing: { get: () => super.routing }
|
|
53
|
+
});
|
|
54
|
+
if (this.option.serverOption && 'key' in this.option.serverOption && 'cert' in this.option.serverOption) {
|
|
55
|
+
this.server = new HttpsServer(this.option.serverOption);
|
|
56
|
+
const httpServer = new HttpServer();
|
|
57
|
+
httpServer.on('request', (req, res) => {
|
|
58
|
+
res.writeHead(301, { Location: `https://${req.headers.host}${req.url}` });
|
|
59
|
+
res.end();
|
|
60
|
+
});
|
|
61
|
+
httpServer.listen(80, this.option.listen.hostname, () => {
|
|
62
|
+
console.log('HTTP redirect server running on port 80');
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
else if (this.option.serverOption) {
|
|
66
|
+
this.server = new HttpServer(this.option.serverOption);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
this.server = new HttpServer();
|
|
70
|
+
}
|
|
71
|
+
this.server.on('request', (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
|
|
73
|
+
const transactionManager = this.option.transactionManagerFactory ? yield this.option.transactionManagerFactory() : undefined;
|
|
74
|
+
res.on('close', () => __awaiter(this, void 0, void 0, function* () {
|
|
75
|
+
if (this.option.closeEndPoints) {
|
|
76
|
+
for (const it of this.option.closeEndPoints) {
|
|
77
|
+
try {
|
|
78
|
+
const execute = (typeof it === 'function' ? this.simstanceManager.getOrNewSim({ target: it }) : it);
|
|
79
|
+
const endPoint = execute === null || execute === void 0 ? void 0 : execute.endPoint(rr, this);
|
|
80
|
+
if (endPoint instanceof Promise) {
|
|
81
|
+
yield endPoint;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (!rr.resIsDone()) {
|
|
89
|
+
rr.resEnd();
|
|
90
|
+
}
|
|
91
|
+
}));
|
|
92
|
+
res.on('error', () => __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
if (this.option.errorEndPoints) {
|
|
94
|
+
for (const it of this.option.errorEndPoints) {
|
|
95
|
+
try {
|
|
96
|
+
const execute = (typeof it === 'function' ? this.simstanceManager.getOrNewSim({ target: it }) : it);
|
|
97
|
+
const endPoint = execute === null || execute === void 0 ? void 0 : execute.endPoint(rr, this);
|
|
98
|
+
if (endPoint instanceof Promise) {
|
|
99
|
+
yield endPoint;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!rr.resIsDone()) {
|
|
107
|
+
rr.resEnd();
|
|
108
|
+
}
|
|
109
|
+
}));
|
|
110
|
+
const rr = new RequestResponse(req, res, { sessionManager: this.sessionManager, option: this.option });
|
|
111
|
+
rr.resSetHeader(HttpHeaders.Server, 'simple-boot-http-server');
|
|
112
|
+
const cookie = rr.reqCookieGet(this.option.sessionOption.key);
|
|
113
|
+
if (!cookie) {
|
|
114
|
+
const session = yield this.sessionManager.session();
|
|
115
|
+
rr.resSetHeader(HttpHeaders.SetCookie, `${this.option.sessionOption.key}=${session.uuid}; Path=/; HttpOnly`);
|
|
116
|
+
}
|
|
117
|
+
const otherStorage = new Map();
|
|
118
|
+
otherStorage.set(RequestResponse, rr);
|
|
119
|
+
otherStorage.set(IncomingMessage, req);
|
|
120
|
+
otherStorage.set(ServerResponse, res);
|
|
121
|
+
try {
|
|
122
|
+
transactionManager === null || transactionManager === void 0 ? void 0 : transactionManager.try();
|
|
123
|
+
if (this.option.requestEndPoints) {
|
|
124
|
+
for (const it of this.option.requestEndPoints) {
|
|
125
|
+
try {
|
|
126
|
+
const execute = (typeof it === 'function' ? this.simstanceManager.getOrNewSim({ target: it }) : it);
|
|
127
|
+
execute === null || execute === void 0 ? void 0 : execute.endPoint(rr, this);
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const filter = {
|
|
134
|
+
carrier: new Map(),
|
|
135
|
+
filters: []
|
|
136
|
+
};
|
|
137
|
+
for (let i = 0; this.option.filters && i < this.option.filters.length; i++) {
|
|
138
|
+
const it = this.option.filters[i];
|
|
139
|
+
const execute = (typeof it === 'function' ? this.simstanceManager.getOrNewSim({ target: it }) : it);
|
|
140
|
+
let sw = true;
|
|
141
|
+
if (execute === null || execute === void 0 ? void 0 : execute.proceedBefore) {
|
|
142
|
+
sw = yield execute.proceedBefore({ rr, app: this, carrier: filter.carrier });
|
|
143
|
+
filter.filters.push({ filter: execute, sw });
|
|
144
|
+
}
|
|
145
|
+
if (!sw) {
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (!rr.resIsDone()) {
|
|
150
|
+
const routerModule = yield _super.routing.call(this, rr.reqIntent);
|
|
151
|
+
otherStorage.set(RouterModule, routerModule);
|
|
152
|
+
const moduleInstance = (_a = routerModule === null || routerModule === void 0 ? void 0 : routerModule.getModuleInstance) === null || _a === void 0 ? void 0 : _a.call(routerModule);
|
|
153
|
+
let methods = [];
|
|
154
|
+
if (routerModule && moduleInstance) {
|
|
155
|
+
if (routerModule.propertyKeys) {
|
|
156
|
+
const map = (_b = routerModule.propertyKeys) === null || _b === void 0 ? void 0 : _b.map((it) => {
|
|
157
|
+
return { propertyKey: it, config: getUrlMapping(moduleInstance, it) };
|
|
158
|
+
});
|
|
159
|
+
methods.push(...(map !== null && map !== void 0 ? map : []));
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
methods.push(...((_c = getUrlMappings(moduleInstance).filter(it => !getRoute(moduleInstance, it.propertyKey))) !== null && _c !== void 0 ? _c : []));
|
|
163
|
+
}
|
|
164
|
+
if (((_d = rr.reqMethod()) === null || _d === void 0 ? void 0 : _d.toUpperCase()) === HttpMethod.OPTIONS.toUpperCase()) {
|
|
165
|
+
rr.resSetHeader(HttpHeaders.Allow, methods.map(it => it.config.method).join(', '));
|
|
166
|
+
rr.resStatusCode(HttpStatus.Ok);
|
|
167
|
+
}
|
|
168
|
+
methods = methods.filter(it => { var _a; return it && it.propertyKey && it.config && ((_a = rr.reqMethod()) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === it.config.method.toUpperCase(); });
|
|
169
|
+
methods.sort((a, b) => {
|
|
170
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
171
|
+
return (((_d = (_c = (_b = (_a = b.config) === null || _a === void 0 ? void 0 : _a.req) === null || _b === void 0 ? void 0 : _b.contentType) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) + ((_h = (_g = (_f = (_e = b.config) === null || _e === void 0 ? void 0 : _e.req) === null || _f === void 0 ? void 0 : _f.accept) === null || _g === void 0 ? void 0 : _g.length) !== null && _h !== void 0 ? _h : 0)) - (((_m = (_l = (_k = (_j = a.config) === null || _j === void 0 ? void 0 : _j.req) === null || _k === void 0 ? void 0 : _k.contentType) === null || _l === void 0 ? void 0 : _l.length) !== null && _m !== void 0 ? _m : 0) + ((_r = (_q = (_p = (_o = a.config) === null || _o === void 0 ? void 0 : _o.req) === null || _p === void 0 ? void 0 : _p.accept) === null || _q === void 0 ? void 0 : _q.length) !== null && _r !== void 0 ? _r : 0));
|
|
172
|
+
});
|
|
173
|
+
methods = methods
|
|
174
|
+
.filter(it => { var _a, _b, _c, _d, _e; return ((_b = (_a = it.config) === null || _a === void 0 ? void 0 : _a.req) === null || _b === void 0 ? void 0 : _b.contentType) ? (!!((_e = (_d = (_c = it.config) === null || _c === void 0 ? void 0 : _c.req) === null || _d === void 0 ? void 0 : _d.contentType) === null || _e === void 0 ? void 0 : _e.find(sit => rr.reqHasContentTypeHeader(sit)))) : true; })
|
|
175
|
+
.filter(it => { var _a, _b, _c, _d, _e; return ((_b = (_a = it.config) === null || _a === void 0 ? void 0 : _a.req) === null || _b === void 0 ? void 0 : _b.accept) ? (!!((_e = (_d = (_c = it.config) === null || _c === void 0 ? void 0 : _c.req) === null || _d === void 0 ? void 0 : _d.accept) === null || _e === void 0 ? void 0 : _e.find(sit => rr.reqHasAcceptHeader(sit)))) : true; });
|
|
176
|
+
if (methods[0]) {
|
|
177
|
+
const it = methods[0];
|
|
178
|
+
const paramTypes = ReflectUtils.getParameterTypes(moduleInstance, it.propertyKey);
|
|
179
|
+
const injects = getInject(moduleInstance, it.propertyKey);
|
|
180
|
+
const validIndexs = getValidIndex(moduleInstance, it.propertyKey);
|
|
181
|
+
if (injects) {
|
|
182
|
+
const isJson = injects.find(it => { var _a; return ((_a = it.config) === null || _a === void 0 ? void 0 : _a.situationType) === UrlMappingSituationType.REQ_JSON_BODY; });
|
|
183
|
+
const isFormUrl = injects.find(it => { var _a; return ((_a = it.config) === null || _a === void 0 ? void 0 : _a.situationType) === UrlMappingSituationType.REQ_FORM_URL_BODY; });
|
|
184
|
+
const isTransactionManager = injects.find(it => { var _a; return ((_a = it.config) === null || _a === void 0 ? void 0 : _a.situationType) === InjectSituationType.TransactionManager; });
|
|
185
|
+
const siturationContainers = new SituationTypeContainers();
|
|
186
|
+
if (isJson) {
|
|
187
|
+
let data = yield rr.reqBodyJsonData();
|
|
188
|
+
if (isJson.type) {
|
|
189
|
+
data = Object.assign(new isJson.type(), data);
|
|
190
|
+
}
|
|
191
|
+
if (validIndexs.includes(isJson.index)) {
|
|
192
|
+
const inValid = execValidationInValid(data);
|
|
193
|
+
if (((_e = inValid === null || inValid === void 0 ? void 0 : inValid.length) !== null && _e !== void 0 ? _e : 0) > 0) {
|
|
194
|
+
throw new ValidException(inValid);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
siturationContainers.push(new SituationTypeContainer({
|
|
198
|
+
situationType: UrlMappingSituationType.REQ_JSON_BODY,
|
|
199
|
+
data
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
if (isFormUrl) {
|
|
203
|
+
let data = yield rr.reqBodyFormUrlData();
|
|
204
|
+
if (isFormUrl.type) {
|
|
205
|
+
data = Object.assign(new isFormUrl.type(), data);
|
|
206
|
+
}
|
|
207
|
+
if (validIndexs.includes(isFormUrl.index)) {
|
|
208
|
+
const inValid = execValidationInValid(data);
|
|
209
|
+
if (((_f = inValid === null || inValid === void 0 ? void 0 : inValid.length) !== null && _f !== void 0 ? _f : 0) > 0) {
|
|
210
|
+
throw new ValidException(inValid);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
siturationContainers.push(new SituationTypeContainer({ situationType: UrlMappingSituationType.REQ_FORM_URL_BODY, data }));
|
|
214
|
+
}
|
|
215
|
+
if (isTransactionManager && isTransactionManager.type && transactionManager && transactionManager.hasTransaction(isTransactionManager.type)) {
|
|
216
|
+
let data = yield transactionManager.getTransaction(isTransactionManager.type);
|
|
217
|
+
if (data) {
|
|
218
|
+
data = yield data.try(isTransactionManager.config.argument);
|
|
219
|
+
siturationContainers.push(new SituationTypeContainer({ situationType: InjectSituationType.TransactionManager, data, index: isTransactionManager.index }));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (siturationContainers.length) {
|
|
223
|
+
otherStorage.set(SituationTypeContainers, siturationContainers);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
for (const paramType of paramTypes) {
|
|
227
|
+
if (paramType === ReqFormUrlBody) {
|
|
228
|
+
otherStorage.set(ReqFormUrlBody, yield rr.reqBodyReqFormUrlBody());
|
|
229
|
+
}
|
|
230
|
+
else if (paramType === ReqJsonBody) {
|
|
231
|
+
otherStorage.set(ReqJsonBody, yield rr.reqBodyReqJsonBody());
|
|
232
|
+
}
|
|
233
|
+
else if (paramType === URLSearchParams) {
|
|
234
|
+
otherStorage.set(URLSearchParams, rr.reqUrlSearchParams);
|
|
235
|
+
}
|
|
236
|
+
else if (paramType === ReqMultipartFormBody) {
|
|
237
|
+
otherStorage.set(ReqMultipartFormBody, rr.reqBodyMultipartFormData());
|
|
238
|
+
}
|
|
239
|
+
else if (paramType === ReqHeader) {
|
|
240
|
+
otherStorage.set(ReqHeader, rr.reqHeaderObj);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
let data = yield this.simstanceManager.executeBindParameterSimPromise({
|
|
244
|
+
target: moduleInstance,
|
|
245
|
+
targetKey: it.propertyKey
|
|
246
|
+
}, otherStorage);
|
|
247
|
+
if ((_g = it.config) === null || _g === void 0 ? void 0 : _g.resolver) {
|
|
248
|
+
const execute = typeof it.config.resolver === 'function' ? this.simstanceManager.getOrNewSim({ target: it.config.resolver }) : it.config.resolver;
|
|
249
|
+
data = yield ((_h = execute === null || execute === void 0 ? void 0 : execute.resolve) === null || _h === void 0 ? void 0 : _h.call(execute, data, rr));
|
|
250
|
+
}
|
|
251
|
+
const status = (_l = (_k = (_j = it.config) === null || _j === void 0 ? void 0 : _j.res) === null || _k === void 0 ? void 0 : _k.status) !== null && _l !== void 0 ? _l : HttpStatus.Ok;
|
|
252
|
+
const headers = (_p = (_o = (_m = it.config) === null || _m === void 0 ? void 0 : _m.res) === null || _o === void 0 ? void 0 : _o.header) !== null && _p !== void 0 ? _p : {};
|
|
253
|
+
if ((_r = (_q = it.config) === null || _q === void 0 ? void 0 : _q.res) === null || _r === void 0 ? void 0 : _r.contentType) {
|
|
254
|
+
headers[HttpHeaders.ContentType] = (_t = (_s = it.config) === null || _s === void 0 ? void 0 : _s.res) === null || _t === void 0 ? void 0 : _t.contentType;
|
|
255
|
+
}
|
|
256
|
+
if (((_x = (_w = (_v = (_u = it.config) === null || _u === void 0 ? void 0 : _u.res) === null || _v === void 0 ? void 0 : _v.contentType) === null || _w === void 0 ? void 0 : _w.toLowerCase().indexOf(Mimes.ApplicationJson.toLowerCase())) !== null && _x !== void 0 ? _x : -1) > -1) {
|
|
257
|
+
data = JSON.stringify(data);
|
|
258
|
+
}
|
|
259
|
+
else if (data && typeof data === 'object') {
|
|
260
|
+
data = JSON.stringify(data);
|
|
261
|
+
}
|
|
262
|
+
rr.resSetHeaders(headers);
|
|
263
|
+
rr.resSetStatusCode(status);
|
|
264
|
+
rr.resWrite(data);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (this.option.noSuchRouteEndPointMappingThrow && methods.length <= 0 && ((_y = rr.reqMethod()) === null || _y === void 0 ? void 0 : _y.toUpperCase()) !== HttpMethod.OPTIONS) {
|
|
268
|
+
throw this.option.noSuchRouteEndPointMappingThrow(rr);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
for (const it of filter.filters.reverse()) {
|
|
272
|
+
if (((_z = it.filter) === null || _z === void 0 ? void 0 : _z.proceedAfter) && !(yield it.filter.proceedAfter({ rr, app: this, before: it.sw, carrier: filter.carrier }))) {
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
catch (e) {
|
|
278
|
+
transactionManager === null || transactionManager === void 0 ? void 0 : transactionManager.catch(e);
|
|
279
|
+
rr.resStatusCode(e instanceof HttpError ? e.status : HttpStatus.InternalServerError);
|
|
280
|
+
const execute = typeof this.option.globalAdvice === 'function' ? this.simstanceManager.getOrNewSim(this.option.globalAdvice) : this.option.globalAdvice;
|
|
281
|
+
if (!execute) {
|
|
282
|
+
rr.resEnd();
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
if (e && typeof e === 'object') {
|
|
286
|
+
otherStorage.set(e.constructor, e);
|
|
287
|
+
otherStorage.set(SituationTypeContainer, new SituationTypeContainer({
|
|
288
|
+
situationType: ExceptionHandlerSituationType.ERROR_OBJECT,
|
|
289
|
+
data: e
|
|
290
|
+
}));
|
|
291
|
+
}
|
|
292
|
+
const target = targetExceptionHandler(execute, e);
|
|
293
|
+
if (target) {
|
|
294
|
+
yield this.simstanceManager.executeBindParameterSimPromise({
|
|
295
|
+
target: execute,
|
|
296
|
+
targetKey: target.propertyKey
|
|
297
|
+
}, otherStorage);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
finally {
|
|
301
|
+
transactionManager === null || transactionManager === void 0 ? void 0 : transactionManager.finally();
|
|
302
|
+
}
|
|
303
|
+
if (!rr.resIsDone()) {
|
|
304
|
+
rr.resEnd();
|
|
305
|
+
}
|
|
306
|
+
}));
|
|
307
|
+
this.server.listen(this.option.listen.port, this.option.listen.hostname, this.option.listen.backlog, () => {
|
|
308
|
+
var _a, _b;
|
|
309
|
+
(_b = (_a = this.option.listen).listeningListener) === null || _b === void 0 ? void 0 : _b.call(_a, this, this.server);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=SimpleBootHttpServer.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export declare enum HttpHeaders {
|
|
2
|
+
ContentLength = "Content-Length",
|
|
3
|
+
ContentType = "Content-Type",
|
|
4
|
+
ContentEncoding = "Content-Encoding",
|
|
5
|
+
Accept = "Accept",
|
|
6
|
+
Authorization = "Authorization",
|
|
7
|
+
CacheControl = "Cache-Control",
|
|
8
|
+
Connection = "Connection",
|
|
9
|
+
Date = "Date",
|
|
10
|
+
Host = "Host",
|
|
11
|
+
Pragma = "Pragma",
|
|
12
|
+
Trailer = "Trailer",
|
|
13
|
+
TransferEncoding = "Transfer-Encoding",
|
|
14
|
+
Upgrade = "Upgrade",
|
|
15
|
+
Via = "Via",
|
|
16
|
+
Warning = "Warning",
|
|
17
|
+
AcceptCharset = "Accept-Charset",
|
|
18
|
+
AcceptEncoding = "Accept-Encoding",
|
|
19
|
+
AcceptLanguage = "Accept-Language",
|
|
20
|
+
AccessControlAllowOrigin = "Access-Control-Allow-Origin",
|
|
21
|
+
AccessControlAllowMethods = "Access-Control-Allow-Methods",
|
|
22
|
+
AccessControlAllowHeaders = "Access-Control-Allow-Headers",
|
|
23
|
+
AccessControlExposeHeaders = "Access-Control-Expose-Headers",
|
|
24
|
+
Expect = "Expect",
|
|
25
|
+
From = "From",
|
|
26
|
+
MaxForwards = "Max-Forwards",
|
|
27
|
+
Referer = "Referer",
|
|
28
|
+
UserAgent = "User-Agent",
|
|
29
|
+
Cookie = "Cookie",
|
|
30
|
+
SetCookie = "Set-Cookie",
|
|
31
|
+
Cookie2 = "Cookie2",
|
|
32
|
+
SetCookie2 = "Set-Cookie2",
|
|
33
|
+
Location = "Location",
|
|
34
|
+
IfModifiedSince = "If-Modified-Since",
|
|
35
|
+
IfUnmodifiedSince = "If-Unmodified-Since",
|
|
36
|
+
IfMatch = "If-Match",
|
|
37
|
+
IfNoneMatch = "If-None-Match",
|
|
38
|
+
IfRange = "If-Range",
|
|
39
|
+
Allow = "Allow",
|
|
40
|
+
Server = "Server"
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=HttpHeaders.d.ts.map
|