@alwatr/nanotron-api-server 4.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +418 -0
- package/LICENSE +21 -0
- package/README.md +140 -0
- package/dist/api-connection.d.ts +36 -0
- package/dist/api-connection.d.ts.map +1 -0
- package/dist/api-server.d.ts +109 -0
- package/dist/api-server.d.ts.map +1 -0
- package/dist/const.d.ts +375 -0
- package/dist/const.d.ts.map +1 -0
- package/dist/main.cjs +5 -0
- package/dist/main.cjs.map +7 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.mjs +5 -0
- package/dist/main.mjs.map +7 -0
- package/dist/type.d.ts +144 -0
- package/dist/type.d.ts.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { NanotronApiConnection } from './api-connection.js';
|
|
3
|
+
import type { HttpMethod, MatchType, RouteHandler } from './type.js';
|
|
4
|
+
import type { Dictionary } from '@alwatr/type-helper';
|
|
5
|
+
import type { Duplex } from 'node:stream';
|
|
6
|
+
/**
|
|
7
|
+
* Configuration options for the NanotronApiServer.
|
|
8
|
+
*/
|
|
9
|
+
export interface NanotronApiServerConfig {
|
|
10
|
+
/**
|
|
11
|
+
* The port number to listen on.
|
|
12
|
+
*
|
|
13
|
+
* @default 80
|
|
14
|
+
*/
|
|
15
|
+
port?: number;
|
|
16
|
+
/**
|
|
17
|
+
* The hostname to listen on.
|
|
18
|
+
*
|
|
19
|
+
* @default '0.0.0.0'
|
|
20
|
+
*/
|
|
21
|
+
host?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Sets the timeout (ms) for receiving the entire request from the client.
|
|
24
|
+
*
|
|
25
|
+
* @default 10_000 ms
|
|
26
|
+
*/
|
|
27
|
+
requestTimeout?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Sets the timeout (ms) for receiving the complete HTTP headers from the client.
|
|
30
|
+
*
|
|
31
|
+
* This should be bigger than `keepAliveTimeout + your server's expected response time`.
|
|
32
|
+
*
|
|
33
|
+
* @default 130_000 ms
|
|
34
|
+
*/
|
|
35
|
+
headersTimeout?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Sets the timeout (ms) for receiving the complete HTTP headers from the client.
|
|
38
|
+
*
|
|
39
|
+
* @default 120_000 ms
|
|
40
|
+
*/
|
|
41
|
+
keepAliveTimeout?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Add /health route.
|
|
44
|
+
*
|
|
45
|
+
* @default true
|
|
46
|
+
*/
|
|
47
|
+
healthRoute?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Add OPTIONS route for preflight requests to allow access all origins.
|
|
50
|
+
*
|
|
51
|
+
* @default false
|
|
52
|
+
*/
|
|
53
|
+
allowAllOrigin?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* A prefix to be added to the beginning of the `url` of all defined routes.
|
|
56
|
+
*
|
|
57
|
+
* @default '/api/'
|
|
58
|
+
*/
|
|
59
|
+
prefix?: `/${string}/` | '/';
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Configuration options for defining a route.
|
|
63
|
+
*/
|
|
64
|
+
export interface DefineRouteOption {
|
|
65
|
+
/**
|
|
66
|
+
* The HTTP method for this route.
|
|
67
|
+
*/
|
|
68
|
+
method: HttpMethod;
|
|
69
|
+
/**
|
|
70
|
+
* The URL path for this route.
|
|
71
|
+
*/
|
|
72
|
+
url: string;
|
|
73
|
+
/**
|
|
74
|
+
* The function to handle requests to this route.
|
|
75
|
+
*/
|
|
76
|
+
handler: RouteHandler;
|
|
77
|
+
/**
|
|
78
|
+
* Specifies how the `url` should be matched against incoming requests.
|
|
79
|
+
*
|
|
80
|
+
* @default 'exact'
|
|
81
|
+
*/
|
|
82
|
+
matchType?: MatchType;
|
|
83
|
+
}
|
|
84
|
+
export declare class NanotronApiServer {
|
|
85
|
+
protected static readonly defaultConfig_: Readonly<Required<NanotronApiServerConfig>>;
|
|
86
|
+
protected readonly config_: {
|
|
87
|
+
port: number;
|
|
88
|
+
host: string;
|
|
89
|
+
requestTimeout: number;
|
|
90
|
+
headersTimeout: number;
|
|
91
|
+
keepAliveTimeout: number;
|
|
92
|
+
healthRoute: boolean;
|
|
93
|
+
allowAllOrigin: boolean;
|
|
94
|
+
prefix: `/${string}/` | "/";
|
|
95
|
+
};
|
|
96
|
+
protected readonly logger_: import("@alwatr/logger").AlwatrLogger;
|
|
97
|
+
readonly httpServer: import("http").Server<typeof IncomingMessage, typeof ServerResponse>;
|
|
98
|
+
protected readonly routeHandlerList__: Record<MatchType, Dictionary<Dictionary<Required<DefineRouteOption>>>>;
|
|
99
|
+
constructor(config?: Partial<NanotronApiServerConfig>);
|
|
100
|
+
close(): void;
|
|
101
|
+
protected getRouteOption_(option: Required<Pick<DefineRouteOption, 'method' | 'url'>>): Required<DefineRouteOption> | null;
|
|
102
|
+
protected setRouteOption_(option: Required<DefineRouteOption>): void;
|
|
103
|
+
defineRoute(option: DefineRouteOption): void;
|
|
104
|
+
protected handleServerError_(err: NodeJS.ErrnoException): void;
|
|
105
|
+
protected handleClientError_(err: NodeJS.ErrnoException, socket: Duplex): void;
|
|
106
|
+
protected handleHttpError_(connection: NanotronApiConnection, error?: unknown): void;
|
|
107
|
+
protected handleIncomingRequest_(incomingMessage: IncomingMessage, serverResponse: ServerResponse): Promise<void>;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=api-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-server.d.ts","sourceRoot":"","sources":["../src/api-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,eAAe,EAAE,cAAc,EAAC,MAAM,WAAW,CAAC;AAIxE,OAAO,EAAC,qBAAqB,EAAC,MAAM,qBAAqB,CAAC;AAG1D,OAAO,KAAK,EAAC,UAAU,EAAE,SAAS,EAAE,YAAY,EAAC,MAAM,WAAW,CAAC;AACnE,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,MAAM,EAAE,UAAU,CAAC;IAEnB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC;IAEtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,qBAAa,iBAAiB;IAC5B,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CASnF;IAEF,SAAS,CAAC,QAAQ,CAAC,OAAO;cA7FnB,MAAM;cAON,MAAM;wBAOI,MAAM;wBASN,MAAM;0BAOJ,MAAM;qBAOX,OAAO;wBAOJ,OAAO;gBAOf,IAAI,MAAM,GAAG,GAAG,GAAG;MA0CD;IAC3B,SAAS,CAAC,QAAQ,CAAC,OAAO,wCAAC;IAE3B,QAAQ,CAAC,UAAU,uEAAC;IAEpB,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;gBAElG,MAAM,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC;IA+CrD,KAAK,IAAI,IAAI;IAKb,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC,GAAG,QAAQ,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAuB1H,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAepE,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAS5C,SAAS,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,GAAG,IAAI;IAS9D,SAAS,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAQ9E,SAAS,CAAC,gBAAgB,CAAC,UAAU,EAAE,qBAAqB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI;cAMpE,sBAAsB,CAAC,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAyCxH"}
|
package/dist/const.d.ts
ADDED
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object representing standard HTTP methods.
|
|
3
|
+
*/
|
|
4
|
+
export declare const HttpMethods: {
|
|
5
|
+
/**
|
|
6
|
+
* GET: Requests a representation of the specified resource.
|
|
7
|
+
*/
|
|
8
|
+
readonly GET: "GET";
|
|
9
|
+
/**
|
|
10
|
+
* HEAD: Asks for a response identical to that of a GET request, but without the response body.
|
|
11
|
+
*/
|
|
12
|
+
readonly HEAD: "HEAD";
|
|
13
|
+
/**
|
|
14
|
+
* POST: Submits data to be processed (e.g., from an HTML form) to the identified resource.
|
|
15
|
+
*/
|
|
16
|
+
readonly POST: "POST";
|
|
17
|
+
/**
|
|
18
|
+
* PUT: Uploads a representation of the specified URI.
|
|
19
|
+
*/
|
|
20
|
+
readonly PUT: "PUT";
|
|
21
|
+
/**
|
|
22
|
+
* DELETE: Deletes the specified resource.
|
|
23
|
+
*/
|
|
24
|
+
readonly DELETE: "DELETE";
|
|
25
|
+
/**
|
|
26
|
+
* CONNECT: Establishes a tunnel to the server identified by the target resource.
|
|
27
|
+
*/
|
|
28
|
+
readonly CONNECT: "CONNECT";
|
|
29
|
+
/**
|
|
30
|
+
* OPTIONS: Describes the communication options for the target resource.
|
|
31
|
+
*/
|
|
32
|
+
readonly OPTIONS: "OPTIONS";
|
|
33
|
+
/**
|
|
34
|
+
* TRACE: Performs a message loop-back test along the path to the target resource.
|
|
35
|
+
*/
|
|
36
|
+
readonly TRACE: "TRACE";
|
|
37
|
+
/**
|
|
38
|
+
* PATCH: Applies partial modifications to a resource.
|
|
39
|
+
*/
|
|
40
|
+
readonly PATCH: "PATCH";
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Object representing standard HTTP status codes.
|
|
44
|
+
*/
|
|
45
|
+
export declare const HttpStatusCodes: {
|
|
46
|
+
/**
|
|
47
|
+
* 100 Continue: The server has received the request headers and the client should proceed to send the request body.
|
|
48
|
+
*/
|
|
49
|
+
readonly Info_100_Continue: 100;
|
|
50
|
+
/**
|
|
51
|
+
* 101 Switching Protocols: The server understands and is willing to comply with the clients request to switch protocols.
|
|
52
|
+
*/
|
|
53
|
+
readonly Info_101_Switching_Protocols: 101;
|
|
54
|
+
/**
|
|
55
|
+
* 102 Processing: The server has received and is processing the request, but no response is available yet.
|
|
56
|
+
*/
|
|
57
|
+
readonly Info_102_Processing: 102;
|
|
58
|
+
/**
|
|
59
|
+
* 103 Early Hints: The server is sending some response headers before the final HTTP message.
|
|
60
|
+
*/
|
|
61
|
+
readonly Info_103_Early_Hints: 103;
|
|
62
|
+
/**
|
|
63
|
+
* 200 OK: The request has succeeded.
|
|
64
|
+
*/
|
|
65
|
+
readonly Success_200_OK: 200;
|
|
66
|
+
/**
|
|
67
|
+
* 201 Created: The request has been fulfilled and resulted in a new resource being created.
|
|
68
|
+
*/
|
|
69
|
+
readonly Success_201_Created: 201;
|
|
70
|
+
/**
|
|
71
|
+
* 202 Accepted: The request has been accepted for processing, but the processing has not been completed.
|
|
72
|
+
*/
|
|
73
|
+
readonly Success_202_Accepted: 202;
|
|
74
|
+
/**
|
|
75
|
+
* 203 Non-Authoritative Information: The server is a transforming proxy that received a 200 OK
|
|
76
|
+
* from the origin server but is returning a modified version of the origins response.
|
|
77
|
+
*/
|
|
78
|
+
readonly Success_203_Non_Authoritative_Information: 203;
|
|
79
|
+
/**
|
|
80
|
+
* 204 No Content: The server successfully processed the request and is not returning any content.
|
|
81
|
+
*/
|
|
82
|
+
readonly Success_204_No_Content: 204;
|
|
83
|
+
/**
|
|
84
|
+
* 205 Reset Content: The server successfully processed the request,
|
|
85
|
+
* asks that the client reset its document view, and is not returning any content.
|
|
86
|
+
*/
|
|
87
|
+
readonly Success_205_Reset_Content: 205;
|
|
88
|
+
/**
|
|
89
|
+
* 206 Partial Content: The server is delivering only part of the resource due to a range header sent by the client.
|
|
90
|
+
*/
|
|
91
|
+
readonly Success_206_Partial_Content: 206;
|
|
92
|
+
/**
|
|
93
|
+
* 207 Multi-Status: The message body that follows is an XML message
|
|
94
|
+
* and can contain a number of separate response codes, depending on how many sub-requests were made.
|
|
95
|
+
*/
|
|
96
|
+
readonly Success_207_Multi_Status: 207;
|
|
97
|
+
/**
|
|
98
|
+
* 208 Already Reported: The members of a DAV binding have already been enumerated
|
|
99
|
+
* in a preceding part of the (multi-status) response, and are not being included again.
|
|
100
|
+
*/
|
|
101
|
+
readonly Success_208_Already_Reported: 208;
|
|
102
|
+
/**
|
|
103
|
+
* 226 IM Used: The server has fulfilled a request for the resource, and the response is a representation
|
|
104
|
+
* of the result of one or more instance-manipulations applied to the current instance.
|
|
105
|
+
*/
|
|
106
|
+
readonly Success_226_IM_Used: 226;
|
|
107
|
+
/**
|
|
108
|
+
* 300 Multiple Choices: The request has more than one possible response.
|
|
109
|
+
*/
|
|
110
|
+
readonly Redirect_300_Multiple_Choices: 300;
|
|
111
|
+
/**
|
|
112
|
+
* 301 Moved Permanently: The URL of the requested resource has been changed permanently.
|
|
113
|
+
*/
|
|
114
|
+
readonly Redirect_301_Moved_Permanently: 301;
|
|
115
|
+
/**
|
|
116
|
+
* 302 Found: The URL of the requested resource has been changed temporarily.
|
|
117
|
+
*/
|
|
118
|
+
readonly Redirect_302_Found: 302;
|
|
119
|
+
/**
|
|
120
|
+
* 303 See Other: The response to the request can be found under another URI using a GET method.
|
|
121
|
+
*/
|
|
122
|
+
readonly Redirect_303_See_Other: 303;
|
|
123
|
+
/**
|
|
124
|
+
* 304 Not Modified: The resource has not been modified since the version specified
|
|
125
|
+
* by the request headers If-Modified-Since or If-None-Match.
|
|
126
|
+
*/
|
|
127
|
+
readonly Redirect_304_Not_Modified: 304;
|
|
128
|
+
/**
|
|
129
|
+
* 305 Use Proxy: The requested resource is only available through a proxy, the address for which is provided in the response.
|
|
130
|
+
*/
|
|
131
|
+
readonly Redirect_305_Use_Proxy: 305;
|
|
132
|
+
/**
|
|
133
|
+
* 306 Switch Proxy: No longer used. Originally meant "Subsequent requests should use the specified proxy."
|
|
134
|
+
*/
|
|
135
|
+
readonly Redirect_306_Switch_Proxy: 306;
|
|
136
|
+
/**
|
|
137
|
+
* 307 Temporary Redirect: The server sends this response to direct the client
|
|
138
|
+
* to get the requested resource at another URI with the same method that was used in the prior request.
|
|
139
|
+
*/
|
|
140
|
+
readonly Redirect_307_Temporary_Redirect: 307;
|
|
141
|
+
/**
|
|
142
|
+
* 308 Permanent Redirect: This means that the resource is now permanently located at another URI,
|
|
143
|
+
* specified by the Location: HTTP Response header.
|
|
144
|
+
*/
|
|
145
|
+
readonly Redirect_308_Permanent_Redirect: 308;
|
|
146
|
+
/**
|
|
147
|
+
* 400 Bad Request: The server cannot or will not process the request due to something that is perceived to be a client error.
|
|
148
|
+
*/
|
|
149
|
+
readonly Error_Client_400_Bad_Request: 400;
|
|
150
|
+
/**
|
|
151
|
+
* 401 Unauthorized: The request has not been applied because it lacks valid authentication credentials for the target resource.
|
|
152
|
+
*/
|
|
153
|
+
readonly Error_Client_401_Unauthorized: 401;
|
|
154
|
+
/**
|
|
155
|
+
* 402 Payment Required: Reserved for future use.
|
|
156
|
+
*/
|
|
157
|
+
readonly Error_Client_402_Payment_Required: 402;
|
|
158
|
+
/**
|
|
159
|
+
* 403 Forbidden: The client does not have access rights to the content, so the server is refusing to give the requested resource.
|
|
160
|
+
*/
|
|
161
|
+
readonly Error_Client_403_Forbidden: 403;
|
|
162
|
+
/**
|
|
163
|
+
* 404 Not Found: The server can not find the requested resource.
|
|
164
|
+
*/
|
|
165
|
+
readonly Error_Client_404_Not_Found: 404;
|
|
166
|
+
/**
|
|
167
|
+
* 405 Method Not Allowed: The request method is known by the server but is not supported by the target resource.
|
|
168
|
+
*/
|
|
169
|
+
readonly Error_Client_405_Method_Not_Allowed: 405;
|
|
170
|
+
/**
|
|
171
|
+
* 406 Not Acceptable: The target resource does not have a current representation that would be acceptable
|
|
172
|
+
* to the user agent, according to the proactive negotiation header fields received in the request,
|
|
173
|
+
* and the server is unwilling to supply a default representation.
|
|
174
|
+
*/
|
|
175
|
+
readonly Error_Client_406_Not_Acceptable: 406;
|
|
176
|
+
/**
|
|
177
|
+
* 407 Proxy Authentication Required: Similar to 401 Unauthorized,
|
|
178
|
+
* but it indicates that the client needs to authenticate itself in order to use a proxy.
|
|
179
|
+
*/
|
|
180
|
+
readonly Error_Client_407_Proxy_Authentication_Required: 407;
|
|
181
|
+
/**
|
|
182
|
+
* 408 Request Timeout: The server timed out waiting for the request.
|
|
183
|
+
*/
|
|
184
|
+
readonly Error_Client_408_Request_Timeout: 408;
|
|
185
|
+
/**
|
|
186
|
+
* 409 Conflict: The request could not be processed because of conflict in the request, such as an edit conflict.
|
|
187
|
+
*/
|
|
188
|
+
readonly Error_Client_409_Conflict: 409;
|
|
189
|
+
/**
|
|
190
|
+
* 410 Gone: The requested resource is no longer available and will not be available again.
|
|
191
|
+
*/
|
|
192
|
+
readonly Error_Client_410_Gone: 410;
|
|
193
|
+
/**
|
|
194
|
+
* 411 Length Required: The server refuses to accept the request without a defined Content-Length header.
|
|
195
|
+
*/
|
|
196
|
+
readonly Error_Client_411_Length_Required: 411;
|
|
197
|
+
/**
|
|
198
|
+
* 412 Precondition Failed: One or more conditions given in the request header fields evaluated to false when tested on the server.
|
|
199
|
+
*/
|
|
200
|
+
readonly Error_Client_412_Precondition_Failed: 412;
|
|
201
|
+
/**
|
|
202
|
+
* 413 Payload Too Large: The server is refusing to process a request because the request payload is larger
|
|
203
|
+
* than the server is willing or able to process.
|
|
204
|
+
*/
|
|
205
|
+
readonly Error_Client_413_Payload_Too_Large: 413;
|
|
206
|
+
/**
|
|
207
|
+
* 414 URI Too Long: The server is refusing to service the request because the URI is longer than the server is willing to interpret.
|
|
208
|
+
*/
|
|
209
|
+
readonly Error_Client_414_URI_Too_Long: 414;
|
|
210
|
+
/**
|
|
211
|
+
* 415 Unsupported Media Type: The server is refusing to service the request
|
|
212
|
+
* because the entity of the request is in a format not supported by the requested resource for the requested method.
|
|
213
|
+
*/
|
|
214
|
+
readonly Error_Client_415_Unsupported_Media_Type: 415;
|
|
215
|
+
/**
|
|
216
|
+
* 416 Range Not Satisfiable: The client has asked for a portion of the file, but the server cannot supply that portion.
|
|
217
|
+
*/
|
|
218
|
+
readonly Error_Client_416_Range_Not_Satisfiable: 416;
|
|
219
|
+
/**
|
|
220
|
+
* 417 Expectation Failed: The server cannot meet the requirements of the Expect request-header field.
|
|
221
|
+
*/
|
|
222
|
+
readonly Error_Client_417_Expectation_Failed: 417;
|
|
223
|
+
/**
|
|
224
|
+
* 421 Misdirected Request: The request was directed at a server that is not able to produce a response.
|
|
225
|
+
*/
|
|
226
|
+
readonly Error_Client_421_Misdirected_Request: 421;
|
|
227
|
+
/**
|
|
228
|
+
* 422 Unprocessable Entity: The request was well-formed but was unable to be followed due to semantic errors.
|
|
229
|
+
*/
|
|
230
|
+
readonly Error_Client_422_Unprocessable_Entity: 422;
|
|
231
|
+
/**
|
|
232
|
+
* 423 Locked: The resource that is being accessed is locked.
|
|
233
|
+
*/
|
|
234
|
+
readonly Error_Client_423_Locked: 423;
|
|
235
|
+
/**
|
|
236
|
+
* 424 Failed Dependency: The request failed due to a failure of a previous request.
|
|
237
|
+
*/
|
|
238
|
+
readonly Error_Client_424_Failed_Dependency: 424;
|
|
239
|
+
/**
|
|
240
|
+
* 425 Too Early: The server is unwilling to risk processing a request that might be replayed.
|
|
241
|
+
*/
|
|
242
|
+
readonly Error_Client_425_Too_Early: 425;
|
|
243
|
+
/**
|
|
244
|
+
* 426 Upgrade Required: The server refuses to perform the request using the current protocol
|
|
245
|
+
* but might be willing to do so after the client upgrades to a different protocol.
|
|
246
|
+
*/
|
|
247
|
+
readonly Error_Client_426_Upgrade_Required: 426;
|
|
248
|
+
/**
|
|
249
|
+
* 428 Precondition Required: The origin server requires the request to be conditional.
|
|
250
|
+
*/
|
|
251
|
+
readonly Error_Client_428_Precondition_Required: 428;
|
|
252
|
+
/**
|
|
253
|
+
* 429 Too Many Requests: The user has sent too many requests in a given amount of time ("rate limiting").
|
|
254
|
+
*/
|
|
255
|
+
readonly Error_Client_429_Too_Many_Requests: 429;
|
|
256
|
+
/**
|
|
257
|
+
* 431 Request Header Fields Too Large: The server is unwilling to process the request because its header fields are too large.
|
|
258
|
+
*/
|
|
259
|
+
readonly Error_Client_431_Request_Header_Fields_Too_Large: 431;
|
|
260
|
+
/**
|
|
261
|
+
* 451 Unavailable For Legal Reasons: The user requests an illegal resource, such as a web page censored by a government.
|
|
262
|
+
*/
|
|
263
|
+
readonly Error_Client_451_Unavailable_For_Legal_Reasons: 451;
|
|
264
|
+
/**
|
|
265
|
+
* 500 Internal Server Error: A generic error message, given when no more specific message is suitable.
|
|
266
|
+
*/
|
|
267
|
+
readonly Error_Server_500_Internal_Server_Error: 500;
|
|
268
|
+
/**
|
|
269
|
+
* 501 Not Implemented: The server either does not recognize the request method, or it lacks the ability to fulfill the request.
|
|
270
|
+
*/
|
|
271
|
+
readonly Error_Server_501_Not_Implemented: 501;
|
|
272
|
+
/**
|
|
273
|
+
* 502 Bad Gateway: The server was acting as a gateway or proxy and received an invalid response from the upstream server.
|
|
274
|
+
*/
|
|
275
|
+
readonly Error_Server_502_Bad_Gateway: 502;
|
|
276
|
+
/**
|
|
277
|
+
* 503 Service Unavailable: The server is currently unavailable (because it is overloaded or down for maintenance).
|
|
278
|
+
*/
|
|
279
|
+
readonly Error_Server_503_Service_Unavailable: 503;
|
|
280
|
+
/**
|
|
281
|
+
* 504 Gateway Timeout: The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.
|
|
282
|
+
*/
|
|
283
|
+
readonly Error_Server_504_Gateway_Timeout: 504;
|
|
284
|
+
/**
|
|
285
|
+
* 505 HTTP Version Not Supported: The server does not support the HTTP protocol version used in the request.
|
|
286
|
+
*/
|
|
287
|
+
readonly Error_Server_505_HTTP_Version_Not_Supported: 505;
|
|
288
|
+
/**
|
|
289
|
+
* 506 Variant Also Negotiates: Transparent content negotiation for the request results in a circular reference.
|
|
290
|
+
*/
|
|
291
|
+
readonly Error_Server_506_Variant_Also_Negotiates: 506;
|
|
292
|
+
/**
|
|
293
|
+
* 507 Insufficient Storage: The server is unable to store the representation needed to complete the request.
|
|
294
|
+
*/
|
|
295
|
+
readonly Error_Server_507_Insufficient_Storage: 507;
|
|
296
|
+
/**
|
|
297
|
+
* 508 Loop Detected: The server detected an infinite loop while processing the request.
|
|
298
|
+
*/
|
|
299
|
+
readonly Error_Server_508_Loop_Detected: 508;
|
|
300
|
+
/**
|
|
301
|
+
* 510 Not Extended: Further extensions to the request are required for the server to fulfill it.
|
|
302
|
+
*/
|
|
303
|
+
readonly Error_Server_510_Not_Extended: 510;
|
|
304
|
+
/**
|
|
305
|
+
* 511 Network Authentication Required: The client needs to authenticate to gain network access.
|
|
306
|
+
*/
|
|
307
|
+
readonly Error_Server_511_Network_Authentication_Required: 511;
|
|
308
|
+
};
|
|
309
|
+
export declare const HttpStatusMessages: {
|
|
310
|
+
100: string;
|
|
311
|
+
101: string;
|
|
312
|
+
102: string;
|
|
313
|
+
103: string;
|
|
314
|
+
200: string;
|
|
315
|
+
201: string;
|
|
316
|
+
202: string;
|
|
317
|
+
203: string;
|
|
318
|
+
204: string;
|
|
319
|
+
205: string;
|
|
320
|
+
206: string;
|
|
321
|
+
207: string;
|
|
322
|
+
208: string;
|
|
323
|
+
226: string;
|
|
324
|
+
300: string;
|
|
325
|
+
301: string;
|
|
326
|
+
302: string;
|
|
327
|
+
303: string;
|
|
328
|
+
304: string;
|
|
329
|
+
305: string;
|
|
330
|
+
307: string;
|
|
331
|
+
308: string;
|
|
332
|
+
400: string;
|
|
333
|
+
401: string;
|
|
334
|
+
402: string;
|
|
335
|
+
403: string;
|
|
336
|
+
404: string;
|
|
337
|
+
405: string;
|
|
338
|
+
406: string;
|
|
339
|
+
407: string;
|
|
340
|
+
408: string;
|
|
341
|
+
409: string;
|
|
342
|
+
410: string;
|
|
343
|
+
411: string;
|
|
344
|
+
412: string;
|
|
345
|
+
413: string;
|
|
346
|
+
414: string;
|
|
347
|
+
415: string;
|
|
348
|
+
416: string;
|
|
349
|
+
417: string;
|
|
350
|
+
418: string;
|
|
351
|
+
421: string;
|
|
352
|
+
422: string;
|
|
353
|
+
423: string;
|
|
354
|
+
424: string;
|
|
355
|
+
425: string;
|
|
356
|
+
426: string;
|
|
357
|
+
428: string;
|
|
358
|
+
429: string;
|
|
359
|
+
431: string;
|
|
360
|
+
451: string;
|
|
361
|
+
500: string;
|
|
362
|
+
501: string;
|
|
363
|
+
502: string;
|
|
364
|
+
503: string;
|
|
365
|
+
504: string;
|
|
366
|
+
505: string;
|
|
367
|
+
506: string;
|
|
368
|
+
507: string;
|
|
369
|
+
508: string;
|
|
370
|
+
509: string;
|
|
371
|
+
510: string;
|
|
372
|
+
511: string;
|
|
373
|
+
};
|
|
374
|
+
export type HttpStatusCode = keyof typeof HttpStatusMessages;
|
|
375
|
+
//# sourceMappingURL=const.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"const.d.ts","sourceRoot":"","sources":["../src/const.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,WAAW;IACtB;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;CAEK,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,eAAe;IAC1B;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;;OAGG;;IAGH;;OAEG;;IAGH;;;OAGG;;IAGH;;OAEG;;IAGH;;;OAGG;;IAGH;;;OAGG;;IAGH;;;OAGG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;;OAGG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;;OAGG;;IAGH;;;OAGG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;;;OAIG;;IAGH;;;OAGG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;;OAGG;;IAGH;;OAEG;;IAGH;;;OAGG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;;OAGG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;CAEK,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgE9B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,kBAAkB,CAAC"}
|
package/dist/main.cjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/* @alwatr/nanotron-api-server v4.0.0-alpha.0 */
|
|
2
|
+
"use strict";var l=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var E=(i,e)=>{for(var r in e)l(i,r,{get:e[r],enumerable:!0})},R=(i,e,r,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of f(e))!m.call(i,o)&&o!==r&&l(i,o,{get:()=>e[o],enumerable:!(t=y(e,o))||t.enumerable});return i};var S=i=>R(l({},"__esModule",{value:!0}),i);var v={};E(v,{HttpMethods:()=>C,HttpStatusCodes:()=>n,HttpStatusMessages:()=>d,NanotronApiConnection:()=>s,NanotronApiServer:()=>h});module.exports=S(v);var C={GET:"GET",HEAD:"HEAD",POST:"POST",PUT:"PUT",DELETE:"DELETE",CONNECT:"CONNECT",OPTIONS:"OPTIONS",TRACE:"TRACE",PATCH:"PATCH"},n={Info_100_Continue:100,Info_101_Switching_Protocols:101,Info_102_Processing:102,Info_103_Early_Hints:103,Success_200_OK:200,Success_201_Created:201,Success_202_Accepted:202,Success_203_Non_Authoritative_Information:203,Success_204_No_Content:204,Success_205_Reset_Content:205,Success_206_Partial_Content:206,Success_207_Multi_Status:207,Success_208_Already_Reported:208,Success_226_IM_Used:226,Redirect_300_Multiple_Choices:300,Redirect_301_Moved_Permanently:301,Redirect_302_Found:302,Redirect_303_See_Other:303,Redirect_304_Not_Modified:304,Redirect_305_Use_Proxy:305,Redirect_306_Switch_Proxy:306,Redirect_307_Temporary_Redirect:307,Redirect_308_Permanent_Redirect:308,Error_Client_400_Bad_Request:400,Error_Client_401_Unauthorized:401,Error_Client_402_Payment_Required:402,Error_Client_403_Forbidden:403,Error_Client_404_Not_Found:404,Error_Client_405_Method_Not_Allowed:405,Error_Client_406_Not_Acceptable:406,Error_Client_407_Proxy_Authentication_Required:407,Error_Client_408_Request_Timeout:408,Error_Client_409_Conflict:409,Error_Client_410_Gone:410,Error_Client_411_Length_Required:411,Error_Client_412_Precondition_Failed:412,Error_Client_413_Payload_Too_Large:413,Error_Client_414_URI_Too_Long:414,Error_Client_415_Unsupported_Media_Type:415,Error_Client_416_Range_Not_Satisfiable:416,Error_Client_417_Expectation_Failed:417,Error_Client_421_Misdirected_Request:421,Error_Client_422_Unprocessable_Entity:422,Error_Client_423_Locked:423,Error_Client_424_Failed_Dependency:424,Error_Client_425_Too_Early:425,Error_Client_426_Upgrade_Required:426,Error_Client_428_Precondition_Required:428,Error_Client_429_Too_Many_Requests:429,Error_Client_431_Request_Header_Fields_Too_Large:431,Error_Client_451_Unavailable_For_Legal_Reasons:451,Error_Server_500_Internal_Server_Error:500,Error_Server_501_Not_Implemented:501,Error_Server_502_Bad_Gateway:502,Error_Server_503_Service_Unavailable:503,Error_Server_504_Gateway_Timeout:504,Error_Server_505_HTTP_Version_Not_Supported:505,Error_Server_506_Variant_Also_Negotiates:506,Error_Server_507_Insufficient_Storage:507,Error_Server_508_Loop_Detected:508,Error_Server_510_Not_Extended:510,Error_Server_511_Network_Authentication_Required:511},d={100:"Continue",101:"Switching Protocols",102:"Processing",103:"Early Hints",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",208:"Already Reported",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",307:"Temporary Redirect",308:"Permanent Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Payload Too Large",414:"URI Too Long",415:"Unsupported Media Type",416:"Range Not Satisfiable",417:"Expectation Failed",418:"I'm a Teapot",421:"Misdirected Request",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",425:"Too Early",426:"Upgrade Required",428:"Precondition Required",429:"Too Many Requests",431:"Request Header Fields Too Large",451:"Unavailable For Legal Reasons",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",508:"Loop Detected",509:"Bandwidth Limit Exceeded",510:"Not Extended",511:"Network Authentication Required"};var c=require("@alwatr/logger"),_=class _{constructor(e,r,t){this.incomingMessage=e;this.serverResponse=r;this.config_=t;this.replySent_=!1;this.logger_=(0,c.createLogger)("nanotron-api-connection"),this.logger_.logMethodArgs?.("new",{method:e.method,url:e.url}),this.method=(this.incomingMessage.method??"GET").toUpperCase();let o=this.incomingMessage.url??"";this.config_.prefix!=="/"&&o.indexOf(this.config_.prefix)===0&&(o=o.slice(this.config_.prefix.length-1)),o=o.replace(_.versionPattern_,"/"),this.url=new URL(o,"http://hostname/"),this.replyHeaders={server:"Alwatr Nanotron","content-type":"text/plain"}}get replySent(){return this.replySent_}get replyStatusCode(){return this.serverResponse.statusCode}set replyStatusCode(e){this.serverResponse.statusCode=e}applyReplyHeaders_(){this.logger_.logMethodArgs?.("applyReplyHeaders_",this.replyHeaders);for(let e in this.replyHeaders)this.serverResponse.setHeader(e,this.replyHeaders[e])}replyJsonError(e){this.logger_.logMethodArgs?.("replyJsonError",{errorResponse:e}),this.replyJson(e)}replyJson(e){this.logger_.logMethodArgs?.("replyJson",{responseJson:e});let r;try{r=JSON.stringify(e)}catch(t){this.logger_.error("replyJson","reply_json_stringify_failed",t,{url:this.url.pathname,method:this.method}),this.replyStatusCode=n.Error_Server_500_Internal_Server_Error,r=JSON.stringify({ok:!1,errorCode:"reply_json_stringify_failed",errorMessage:"Failed to stringify response JSON."})}this.replyHeaders["content-type"]="application/json",this.reply(r)}replyError(e){this.logger_.logMethodArgs?.("replyError",{error:e});let r=this.replyStatusCode;if(e===void 0||!(e instanceof Error)){this.replyJson({ok:!1,errorCode:"error_"+r,errorMessage:d[r]});return}this.replyJson({ok:!1,errorCode:e.name,errorMessage:e.message})}reply(e){if(this.logger_.logMethodArgs?.("reply",{url:this.url.pathname,method:this.method}),this.replySent_||this.serverResponse.writableFinished){this.logger_.accident("reply","reply_already_sent",{url:this.url.pathname,method:this.method,replySent:this.replySent_,writableFinished:this.serverResponse.writableFinished});return}try{typeof e=="string"&&(e=Buffer.from(e)),this.replyHeaders["content-length"]=e.byteLength,this.applyReplyHeaders_(),this.serverResponse.end(e,"binary"),this.replySent_=!0}catch(r){this.logger_.error("reply","server_response_error",r,{url:this.url.pathname,method:this.method})}}};_.versionPattern_=new RegExp("^/v[0-9]+/");var s=_;var u=require("node:http"),g=require("@alwatr/logger"),a=class a{constructor(e){this.config_={...a.defaultConfig_,...e},this.logger_=(0,g.createLogger)("nanotron-api-server"+(this.config_.port!==80?":"+this.config_.port:"")),this.logger_.logMethodArgs?.("new",{config:this.config_}),this.handleIncomingRequest_=this.handleIncomingRequest_.bind(this),this.handleServerError_=this.handleServerError_.bind(this),this.handleClientError_=this.handleClientError_.bind(this),this.e={exact:{},startsWith:{}},this.httpServer=(0,u.createServer)({keepAlive:!0,keepAliveInitialDelay:0,noDelay:!0},this.handleIncomingRequest_),this.httpServer.requestTimeout=this.config_.requestTimeout,this.httpServer.keepAliveTimeout=this.config_.keepAliveTimeout,this.httpServer.headersTimeout=this.config_.headersTimeout,this.httpServer.listen(this.config_.port,this.config_.host,()=>{this.logger_.logOther?.(`listening on ${this.config_.host}:${this.config_.port}`)}),this.httpServer.on("error",this.handleServerError_),this.httpServer.on("clientError",this.handleClientError_)}close(){this.logger_.logMethod?.("close"),this.httpServer.close()}getRouteOption_(e){if(this.logger_.logMethodArgs?.("getRouteOption_",e),Object.hasOwn(this.e.exact,e.method)&&Object.hasOwn(this.e.exact[e.method],e.url))return this.e.exact[e.method][e.url];if(Object.hasOwn(this.e.startsWith,e.method)){let r=this.e.startsWith[e.method];for(let t in r)if(t.indexOf(e.url)===0)return r[t]}return this.logger_.incident?.("getRouteOption_","route_not_found",e),null}setRouteOption_(e){var t;this.logger_.logMethodArgs?.("setRouteOption_",{...e,handler:"function"});let r=this.e[e.matchType];if(r[t=e.method]??(r[t]={}),Object.hasOwn(r[e.method],e.url))throw this.logger_.error("defineRoute","route_already_exists",{...e,handler:"function"}),new Error("route_already_exists");r[e.method][e.url]=e}defineRoute(e){let r={...e,matchType:"exact"};this.logger_.logMethodArgs?.("defineRoute",{...r,handler:"function"}),this.setRouteOption_(r)}handleServerError_(e){e.code==="EADDRINUSE"?this.logger_.error("handleServerError_","address_in_use",e):this.logger_.error("handleServerError_","http_server_error",e.message||"HTTP server catch an error",e)}handleClientError_(e,r){this.logger_.accident("handleClientError_","http_server_client_error",{errCode:e.code,errMessage:e.message}),r.end(`HTTP/1.1 400 Bad Request\r
|
|
3
|
+
\r
|
|
4
|
+
`)}handleHttpError_(e,r){this.logger_.logMethod?.("handleHttpError_"),e.replyError(r)}async handleIncomingRequest_(e,r){if(this.logger_.logMethod?.("handleIncomingRequest_"),e.url===void 0){this.logger_.accident("handleIncomingRequest_","http_server_url_undefined");return}if(e.method===void 0){this.logger_.accident("handleIncomingRequest_","http_server_method_undefined");return}let t=new s(e,r,{prefix:this.config_.prefix}),o=this.getRouteOption_({method:t.method,url:t.url.pathname});if(o===null)return t.replyStatusCode=n.Error_Client_404_Not_Found,this.handleHttpError_(t);try{await o.handler(t)}catch(p){this.logger_.error("handleIncomingRequest_","route_handler_error",p,{url:t.url.pathname,method:t.method}),t.replyStatusCode=n.Error_Server_500_Internal_Server_Error,this.handleHttpError_(t,p)}}};a.defaultConfig_={host:"0.0.0.0",port:80,requestTimeout:1e4,headersTimeout:13e4,keepAliveTimeout:12e4,healthRoute:!0,allowAllOrigin:!1,prefix:"/api/"};var h=a;0&&(module.exports={HttpMethods,HttpStatusCodes,HttpStatusMessages,NanotronApiConnection,NanotronApiServer});
|
|
5
|
+
//# sourceMappingURL=main.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/main.ts", "../src/const.ts", "../src/api-connection.ts", "../src/api-server.ts"],
|
|
4
|
+
"sourcesContent": ["export * from './api-server.js';\nexport * from './api-connection.js';\nexport * from './type.js';\nexport * from './const.js';\n", "/**\n * Object representing standard HTTP methods.\n */\nexport const HttpMethods = {\n /**\n * GET: Requests a representation of the specified resource.\n */\n GET: 'GET',\n\n /**\n * HEAD: Asks for a response identical to that of a GET request, but without the response body.\n */\n HEAD: 'HEAD',\n\n /**\n * POST: Submits data to be processed (e.g., from an HTML form) to the identified resource.\n */\n POST: 'POST',\n\n /**\n * PUT: Uploads a representation of the specified URI.\n */\n PUT: 'PUT',\n\n /**\n * DELETE: Deletes the specified resource.\n */\n DELETE: 'DELETE',\n\n /**\n * CONNECT: Establishes a tunnel to the server identified by the target resource.\n */\n CONNECT: 'CONNECT',\n\n /**\n * OPTIONS: Describes the communication options for the target resource.\n */\n OPTIONS: 'OPTIONS',\n\n /**\n * TRACE: Performs a message loop-back test along the path to the target resource.\n */\n TRACE: 'TRACE',\n\n /**\n * PATCH: Applies partial modifications to a resource.\n */\n PATCH: 'PATCH'\n} as const;\n\n/**\n * Object representing standard HTTP status codes.\n */\nexport const HttpStatusCodes = {\n /**\n * 100 Continue: The server has received the request headers and the client should proceed to send the request body.\n */\n Info_100_Continue: 100,\n\n /**\n * 101 Switching Protocols: The server understands and is willing to comply with the clients request to switch protocols.\n */\n Info_101_Switching_Protocols: 101,\n\n /**\n * 102 Processing: The server has received and is processing the request, but no response is available yet.\n */\n Info_102_Processing: 102,\n\n /**\n * 103 Early Hints: The server is sending some response headers before the final HTTP message.\n */\n Info_103_Early_Hints: 103,\n\n /**\n * 200 OK: The request has succeeded.\n */\n Success_200_OK: 200,\n\n /**\n * 201 Created: The request has been fulfilled and resulted in a new resource being created.\n */\n Success_201_Created: 201,\n\n /**\n * 202 Accepted: The request has been accepted for processing, but the processing has not been completed.\n */\n Success_202_Accepted: 202,\n\n /**\n * 203 Non-Authoritative Information: The server is a transforming proxy that received a 200 OK\n * from the origin server but is returning a modified version of the origins response.\n */\n Success_203_Non_Authoritative_Information: 203,\n\n /**\n * 204 No Content: The server successfully processed the request and is not returning any content.\n */\n Success_204_No_Content: 204,\n\n /**\n * 205 Reset Content: The server successfully processed the request,\n * asks that the client reset its document view, and is not returning any content.\n */\n Success_205_Reset_Content: 205,\n\n /**\n * 206 Partial Content: The server is delivering only part of the resource due to a range header sent by the client.\n */\n Success_206_Partial_Content: 206,\n\n /**\n * 207 Multi-Status: The message body that follows is an XML message\n * and can contain a number of separate response codes, depending on how many sub-requests were made.\n */\n Success_207_Multi_Status: 207,\n\n /**\n * 208 Already Reported: The members of a DAV binding have already been enumerated\n * in a preceding part of the (multi-status) response, and are not being included again.\n */\n Success_208_Already_Reported: 208,\n\n /**\n * 226 IM Used: The server has fulfilled a request for the resource, and the response is a representation\n * of the result of one or more instance-manipulations applied to the current instance.\n */\n Success_226_IM_Used: 226,\n\n /**\n * 300 Multiple Choices: The request has more than one possible response.\n */\n Redirect_300_Multiple_Choices: 300,\n\n /**\n * 301 Moved Permanently: The URL of the requested resource has been changed permanently.\n */\n Redirect_301_Moved_Permanently: 301,\n\n /**\n * 302 Found: The URL of the requested resource has been changed temporarily.\n */\n Redirect_302_Found: 302,\n\n /**\n * 303 See Other: The response to the request can be found under another URI using a GET method.\n */\n Redirect_303_See_Other: 303,\n\n /**\n * 304 Not Modified: The resource has not been modified since the version specified\n * by the request headers If-Modified-Since or If-None-Match.\n */\n Redirect_304_Not_Modified: 304,\n\n /**\n * 305 Use Proxy: The requested resource is only available through a proxy, the address for which is provided in the response.\n */\n Redirect_305_Use_Proxy: 305,\n\n /**\n * 306 Switch Proxy: No longer used. Originally meant \"Subsequent requests should use the specified proxy.\"\n */\n Redirect_306_Switch_Proxy: 306,\n\n /**\n * 307 Temporary Redirect: The server sends this response to direct the client\n * to get the requested resource at another URI with the same method that was used in the prior request.\n */\n Redirect_307_Temporary_Redirect: 307,\n\n /**\n * 308 Permanent Redirect: This means that the resource is now permanently located at another URI,\n * specified by the Location: HTTP Response header.\n */\n Redirect_308_Permanent_Redirect: 308,\n\n /**\n * 400 Bad Request: The server cannot or will not process the request due to something that is perceived to be a client error.\n */\n Error_Client_400_Bad_Request: 400,\n\n /**\n * 401 Unauthorized: The request has not been applied because it lacks valid authentication credentials for the target resource.\n */\n Error_Client_401_Unauthorized: 401,\n\n /**\n * 402 Payment Required: Reserved for future use.\n */\n Error_Client_402_Payment_Required: 402,\n\n /**\n * 403 Forbidden: The client does not have access rights to the content, so the server is refusing to give the requested resource.\n */\n Error_Client_403_Forbidden: 403,\n\n /**\n * 404 Not Found: The server can not find the requested resource.\n */\n Error_Client_404_Not_Found: 404,\n\n /**\n * 405 Method Not Allowed: The request method is known by the server but is not supported by the target resource.\n */\n Error_Client_405_Method_Not_Allowed: 405,\n\n /**\n * 406 Not Acceptable: The target resource does not have a current representation that would be acceptable\n * to the user agent, according to the proactive negotiation header fields received in the request,\n * and the server is unwilling to supply a default representation.\n */\n Error_Client_406_Not_Acceptable: 406,\n\n /**\n * 407 Proxy Authentication Required: Similar to 401 Unauthorized,\n * but it indicates that the client needs to authenticate itself in order to use a proxy.\n */\n Error_Client_407_Proxy_Authentication_Required: 407,\n\n /**\n * 408 Request Timeout: The server timed out waiting for the request.\n */\n Error_Client_408_Request_Timeout: 408,\n\n /**\n * 409 Conflict: The request could not be processed because of conflict in the request, such as an edit conflict.\n */\n Error_Client_409_Conflict: 409,\n\n /**\n * 410 Gone: The requested resource is no longer available and will not be available again.\n */\n Error_Client_410_Gone: 410,\n\n /**\n * 411 Length Required: The server refuses to accept the request without a defined Content-Length header.\n */\n Error_Client_411_Length_Required: 411,\n\n /**\n * 412 Precondition Failed: One or more conditions given in the request header fields evaluated to false when tested on the server.\n */\n Error_Client_412_Precondition_Failed: 412,\n\n /**\n * 413 Payload Too Large: The server is refusing to process a request because the request payload is larger\n * than the server is willing or able to process.\n */\n Error_Client_413_Payload_Too_Large: 413,\n\n /**\n * 414 URI Too Long: The server is refusing to service the request because the URI is longer than the server is willing to interpret.\n */\n Error_Client_414_URI_Too_Long: 414,\n\n /**\n * 415 Unsupported Media Type: The server is refusing to service the request\n * because the entity of the request is in a format not supported by the requested resource for the requested method.\n */\n Error_Client_415_Unsupported_Media_Type: 415,\n\n /**\n * 416 Range Not Satisfiable: The client has asked for a portion of the file, but the server cannot supply that portion.\n */\n Error_Client_416_Range_Not_Satisfiable: 416,\n\n /**\n * 417 Expectation Failed: The server cannot meet the requirements of the Expect request-header field.\n */\n Error_Client_417_Expectation_Failed: 417,\n\n /**\n * 421 Misdirected Request: The request was directed at a server that is not able to produce a response.\n */\n Error_Client_421_Misdirected_Request: 421,\n\n /**\n * 422 Unprocessable Entity: The request was well-formed but was unable to be followed due to semantic errors.\n */\n Error_Client_422_Unprocessable_Entity: 422,\n\n /**\n * 423 Locked: The resource that is being accessed is locked.\n */\n Error_Client_423_Locked: 423,\n\n /**\n * 424 Failed Dependency: The request failed due to a failure of a previous request.\n */\n Error_Client_424_Failed_Dependency: 424,\n\n /**\n * 425 Too Early: The server is unwilling to risk processing a request that might be replayed.\n */\n Error_Client_425_Too_Early: 425,\n\n /**\n * 426 Upgrade Required: The server refuses to perform the request using the current protocol\n * but might be willing to do so after the client upgrades to a different protocol.\n */\n Error_Client_426_Upgrade_Required: 426,\n\n /**\n * 428 Precondition Required: The origin server requires the request to be conditional.\n */\n Error_Client_428_Precondition_Required: 428,\n\n /**\n * 429 Too Many Requests: The user has sent too many requests in a given amount of time (\"rate limiting\").\n */\n Error_Client_429_Too_Many_Requests: 429,\n\n /**\n * 431 Request Header Fields Too Large: The server is unwilling to process the request because its header fields are too large.\n */\n Error_Client_431_Request_Header_Fields_Too_Large: 431,\n\n /**\n * 451 Unavailable For Legal Reasons: The user requests an illegal resource, such as a web page censored by a government.\n */\n Error_Client_451_Unavailable_For_Legal_Reasons: 451,\n\n /**\n * 500 Internal Server Error: A generic error message, given when no more specific message is suitable.\n */\n Error_Server_500_Internal_Server_Error: 500,\n\n /**\n * 501 Not Implemented: The server either does not recognize the request method, or it lacks the ability to fulfill the request.\n */\n Error_Server_501_Not_Implemented: 501,\n\n /**\n * 502 Bad Gateway: The server was acting as a gateway or proxy and received an invalid response from the upstream server.\n */\n Error_Server_502_Bad_Gateway: 502,\n\n /**\n * 503 Service Unavailable: The server is currently unavailable (because it is overloaded or down for maintenance).\n */\n Error_Server_503_Service_Unavailable: 503,\n\n /**\n * 504 Gateway Timeout: The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.\n */\n Error_Server_504_Gateway_Timeout: 504,\n\n /**\n * 505 HTTP Version Not Supported: The server does not support the HTTP protocol version used in the request.\n */\n Error_Server_505_HTTP_Version_Not_Supported: 505,\n\n /**\n * 506 Variant Also Negotiates: Transparent content negotiation for the request results in a circular reference.\n */\n Error_Server_506_Variant_Also_Negotiates: 506,\n\n /**\n * 507 Insufficient Storage: The server is unable to store the representation needed to complete the request.\n */\n Error_Server_507_Insufficient_Storage: 507,\n\n /**\n * 508 Loop Detected: The server detected an infinite loop while processing the request.\n */\n Error_Server_508_Loop_Detected: 508,\n\n /**\n * 510 Not Extended: Further extensions to the request are required for the server to fulfill it.\n */\n Error_Server_510_Not_Extended: 510,\n\n /**\n * 511 Network Authentication Required: The client needs to authenticate to gain network access.\n */\n Error_Server_511_Network_Authentication_Required: 511\n} as const;\n\nexport const HttpStatusMessages = {\n 100: 'Continue',\n 101: 'Switching Protocols',\n 102: 'Processing',\n 103: 'Early Hints',\n 200: 'OK',\n 201: 'Created',\n 202: 'Accepted',\n 203: 'Non-Authoritative Information',\n 204: 'No Content',\n 205: 'Reset Content',\n 206: 'Partial Content',\n 207: 'Multi-Status',\n 208: 'Already Reported',\n 226: 'IM Used',\n 300: 'Multiple Choices',\n 301: 'Moved Permanently',\n 302: 'Found',\n 303: 'See Other',\n 304: 'Not Modified',\n 305: 'Use Proxy',\n 307: 'Temporary Redirect',\n 308: 'Permanent Redirect',\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 402: 'Payment Required',\n 403: 'Forbidden',\n 404: 'Not Found',\n 405: 'Method Not Allowed',\n 406: 'Not Acceptable',\n 407: 'Proxy Authentication Required',\n 408: 'Request Timeout',\n 409: 'Conflict',\n 410: 'Gone',\n 411: 'Length Required',\n 412: 'Precondition Failed',\n 413: 'Payload Too Large',\n 414: 'URI Too Long',\n 415: 'Unsupported Media Type',\n 416: 'Range Not Satisfiable',\n 417: 'Expectation Failed',\n 418: 'I\\'m a Teapot',\n 421: 'Misdirected Request',\n 422: 'Unprocessable Entity',\n 423: 'Locked',\n 424: 'Failed Dependency',\n 425: 'Too Early',\n 426: 'Upgrade Required',\n 428: 'Precondition Required',\n 429: 'Too Many Requests',\n 431: 'Request Header Fields Too Large',\n 451: 'Unavailable For Legal Reasons',\n 500: 'Internal Server Error',\n 501: 'Not Implemented',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n 505: 'HTTP Version Not Supported',\n 506: 'Variant Also Negotiates',\n 507: 'Insufficient Storage',\n 508: 'Loop Detected',\n 509: 'Bandwidth Limit Exceeded',\n 510: 'Not Extended',\n 511: 'Network Authentication Required',\n};\n\nexport type HttpStatusCode = keyof typeof HttpStatusMessages;\n", "import {createLogger} from '@alwatr/logger';\n\nimport {type HttpStatusCode, HttpStatusCodes, HttpStatusMessages} from './const.js';\n\nimport type {HttpResponseHeaders, HttpMethod, ErrorResponse} from './type.js';\nimport type {Json} from '@alwatr/type-helper';\nimport type {IncomingMessage, ServerResponse} from 'node:http';\n\n/**\n * Configuration options for the NanotronApiConnection.\n */\nexport interface NanotronApiConnectionConfig {\n /**\n * A prefix to be added to the beginning of the `url` of all defined routes.\n *\n * @default '/api/'\n */\n prefix: `/${string}/` | '/';\n}\n\nexport class NanotronApiConnection {\n protected static versionPattern_ = new RegExp('^/v[0-9]+/');\n\n readonly url;\n\n readonly method;\n\n protected readonly logger_;\n\n readonly replyHeaders: HttpResponseHeaders;\n\n protected replySent_ = false;\n get replySent(): boolean {\n return this.replySent_;\n }\n\n constructor(\n public incomingMessage: IncomingMessage,\n public serverResponse: ServerResponse,\n protected config_: NanotronApiConnectionConfig,\n ) {\n // Create logger.\n this.logger_ = createLogger('nanotron-api-connection'); // TODO: add client ip\n this.logger_.logMethodArgs?.('new', {method: incomingMessage.method, url: incomingMessage.url});\n\n // Parse request method.\n this.method = (this.incomingMessage.method ?? 'GET').toUpperCase() as HttpMethod;\n\n // Parse request URL.\n let url = this.incomingMessage.url ?? '';\n if (this.config_.prefix !== '/' && url.indexOf(this.config_.prefix) === 0) {\n url = url.slice(this.config_.prefix.length - 1);\n }\n url = url.replace(NanotronApiConnection.versionPattern_, '/');\n this.url = new URL(url, 'http://hostname/');\n\n // Set default reply headers.\n this.replyHeaders = {\n server: 'Alwatr Nanotron',\n 'content-type': 'text/plain',\n };\n }\n\n get replyStatusCode(): HttpStatusCode {\n return this.serverResponse.statusCode as HttpStatusCode;\n }\n\n set replyStatusCode(value: HttpStatusCode) {\n this.serverResponse.statusCode = value;\n }\n\n protected applyReplyHeaders_() {\n this.logger_.logMethodArgs?.('applyReplyHeaders_', this.replyHeaders);\n for (const key in this.replyHeaders) {\n this.serverResponse.setHeader(key, this.replyHeaders[key as Lowercase<string>]!);\n }\n }\n\n replyJsonError(errorResponse: ErrorResponse): void {\n this.logger_.logMethodArgs?.('replyJsonError', {errorResponse});\n this.replyJson(errorResponse);\n }\n\n replyJson(responseJson: Json): void {\n this.logger_.logMethodArgs?.('replyJson', {responseJson});\n\n let responseString: string;\n try {\n responseString = JSON.stringify(responseJson);\n }\n catch (error) {\n this.logger_.error('replyJson', 'reply_json_stringify_failed', error, {\n url: this.url.pathname,\n method: this.method,\n });\n this.replyStatusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n responseString = JSON.stringify({\n ok: false,\n errorCode: 'reply_json_stringify_failed',\n errorMessage: 'Failed to stringify response JSON.',\n } as ErrorResponse);\n }\n\n this.replyHeaders['content-type'] = 'application/json';\n this.reply(responseString);\n }\n\n replyError(error?: Error | unknown): void {\n this.logger_.logMethodArgs?.('replyError', {error});\n\n const statusCode = this.replyStatusCode;\n\n if (error === undefined || error instanceof Error === false) {\n this.replyJson({\n ok: false,\n errorCode: ('error_' + statusCode) as Lowercase<string>,\n errorMessage: HttpStatusMessages[statusCode]\n } as ErrorResponse);\n return;\n }\n\n this.replyJson({\n ok: false,\n errorCode: error.name,\n errorMessage: error.message,\n });\n }\n\n reply(context: string | Buffer): void {\n this.logger_.logMethodArgs?.('reply', {url: this.url.pathname, method: this.method});\n\n if (this.replySent_ || this.serverResponse.writableFinished) {\n this.logger_.accident('reply', 'reply_already_sent', {\n url: this.url.pathname,\n method: this.method,\n replySent: this.replySent_,\n writableFinished: this.serverResponse.writableFinished,\n });\n return;\n }\n\n try {\n if (typeof context === 'string') {\n context = Buffer.from(context);\n }\n\n this.replyHeaders['content-length'] = context.byteLength;\n\n this.applyReplyHeaders_();\n this.serverResponse.end(context, 'binary');\n\n this.replySent_ = true;\n }\n catch (error) {\n this.logger_.error('reply', 'server_response_error', error, {url: this.url.pathname, method: this.method});\n }\n }\n}\n", "import {createServer, IncomingMessage, ServerResponse} from 'node:http';\n\nimport {createLogger} from '@alwatr/logger';\n\nimport {NanotronApiConnection} from './api-connection.js';\nimport {HttpStatusCodes} from './const.js';\n\nimport type {HttpMethod, MatchType, RouteHandler} from './type.js';\nimport type {Dictionary} from '@alwatr/type-helper';\nimport type {Duplex} from 'node:stream';\n\n/**\n * Configuration options for the NanotronApiServer.\n */\nexport interface NanotronApiServerConfig {\n /**\n * The port number to listen on.\n *\n * @default 80\n */\n port?: number;\n\n /**\n * The hostname to listen on.\n *\n * @default '0.0.0.0'\n */\n host?: string;\n\n /**\n * Sets the timeout (ms) for receiving the entire request from the client.\n *\n * @default 10_000 ms\n */\n requestTimeout?: number;\n\n /**\n * Sets the timeout (ms) for receiving the complete HTTP headers from the client.\n *\n * This should be bigger than `keepAliveTimeout + your server's expected response time`.\n *\n * @default 130_000 ms\n */\n headersTimeout?: number;\n\n /**\n * Sets the timeout (ms) for receiving the complete HTTP headers from the client.\n *\n * @default 120_000 ms\n */\n keepAliveTimeout?: number;\n\n /**\n * Add /health route.\n *\n * @default true\n */\n healthRoute?: boolean;\n\n /**\n * Add OPTIONS route for preflight requests to allow access all origins.\n *\n * @default false\n */\n allowAllOrigin?: boolean;\n\n /**\n * A prefix to be added to the beginning of the `url` of all defined routes.\n *\n * @default '/api/'\n */\n prefix?: `/${string}/` | '/';\n}\n\n/**\n * Configuration options for defining a route.\n */\nexport interface DefineRouteOption {\n /**\n * The HTTP method for this route.\n */\n method: HttpMethod;\n\n /**\n * The URL path for this route.\n */\n url: string;\n\n /**\n * The function to handle requests to this route.\n */\n handler: RouteHandler;\n\n /**\n * Specifies how the `url` should be matched against incoming requests.\n *\n * @default 'exact'\n */\n matchType?: MatchType;\n}\n\nexport class NanotronApiServer {\n protected static readonly defaultConfig_: Readonly<Required<NanotronApiServerConfig>> = {\n host: '0.0.0.0',\n port: 80,\n requestTimeout: 10_000,\n headersTimeout: 130_000,\n keepAliveTimeout: 120_000,\n healthRoute: true,\n allowAllOrigin: false,\n prefix: '/api/',\n };\n\n protected readonly config_;\n protected readonly logger_;\n\n readonly httpServer;\n\n protected readonly routeHandlerList__: Record<MatchType, Dictionary<Dictionary<Required<DefineRouteOption>>>>;\n\n constructor(config?: Partial<NanotronApiServerConfig>) {\n // Merge the config with the default config.\n this.config_ = {\n ...NanotronApiServer.defaultConfig_,\n ...config,\n };\n\n // Create logger.\n this.logger_ = createLogger('nanotron-api-server' + (this.config_.port !== 80 ? ':' + this.config_.port : ''));\n this.logger_.logMethodArgs?.('new', {config: this.config_});\n\n // Bind methods.\n this.handleIncomingRequest_ = this.handleIncomingRequest_.bind(this);\n this.handleServerError_ = this.handleServerError_.bind(this);\n this.handleClientError_ = this.handleClientError_.bind(this);\n\n // Initialize route handler list.\n this.routeHandlerList__ = {\n exact: {},\n startsWith: {},\n };\n\n // Create the HTTP server.\n this.httpServer = createServer(\n {\n keepAlive: true,\n keepAliveInitialDelay: 0,\n noDelay: true,\n },\n this.handleIncomingRequest_,\n );\n\n // Configure the server.\n this.httpServer.requestTimeout = this.config_.requestTimeout;\n this.httpServer.keepAliveTimeout = this.config_.keepAliveTimeout;\n this.httpServer.headersTimeout = this.config_.headersTimeout;\n\n // Start the server.\n this.httpServer.listen(this.config_.port, this.config_.host, () => {\n this.logger_.logOther?.(`listening on ${this.config_.host}:${this.config_.port}`);\n });\n\n // Handle server errors.\n this.httpServer.on('error', this.handleServerError_);\n this.httpServer.on('clientError', this.handleClientError_);\n }\n\n close(): void {\n this.logger_.logMethod?.('close');\n this.httpServer.close();\n }\n\n protected getRouteOption_(option: Required<Pick<DefineRouteOption, 'method' | 'url'>>): Required<DefineRouteOption> | null {\n this.logger_.logMethodArgs?.('getRouteOption_', option);\n\n if (\n Object.hasOwn(this.routeHandlerList__.exact, option.method) &&\n Object.hasOwn(this.routeHandlerList__.exact[option.method], option.url)\n ) {\n return this.routeHandlerList__.exact[option.method][option.url];\n }\n\n if (Object.hasOwn(this.routeHandlerList__.startsWith, option.method)) {\n const routeList = this.routeHandlerList__.startsWith[option.method];\n for (const url in routeList) {\n if (url.indexOf(option.url) === 0) {\n return routeList[url];\n }\n }\n }\n\n this.logger_.incident?.('getRouteOption_', 'route_not_found', option);\n return null;\n }\n\n protected setRouteOption_(option: Required<DefineRouteOption>): void {\n this.logger_.logMethodArgs?.('setRouteOption_', {...option, handler: 'function'});\n\n const routeHandlerList = this.routeHandlerList__[option.matchType];\n\n routeHandlerList[option.method] ??= {};\n\n if (Object.hasOwn(routeHandlerList[option.method], option.url)) {\n this.logger_.error('defineRoute', 'route_already_exists', {...option, handler: 'function'});\n throw new Error('route_already_exists');\n }\n\n routeHandlerList[option.method][option.url] = option;\n }\n\n defineRoute(option: DefineRouteOption): void {\n const option_: Required<DefineRouteOption> = {\n ...option,\n matchType: 'exact',\n };\n this.logger_.logMethodArgs?.('defineRoute', {...option_, handler: 'function'});\n this.setRouteOption_(option_);\n }\n\n protected handleServerError_(err: NodeJS.ErrnoException): void {\n if (err.code === 'EADDRINUSE') {\n this.logger_.error('handleServerError_', 'address_in_use', err);\n }\n else {\n this.logger_.error('handleServerError_', 'http_server_error', err.message || 'HTTP server catch an error', err);\n }\n }\n\n protected handleClientError_(err: NodeJS.ErrnoException, socket: Duplex): void {\n this.logger_.accident('handleClientError_', 'http_server_client_error', {\n errCode: err.code,\n errMessage: err.message,\n });\n socket.end('HTTP/1.1 400 Bad Request\\r\\n\\r\\n');\n }\n\n protected handleHttpError_(connection: NanotronApiConnection, error?: unknown): void {\n this.logger_.logMethod?.('handleHttpError_');\n // TODO: custom error template by the user.\n connection.replyError(error);\n }\n\n protected async handleIncomingRequest_(incomingMessage: IncomingMessage, serverResponse: ServerResponse): Promise<void> {\n this.logger_.logMethod?.('handleIncomingRequest_');\n\n if (incomingMessage.url === undefined) {\n this.logger_.accident('handleIncomingRequest_', 'http_server_url_undefined');\n return;\n }\n\n if (incomingMessage.method === undefined) {\n this.logger_.accident('handleIncomingRequest_', 'http_server_method_undefined');\n return;\n }\n\n const connection = new NanotronApiConnection(incomingMessage, serverResponse, {prefix: this.config_.prefix});\n\n const routeOption = this.getRouteOption_({\n method: connection.method,\n url: connection.url.pathname,\n });\n\n if (routeOption === null) {\n connection.replyStatusCode = HttpStatusCodes.Error_Client_404_Not_Found;\n return this.handleHttpError_(connection);\n }\n\n try {\n // TODO: hooks\n await routeOption.handler(connection);\n }\n catch (error) {\n this.logger_.error('handleIncomingRequest_', 'route_handler_error', error, {\n url: connection.url.pathname,\n method: connection.method,\n });\n\n connection.replyStatusCode = HttpStatusCodes.Error_Server_500_Internal_Server_Error;\n this.handleHttpError_(connection, error);\n }\n\n // TODO: handled open remained connections.\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["main_exports", "__export", "HttpMethods", "HttpStatusCodes", "HttpStatusMessages", "NanotronApiConnection", "NanotronApiServer", "__toCommonJS", "HttpMethods", "HttpStatusCodes", "HttpStatusMessages", "import_logger", "_NanotronApiConnection", "incomingMessage", "serverResponse", "config_", "url", "value", "key", "errorResponse", "responseJson", "responseString", "error", "HttpStatusCodes", "statusCode", "HttpStatusMessages", "context", "NanotronApiConnection", "import_node_http", "import_logger", "_NanotronApiServer", "config", "routeHandlerList__", "option", "routeList", "url", "_a", "routeHandlerList", "option_", "err", "socket", "connection", "error", "incomingMessage", "serverResponse", "NanotronApiConnection", "routeOption", "HttpStatusCodes", "NanotronApiServer"]
|
|
7
|
+
}
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
|
package/dist/main.mjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/* @alwatr/nanotron-api-server v4.0.0-alpha.0 */
|
|
2
|
+
var u={GET:"GET",HEAD:"HEAD",POST:"POST",PUT:"PUT",DELETE:"DELETE",CONNECT:"CONNECT",OPTIONS:"OPTIONS",TRACE:"TRACE",PATCH:"PATCH"},i={Info_100_Continue:100,Info_101_Switching_Protocols:101,Info_102_Processing:102,Info_103_Early_Hints:103,Success_200_OK:200,Success_201_Created:201,Success_202_Accepted:202,Success_203_Non_Authoritative_Information:203,Success_204_No_Content:204,Success_205_Reset_Content:205,Success_206_Partial_Content:206,Success_207_Multi_Status:207,Success_208_Already_Reported:208,Success_226_IM_Used:226,Redirect_300_Multiple_Choices:300,Redirect_301_Moved_Permanently:301,Redirect_302_Found:302,Redirect_303_See_Other:303,Redirect_304_Not_Modified:304,Redirect_305_Use_Proxy:305,Redirect_306_Switch_Proxy:306,Redirect_307_Temporary_Redirect:307,Redirect_308_Permanent_Redirect:308,Error_Client_400_Bad_Request:400,Error_Client_401_Unauthorized:401,Error_Client_402_Payment_Required:402,Error_Client_403_Forbidden:403,Error_Client_404_Not_Found:404,Error_Client_405_Method_Not_Allowed:405,Error_Client_406_Not_Acceptable:406,Error_Client_407_Proxy_Authentication_Required:407,Error_Client_408_Request_Timeout:408,Error_Client_409_Conflict:409,Error_Client_410_Gone:410,Error_Client_411_Length_Required:411,Error_Client_412_Precondition_Failed:412,Error_Client_413_Payload_Too_Large:413,Error_Client_414_URI_Too_Long:414,Error_Client_415_Unsupported_Media_Type:415,Error_Client_416_Range_Not_Satisfiable:416,Error_Client_417_Expectation_Failed:417,Error_Client_421_Misdirected_Request:421,Error_Client_422_Unprocessable_Entity:422,Error_Client_423_Locked:423,Error_Client_424_Failed_Dependency:424,Error_Client_425_Too_Early:425,Error_Client_426_Upgrade_Required:426,Error_Client_428_Precondition_Required:428,Error_Client_429_Too_Many_Requests:429,Error_Client_431_Request_Header_Fields_Too_Large:431,Error_Client_451_Unavailable_For_Legal_Reasons:451,Error_Server_500_Internal_Server_Error:500,Error_Server_501_Not_Implemented:501,Error_Server_502_Bad_Gateway:502,Error_Server_503_Service_Unavailable:503,Error_Server_504_Gateway_Timeout:504,Error_Server_505_HTTP_Version_Not_Supported:505,Error_Server_506_Variant_Also_Negotiates:506,Error_Server_507_Insufficient_Storage:507,Error_Server_508_Loop_Detected:508,Error_Server_510_Not_Extended:510,Error_Server_511_Network_Authentication_Required:511},l={100:"Continue",101:"Switching Protocols",102:"Processing",103:"Early Hints",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",208:"Already Reported",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",307:"Temporary Redirect",308:"Permanent Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Payload Too Large",414:"URI Too Long",415:"Unsupported Media Type",416:"Range Not Satisfiable",417:"Expectation Failed",418:"I'm a Teapot",421:"Misdirected Request",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",425:"Too Early",426:"Upgrade Required",428:"Precondition Required",429:"Too Many Requests",431:"Request Header Fields Too Large",451:"Unavailable For Legal Reasons",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",508:"Loop Detected",509:"Bandwidth Limit Exceeded",510:"Not Extended",511:"Network Authentication Required"};import{createLogger as h}from"@alwatr/logger";var s=class s{constructor(e,r,t){this.incomingMessage=e;this.serverResponse=r;this.config_=t;this.replySent_=!1;this.logger_=h("nanotron-api-connection"),this.logger_.logMethodArgs?.("new",{method:e.method,url:e.url}),this.method=(this.incomingMessage.method??"GET").toUpperCase();let o=this.incomingMessage.url??"";this.config_.prefix!=="/"&&o.indexOf(this.config_.prefix)===0&&(o=o.slice(this.config_.prefix.length-1)),o=o.replace(s.versionPattern_,"/"),this.url=new URL(o,"http://hostname/"),this.replyHeaders={server:"Alwatr Nanotron","content-type":"text/plain"}}get replySent(){return this.replySent_}get replyStatusCode(){return this.serverResponse.statusCode}set replyStatusCode(e){this.serverResponse.statusCode=e}applyReplyHeaders_(){this.logger_.logMethodArgs?.("applyReplyHeaders_",this.replyHeaders);for(let e in this.replyHeaders)this.serverResponse.setHeader(e,this.replyHeaders[e])}replyJsonError(e){this.logger_.logMethodArgs?.("replyJsonError",{errorResponse:e}),this.replyJson(e)}replyJson(e){this.logger_.logMethodArgs?.("replyJson",{responseJson:e});let r;try{r=JSON.stringify(e)}catch(t){this.logger_.error("replyJson","reply_json_stringify_failed",t,{url:this.url.pathname,method:this.method}),this.replyStatusCode=i.Error_Server_500_Internal_Server_Error,r=JSON.stringify({ok:!1,errorCode:"reply_json_stringify_failed",errorMessage:"Failed to stringify response JSON."})}this.replyHeaders["content-type"]="application/json",this.reply(r)}replyError(e){this.logger_.logMethodArgs?.("replyError",{error:e});let r=this.replyStatusCode;if(e===void 0||!(e instanceof Error)){this.replyJson({ok:!1,errorCode:"error_"+r,errorMessage:l[r]});return}this.replyJson({ok:!1,errorCode:e.name,errorMessage:e.message})}reply(e){if(this.logger_.logMethodArgs?.("reply",{url:this.url.pathname,method:this.method}),this.replySent_||this.serverResponse.writableFinished){this.logger_.accident("reply","reply_already_sent",{url:this.url.pathname,method:this.method,replySent:this.replySent_,writableFinished:this.serverResponse.writableFinished});return}try{typeof e=="string"&&(e=Buffer.from(e)),this.replyHeaders["content-length"]=e.byteLength,this.applyReplyHeaders_(),this.serverResponse.end(e,"binary"),this.replySent_=!0}catch(r){this.logger_.error("reply","server_response_error",r,{url:this.url.pathname,method:this.method})}}};s.versionPattern_=new RegExp("^/v[0-9]+/");var n=s;import{createServer as p}from"node:http";import{createLogger as c}from"@alwatr/logger";var _=class _{constructor(e){this.config_={..._.defaultConfig_,...e},this.logger_=c("nanotron-api-server"+(this.config_.port!==80?":"+this.config_.port:"")),this.logger_.logMethodArgs?.("new",{config:this.config_}),this.handleIncomingRequest_=this.handleIncomingRequest_.bind(this),this.handleServerError_=this.handleServerError_.bind(this),this.handleClientError_=this.handleClientError_.bind(this),this.e={exact:{},startsWith:{}},this.httpServer=p({keepAlive:!0,keepAliveInitialDelay:0,noDelay:!0},this.handleIncomingRequest_),this.httpServer.requestTimeout=this.config_.requestTimeout,this.httpServer.keepAliveTimeout=this.config_.keepAliveTimeout,this.httpServer.headersTimeout=this.config_.headersTimeout,this.httpServer.listen(this.config_.port,this.config_.host,()=>{this.logger_.logOther?.(`listening on ${this.config_.host}:${this.config_.port}`)}),this.httpServer.on("error",this.handleServerError_),this.httpServer.on("clientError",this.handleClientError_)}close(){this.logger_.logMethod?.("close"),this.httpServer.close()}getRouteOption_(e){if(this.logger_.logMethodArgs?.("getRouteOption_",e),Object.hasOwn(this.e.exact,e.method)&&Object.hasOwn(this.e.exact[e.method],e.url))return this.e.exact[e.method][e.url];if(Object.hasOwn(this.e.startsWith,e.method)){let r=this.e.startsWith[e.method];for(let t in r)if(t.indexOf(e.url)===0)return r[t]}return this.logger_.incident?.("getRouteOption_","route_not_found",e),null}setRouteOption_(e){var t;this.logger_.logMethodArgs?.("setRouteOption_",{...e,handler:"function"});let r=this.e[e.matchType];if(r[t=e.method]??(r[t]={}),Object.hasOwn(r[e.method],e.url))throw this.logger_.error("defineRoute","route_already_exists",{...e,handler:"function"}),new Error("route_already_exists");r[e.method][e.url]=e}defineRoute(e){let r={...e,matchType:"exact"};this.logger_.logMethodArgs?.("defineRoute",{...r,handler:"function"}),this.setRouteOption_(r)}handleServerError_(e){e.code==="EADDRINUSE"?this.logger_.error("handleServerError_","address_in_use",e):this.logger_.error("handleServerError_","http_server_error",e.message||"HTTP server catch an error",e)}handleClientError_(e,r){this.logger_.accident("handleClientError_","http_server_client_error",{errCode:e.code,errMessage:e.message}),r.end(`HTTP/1.1 400 Bad Request\r
|
|
3
|
+
\r
|
|
4
|
+
`)}handleHttpError_(e,r){this.logger_.logMethod?.("handleHttpError_"),e.replyError(r)}async handleIncomingRequest_(e,r){if(this.logger_.logMethod?.("handleIncomingRequest_"),e.url===void 0){this.logger_.accident("handleIncomingRequest_","http_server_url_undefined");return}if(e.method===void 0){this.logger_.accident("handleIncomingRequest_","http_server_method_undefined");return}let t=new n(e,r,{prefix:this.config_.prefix}),o=this.getRouteOption_({method:t.method,url:t.url.pathname});if(o===null)return t.replyStatusCode=i.Error_Client_404_Not_Found,this.handleHttpError_(t);try{await o.handler(t)}catch(a){this.logger_.error("handleIncomingRequest_","route_handler_error",a,{url:t.url.pathname,method:t.method}),t.replyStatusCode=i.Error_Server_500_Internal_Server_Error,this.handleHttpError_(t,a)}}};_.defaultConfig_={host:"0.0.0.0",port:80,requestTimeout:1e4,headersTimeout:13e4,keepAliveTimeout:12e4,healthRoute:!0,allowAllOrigin:!1,prefix:"/api/"};var d=_;export{u as HttpMethods,i as HttpStatusCodes,l as HttpStatusMessages,n as NanotronApiConnection,d as NanotronApiServer};
|
|
5
|
+
//# sourceMappingURL=main.mjs.map
|