srvx-nightly 0.11.21 → 0.11.22-20260711-160642-e093402
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/_trust-proxy.mjs +58 -0
- package/dist/_chunks/_utils2.mjs +1 -1
- package/dist/_chunks/types.d.mts +363 -0
- package/dist/adapters/aws-lambda.d.mts +3 -3
- package/dist/adapters/aws-lambda.mjs +21 -11
- package/dist/adapters/bun.d.mts +1 -1
- package/dist/adapters/bun.mjs +3 -0
- package/dist/adapters/bunny.d.mts +1 -1
- package/dist/adapters/cloudflare.d.mts +1 -1
- package/dist/adapters/deno.d.mts +1 -1
- package/dist/adapters/deno.mjs +3 -0
- package/dist/adapters/generic.d.mts +1 -1
- package/dist/adapters/node.d.mts +7 -1
- package/dist/adapters/node.mjs +35 -13
- package/dist/adapters/service-worker.d.mts +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/log.d.mts +1 -1
- package/dist/mtls.d.mts +114 -0
- package/dist/mtls.mjs +32 -0
- package/dist/static.d.mts +1 -1
- package/dist/tracing.d.mts +1 -1
- package/dist/types.d.mts +2 -325
- package/package.json +2 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
function isTrustedProxy(trustProxy, remoteAddress) {
|
|
2
|
+
if (trustProxy === void 0 || trustProxy === false) return false;
|
|
3
|
+
if (trustProxy === true) return true;
|
|
4
|
+
if (trustProxy === "loopback") return isLoopbackAddress(remoteAddress);
|
|
5
|
+
if (remoteAddress === void 0) return false;
|
|
6
|
+
if (trustProxy.includes(remoteAddress)) return true;
|
|
7
|
+
const mapped = ipv4FromMapped(remoteAddress);
|
|
8
|
+
return mapped !== void 0 && trustProxy.includes(mapped);
|
|
9
|
+
}
|
|
10
|
+
function ipv4FromMapped(address) {
|
|
11
|
+
return address.startsWith("::ffff:") && address.includes(".") ? address.slice(7) : void 0;
|
|
12
|
+
}
|
|
13
|
+
function isLoopbackAddress(address) {
|
|
14
|
+
return !!address && (address === "::1" || address.startsWith("127.") || address.startsWith("::ffff:127."));
|
|
15
|
+
}
|
|
16
|
+
const HOST_RE = /^(\[(?:[A-Fa-f0-9:.]+)\]|(?:[A-Za-z0-9_-]+\.)*[A-Za-z0-9_-]+|(?:\d{1,3}\.){3}\d{1,3})(:\d{1,5})?$/;
|
|
17
|
+
function forwardedHostHasPort(host) {
|
|
18
|
+
const bracket = host.lastIndexOf("]");
|
|
19
|
+
return bracket === -1 ? host.includes(":") : host.indexOf(":", bracket) !== -1;
|
|
20
|
+
}
|
|
21
|
+
function firstForwardedValue(value) {
|
|
22
|
+
if (!value) return;
|
|
23
|
+
return (Array.isArray(value) ? value[0] : value).split(",")[0].trim() || void 0;
|
|
24
|
+
}
|
|
25
|
+
const trustProxyPlugin = (server) => {
|
|
26
|
+
const trustProxy = server.options.trustProxy;
|
|
27
|
+
if (trustProxy === void 0 || trustProxy === false) return;
|
|
28
|
+
server.options.middleware.unshift((request, next) => {
|
|
29
|
+
applyTrustedProxy(request, trustProxy);
|
|
30
|
+
return next();
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
function applyTrustedProxy(request, trustProxy) {
|
|
34
|
+
if (!isTrustedProxy(trustProxy, request.ip)) return;
|
|
35
|
+
const headers = request.headers;
|
|
36
|
+
const forwardedProto = firstForwardedValue(headers.get("x-forwarded-proto"));
|
|
37
|
+
const forwardedHost = firstForwardedValue(headers.get("x-forwarded-host"));
|
|
38
|
+
if (forwardedProto || forwardedHost) {
|
|
39
|
+
const url = new URL(request.url);
|
|
40
|
+
if (forwardedProto === "https" || forwardedProto === "http") url.protocol = `${forwardedProto}:`;
|
|
41
|
+
if (forwardedHost && HOST_RE.test(forwardedHost)) {
|
|
42
|
+
url.host = forwardedHost;
|
|
43
|
+
if (url.port && !forwardedHostHasPort(forwardedHost)) url.port = "";
|
|
44
|
+
}
|
|
45
|
+
Object.defineProperty(request, "url", {
|
|
46
|
+
value: url.href,
|
|
47
|
+
enumerable: true,
|
|
48
|
+
configurable: true
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const forwardedFor = firstForwardedValue(headers.get("x-forwarded-for"));
|
|
52
|
+
if (forwardedFor) Object.defineProperty(request, "ip", {
|
|
53
|
+
value: forwardedFor,
|
|
54
|
+
enumerable: true,
|
|
55
|
+
configurable: true
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
export { HOST_RE, firstForwardedValue, isTrustedProxy, trustProxyPlugin };
|
package/dist/_chunks/_utils2.mjs
CHANGED
|
@@ -72,4 +72,4 @@ function createWaitUntil() {
|
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
|
-
export { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions, toNativeResponse };
|
|
75
|
+
export { createWaitUntil, fmtURL, printListening, resolveCertOrKey, resolvePortAndHost, resolveTLSOptions, toNativeResponse };
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import * as NodeHttp from "node:http";
|
|
2
|
+
import * as NodeHttps from "node:https";
|
|
3
|
+
import * as NodeHttp2 from "node:http2";
|
|
4
|
+
import * as AWS from "aws-lambda";
|
|
5
|
+
import * as NodeNet from "node:net";
|
|
6
|
+
import * as Bun from "bun";
|
|
7
|
+
import * as CF from "@cloudflare/workers-types";
|
|
8
|
+
/**
|
|
9
|
+
* Controls whether `X-Forwarded-*` headers (proto, host, for, and the HTTP/2
|
|
10
|
+
* `:scheme` pseudo-header) are trusted when deriving request metadata.
|
|
11
|
+
*
|
|
12
|
+
* These headers are set by the client on the wire, so they can only be trusted
|
|
13
|
+
* when a proxy you control sits in front and overwrites them. See
|
|
14
|
+
* {@link ServerOptions.trustProxy}.
|
|
15
|
+
*
|
|
16
|
+
* - `false` (default): never trust forwarded headers; derive protocol, host
|
|
17
|
+
* and client IP from the real transport only.
|
|
18
|
+
* - `true`: always trust forwarded headers.
|
|
19
|
+
* - `"loopback"`: trust only when the immediate peer is a loopback address
|
|
20
|
+
* (`127.0.0.0/8` or `::1`), i.e. a proxy running on the same host.
|
|
21
|
+
* - `string[]`: trust only when the immediate peer address is in the allowlist.
|
|
22
|
+
*/
|
|
23
|
+
type TrustProxyOption = boolean | "loopback" | string[];
|
|
24
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
25
|
+
type IsAny<T> = Equal<T, any> extends true ? true : false;
|
|
26
|
+
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;
|
|
27
|
+
/**
|
|
28
|
+
* Faster URL constructor with lazy access to pathname and search params (For Node, Deno, and Bun).
|
|
29
|
+
*/
|
|
30
|
+
declare const FastURL: typeof globalThis.URL;
|
|
31
|
+
/**
|
|
32
|
+
* Faster Response constructor optimized for Node.js (same as Response for other runtimes).
|
|
33
|
+
*/
|
|
34
|
+
declare const FastResponse: typeof globalThis.Response;
|
|
35
|
+
/**
|
|
36
|
+
* Create a new server instance.
|
|
37
|
+
*/
|
|
38
|
+
declare function serve(options: ServerOptions): Server;
|
|
39
|
+
/**
|
|
40
|
+
* Web fetch compatible request handler
|
|
41
|
+
*/
|
|
42
|
+
type ServerHandler = (request: ServerRequest) => MaybePromise<Response>;
|
|
43
|
+
type ServerMiddleware = (request: ServerRequest, next: () => Response | Promise<Response>) => Response | Promise<Response>;
|
|
44
|
+
type ServerPlugin = (server: Server) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Server options
|
|
47
|
+
*/
|
|
48
|
+
interface ServerOptions {
|
|
49
|
+
/**
|
|
50
|
+
* The fetch handler handles incoming requests.
|
|
51
|
+
*/
|
|
52
|
+
fetch: ServerHandler;
|
|
53
|
+
/**
|
|
54
|
+
* Handle lifecycle errors.
|
|
55
|
+
*
|
|
56
|
+
* @note This handler will set built-in Bun and Deno error handler.
|
|
57
|
+
*/
|
|
58
|
+
error?: ErrorHandler;
|
|
59
|
+
/**
|
|
60
|
+
* Server middleware handlers to run before the main fetch handler.
|
|
61
|
+
*/
|
|
62
|
+
middleware?: ServerMiddleware[];
|
|
63
|
+
/**
|
|
64
|
+
* Server plugins.
|
|
65
|
+
*/
|
|
66
|
+
plugins?: ServerPlugin[];
|
|
67
|
+
/**
|
|
68
|
+
* If set to `true`, server will not start listening automatically.
|
|
69
|
+
*/
|
|
70
|
+
manual?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* The port server should be listening to.
|
|
73
|
+
*
|
|
74
|
+
* Default is read from `PORT` environment variable or will be `3000`.
|
|
75
|
+
*
|
|
76
|
+
* **Tip:** You can set the port to `0` to use a random port.
|
|
77
|
+
*/
|
|
78
|
+
port?: string | number;
|
|
79
|
+
/**
|
|
80
|
+
* The hostname (IP or resolvable host) server listener should bound to.
|
|
81
|
+
*
|
|
82
|
+
* When not provided, server with listen to all network interfaces by default.
|
|
83
|
+
*
|
|
84
|
+
* **Important:** If you are running a server that is not expected to be exposed to the network, use `hostname: "localhost"`.
|
|
85
|
+
*/
|
|
86
|
+
hostname?: string;
|
|
87
|
+
/**
|
|
88
|
+
* Enabling this option allows multiple processes to bind to the same port, which is useful for load balancing.
|
|
89
|
+
*
|
|
90
|
+
* **Note:** Despite Node.js built-in behavior that has `exclusive` flag (opposite of `reusePort`) enabled by default, srvx uses non-exclusive mode for consistency.
|
|
91
|
+
*/
|
|
92
|
+
reusePort?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* The protocol to use for the server.
|
|
95
|
+
*
|
|
96
|
+
* Possible values are `http` and `https`.
|
|
97
|
+
*
|
|
98
|
+
* If `protocol` is not set, Server will use `http` as the default protocol or `https` if both `tls.cert` and `tls.key` options are provided.
|
|
99
|
+
*/
|
|
100
|
+
protocol?: "http" | "https";
|
|
101
|
+
/**
|
|
102
|
+
* If set to `true`, server will not print the listening address.
|
|
103
|
+
*/
|
|
104
|
+
silent?: boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Graceful shutdown on SIGINT and SIGTERM signals.
|
|
107
|
+
*
|
|
108
|
+
* Supported for Node.js, Deno and Bun runtimes.
|
|
109
|
+
*
|
|
110
|
+
* @default true (disabled in test and ci environments)
|
|
111
|
+
*/
|
|
112
|
+
gracefulShutdown?: boolean | {
|
|
113
|
+
gracefulTimeout?: number;
|
|
114
|
+
forceTimeout?: number;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Maximum allowed size (in bytes) for the request body.
|
|
118
|
+
*
|
|
119
|
+
* As the body is read, its accumulated length is tracked and, once it exceeds
|
|
120
|
+
* this limit, reading is aborted and rejects with a `413`-style error (the error
|
|
121
|
+
* has `statusCode: 413`, `status: 413` and `code: "ERR_BODY_TOO_LARGE"`) so a
|
|
122
|
+
* handler can map it to an HTTP 413 (Payload Too Large) response.
|
|
123
|
+
*
|
|
124
|
+
* The limit covers the buffered reads (`request.text()` / `request.json()`) as
|
|
125
|
+
* well as the streamed body (`request.body`, and therefore `arrayBuffer()` /
|
|
126
|
+
* `blob()` / `bytes()` / `formData()`).
|
|
127
|
+
*
|
|
128
|
+
* Runtime support:
|
|
129
|
+
* - **Node**: enforced by srvx (body stream is size-limited).
|
|
130
|
+
* - **Bun**: mapped to Bun's native `maxRequestBodySize` (413 before the handler).
|
|
131
|
+
* - **Deno**: enforced by srvx (request body stream is size-limited).
|
|
132
|
+
*
|
|
133
|
+
* @default undefined (no limit)
|
|
134
|
+
*/
|
|
135
|
+
maxRequestBodySize?: number;
|
|
136
|
+
/**
|
|
137
|
+
* Whether to trust `X-Forwarded-*` headers (`X-Forwarded-Proto`,
|
|
138
|
+
* `X-Forwarded-Host`, `X-Forwarded-For`, and the HTTP/2 `:scheme`) when
|
|
139
|
+
* deriving `request.url` and `request.ip`.
|
|
140
|
+
*
|
|
141
|
+
* Any client can send `X-Forwarded-Proto: https`, `X-Forwarded-Host` or
|
|
142
|
+
* `X-Forwarded-For`, so trusting them lets a request masquerade as `https:`,
|
|
143
|
+
* forge its host, or spoof its client IP. Only enable this when a proxy you
|
|
144
|
+
* control sits in front and overwrites the headers.
|
|
145
|
+
*
|
|
146
|
+
* - `false` (default): ignore the headers; use the real connection protocol,
|
|
147
|
+
* the on-the-wire `Host` header and the socket peer address.
|
|
148
|
+
* - `true`: always trust the headers.
|
|
149
|
+
* - `"loopback"`: trust them only when the proxy connects from a loopback
|
|
150
|
+
* address (`127.0.0.0/8` or `::1`).
|
|
151
|
+
* - `string[]`: trust them only when the proxy's address is in the list.
|
|
152
|
+
*
|
|
153
|
+
* Applies to the Node, AWS Lambda, Bun and Deno adapters.
|
|
154
|
+
*
|
|
155
|
+
* @default false
|
|
156
|
+
*/
|
|
157
|
+
trustProxy?: TrustProxyOption;
|
|
158
|
+
/**
|
|
159
|
+
* TLS server options.
|
|
160
|
+
*/
|
|
161
|
+
tls?: {
|
|
162
|
+
/**
|
|
163
|
+
* File path or inlined TLS certificate in PEM format (required).
|
|
164
|
+
*/
|
|
165
|
+
cert?: string;
|
|
166
|
+
/**
|
|
167
|
+
* File path or inlined TLS private key in PEM format (required).
|
|
168
|
+
*/
|
|
169
|
+
key?: string;
|
|
170
|
+
/**
|
|
171
|
+
* Passphrase for the private key (optional).
|
|
172
|
+
*/
|
|
173
|
+
passphrase?: string;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Node.js server options.
|
|
177
|
+
*/
|
|
178
|
+
node?: (NodeHttp.ServerOptions | NodeHttps.ServerOptions | NodeHttp2.ServerOptions) & NodeNet.ListenOptions & {
|
|
179
|
+
http2?: boolean;
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Bun server options
|
|
183
|
+
*
|
|
184
|
+
* @docs https://bun.sh/docs/api/http
|
|
185
|
+
*/
|
|
186
|
+
bun?: Omit<Bun.Serve.Options<any>, "fetch">;
|
|
187
|
+
/**
|
|
188
|
+
* Deno server options
|
|
189
|
+
*
|
|
190
|
+
* @docs https://docs.deno.com/api/deno/~/Deno.serve
|
|
191
|
+
*/
|
|
192
|
+
deno?: Deno.ServeOptions;
|
|
193
|
+
/**
|
|
194
|
+
* Service worker options
|
|
195
|
+
*/
|
|
196
|
+
serviceWorker?: {
|
|
197
|
+
/**
|
|
198
|
+
* The path to the service worker file to be registered.
|
|
199
|
+
*/
|
|
200
|
+
url?: string;
|
|
201
|
+
/**
|
|
202
|
+
* The scope of the service worker.
|
|
203
|
+
*
|
|
204
|
+
*/
|
|
205
|
+
scope?: string;
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
interface Server<Handler = ServerHandler> {
|
|
209
|
+
/**
|
|
210
|
+
* Current runtime name
|
|
211
|
+
*/
|
|
212
|
+
readonly runtime: "node" | "deno" | "bun" | "bunny" | "cloudflare" | "service-worker" | "aws-lambda" | "generic";
|
|
213
|
+
/**
|
|
214
|
+
* Server options
|
|
215
|
+
*/
|
|
216
|
+
readonly options: ServerOptions & {
|
|
217
|
+
middleware: ServerMiddleware[];
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Server URL address.
|
|
221
|
+
*/
|
|
222
|
+
readonly url?: string;
|
|
223
|
+
/**
|
|
224
|
+
* Node.js context.
|
|
225
|
+
*/
|
|
226
|
+
readonly node?: {
|
|
227
|
+
server?: NodeHttp.Server | NodeHttp2.Http2Server;
|
|
228
|
+
handler: (req: NodeServerRequest, res: NodeServerResponse) => void | Promise<void>;
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* Bun context.
|
|
232
|
+
*/
|
|
233
|
+
readonly bun?: {
|
|
234
|
+
server?: Bun.Server<any>;
|
|
235
|
+
};
|
|
236
|
+
/**
|
|
237
|
+
* Deno context.
|
|
238
|
+
*/
|
|
239
|
+
readonly deno?: {
|
|
240
|
+
server?: Deno.HttpServer;
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* Server fetch handler
|
|
244
|
+
*/
|
|
245
|
+
readonly fetch: Handler;
|
|
246
|
+
/**
|
|
247
|
+
* Start listening for incoming requests.
|
|
248
|
+
* When `manual` option is enabled, this method needs to be called explicitly to begin accepting connections.
|
|
249
|
+
*/
|
|
250
|
+
serve(): void | Promise<Server<Handler>>;
|
|
251
|
+
/**
|
|
252
|
+
* Returns a promise that resolves when the server is ready.
|
|
253
|
+
*/
|
|
254
|
+
ready(): Promise<Server<Handler>>;
|
|
255
|
+
/**
|
|
256
|
+
* Register a background task that the server should await before closing.
|
|
257
|
+
*
|
|
258
|
+
* Same as `request.waitUntil` but available at the server level for use outside of request handlers.
|
|
259
|
+
*/
|
|
260
|
+
readonly waitUntil?: (promise: Promise<unknown>) => void;
|
|
261
|
+
/**
|
|
262
|
+
* Stop listening to prevent new connections from being accepted.
|
|
263
|
+
*
|
|
264
|
+
* By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops.
|
|
265
|
+
*
|
|
266
|
+
* @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections.
|
|
267
|
+
* @default false
|
|
268
|
+
*/
|
|
269
|
+
close(closeActiveConnections?: boolean): Promise<void>;
|
|
270
|
+
}
|
|
271
|
+
interface ServerRuntimeContext {
|
|
272
|
+
name: "node" | "deno" | "bun" | "bunny" | "cloudflare" | "aws-lambda" | (string & {});
|
|
273
|
+
/**
|
|
274
|
+
* Underlying Node.js server request info.
|
|
275
|
+
*/
|
|
276
|
+
node?: {
|
|
277
|
+
req: NodeServerRequest;
|
|
278
|
+
res?: NodeServerResponse;
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* Underlying Deno server request info.
|
|
282
|
+
*/
|
|
283
|
+
deno?: {
|
|
284
|
+
info: Deno.ServeHandlerInfo<Deno.NetAddr>;
|
|
285
|
+
};
|
|
286
|
+
/**
|
|
287
|
+
* Underlying Bun server request context.
|
|
288
|
+
*/
|
|
289
|
+
bun?: {
|
|
290
|
+
server: Bun.Server<any>;
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* Underlying Cloudflare request context.
|
|
294
|
+
*/
|
|
295
|
+
cloudflare?: {
|
|
296
|
+
context: CF.ExecutionContext;
|
|
297
|
+
env: IsAny<typeof import("cloudflare:workers")> extends true ? Record<string, unknown> : typeof import("cloudflare:workers").env;
|
|
298
|
+
};
|
|
299
|
+
awsLambda?: {
|
|
300
|
+
context: AWS.Context;
|
|
301
|
+
event: AWS.APIGatewayProxyEvent | AWS.APIGatewayProxyEventV2;
|
|
302
|
+
};
|
|
303
|
+
serviceWorker?: {
|
|
304
|
+
event: FetchEvent;
|
|
305
|
+
};
|
|
306
|
+
netlify?: {
|
|
307
|
+
context: any;
|
|
308
|
+
};
|
|
309
|
+
stormkit?: {
|
|
310
|
+
event: any;
|
|
311
|
+
context: any;
|
|
312
|
+
};
|
|
313
|
+
vercel?: {
|
|
314
|
+
context: {
|
|
315
|
+
waitUntil?: (promise: Promise<any>) => void;
|
|
316
|
+
};
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
interface ServerRequestContext {
|
|
320
|
+
[key: string]: unknown;
|
|
321
|
+
}
|
|
322
|
+
interface ServerRequest extends Request {
|
|
323
|
+
/**
|
|
324
|
+
* Access to Node.js native instance of request.
|
|
325
|
+
*
|
|
326
|
+
* See https://srvx.h3.dev/guide/node#noderequest
|
|
327
|
+
*/
|
|
328
|
+
_request?: Request;
|
|
329
|
+
/**
|
|
330
|
+
* Access to the parsed URL
|
|
331
|
+
*/
|
|
332
|
+
_url?: URL;
|
|
333
|
+
/**
|
|
334
|
+
* Runtime specific request context.
|
|
335
|
+
*/
|
|
336
|
+
runtime?: ServerRuntimeContext;
|
|
337
|
+
/**
|
|
338
|
+
* IP address of the client.
|
|
339
|
+
*/
|
|
340
|
+
ip?: string | undefined;
|
|
341
|
+
/**
|
|
342
|
+
* Arbitrary context related to the request.
|
|
343
|
+
*/
|
|
344
|
+
context?: ServerRequestContext;
|
|
345
|
+
/**
|
|
346
|
+
* Tell the runtime about an ongoing operation that shouldn't close until the promise resolves.
|
|
347
|
+
*/
|
|
348
|
+
waitUntil?: (promise: Promise<unknown>) => void | Promise<void>;
|
|
349
|
+
}
|
|
350
|
+
type FetchHandler = (request: Request) => Response | Promise<Response>;
|
|
351
|
+
type ErrorHandler = (error: unknown) => Response | Promise<Response>;
|
|
352
|
+
type BunFetchHandler = (request: Request, server?: Bun.Server<any>) => Response | Promise<Response>;
|
|
353
|
+
type DenoFetchHandler = (request: Request, info?: Deno.ServeHandlerInfo<Deno.NetAddr>) => Response | Promise<Response>;
|
|
354
|
+
type NodeServerRequest = NodeHttp.IncomingMessage | NodeHttp2.Http2ServerRequest;
|
|
355
|
+
type NodeServerResponse = NodeHttp.ServerResponse | NodeHttp2.Http2ServerResponse;
|
|
356
|
+
type NodeHttp1Handler = (req: NodeHttp.IncomingMessage, res: NodeHttp.ServerResponse) => void | Promise<void>;
|
|
357
|
+
type NodeHttp2Handler = (req: NodeHttp2.Http2ServerRequest, res: NodeHttp2.Http2ServerResponse) => void | Promise<void>;
|
|
358
|
+
type NodeHttpHandler = NodeHttp1Handler | NodeHttp2Handler;
|
|
359
|
+
type NodeHTTP1Middleware = (req: NodeHttp.IncomingMessage, res: NodeHttp.ServerResponse, next: (error?: Error) => void) => unknown | Promise<unknown>;
|
|
360
|
+
type NodeHTTP2Middleware = (req: NodeHttp2.Http2ServerRequest, res: NodeHttp2.Http2ServerResponse, next: (error?: Error) => void) => unknown | Promise<unknown>;
|
|
361
|
+
type NodeHTTPMiddleware = NodeHTTP1Middleware | NodeHTTP2Middleware;
|
|
362
|
+
type CloudflareFetchHandler = CF.ExportedHandlerFetchHandler;
|
|
363
|
+
export { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FastResponse, FastURL, FetchHandler, NodeHTTP1Middleware, NodeHTTP2Middleware, NodeHTTPMiddleware, NodeHttp1Handler, NodeHttp2Handler, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerRequest, ServerRequestContext, ServerRuntimeContext, TrustProxyOption, serve };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FetchHandler, ServerOptions } from "../types.mjs";
|
|
1
|
+
import { FetchHandler, ServerOptions, TrustProxyOption } from "../_chunks/types.mjs";
|
|
2
2
|
import * as AWS from "aws-lambda";
|
|
3
3
|
type AWSLambdaResponseStream = NodeJS.WritableStream & {
|
|
4
4
|
setContentType(contentType: string): void;
|
|
@@ -8,7 +8,7 @@ type AwsLambdaEvent = AWS.APIGatewayProxyEvent | AWS.APIGatewayProxyEventV2;
|
|
|
8
8
|
type AWSLambdaHandler = (event: AwsLambdaEvent, context: AWS.Context) => MaybePromise<AWS.APIGatewayProxyResult | AWS.APIGatewayProxyResultV2>;
|
|
9
9
|
type AWSLambdaStreamingHandler = (event: AwsLambdaEvent, responseStream: AWSLambdaResponseStream, context: AWS.Context) => MaybePromise<void>;
|
|
10
10
|
declare function toLambdaHandler(options: ServerOptions): AWSLambdaHandler;
|
|
11
|
-
declare function handleLambdaEvent(fetchHandler: FetchHandler, event: AwsLambdaEvent, context: AWS.Context): Promise<AWS.APIGatewayProxyResult | AWS.APIGatewayProxyResultV2>;
|
|
12
|
-
declare function handleLambdaEventWithStream(fetchHandler: FetchHandler, event: AwsLambdaEvent, responseStream: AWSLambdaResponseStream, context: AWS.Context): Promise<void>;
|
|
11
|
+
declare function handleLambdaEvent(fetchHandler: FetchHandler, event: AwsLambdaEvent, context: AWS.Context, trustProxy?: TrustProxyOption): Promise<AWS.APIGatewayProxyResult | AWS.APIGatewayProxyResultV2>;
|
|
12
|
+
declare function handleLambdaEventWithStream(fetchHandler: FetchHandler, event: AwsLambdaEvent, responseStream: AWSLambdaResponseStream, context: AWS.Context, trustProxy?: TrustProxyOption): Promise<void>;
|
|
13
13
|
declare function invokeLambdaHandler(handler: AWSLambdaHandler, request: Request): Promise<Response>;
|
|
14
14
|
export { AWSLambdaHandler, type AWSLambdaResponseStream, AWSLambdaStreamingHandler, AwsLambdaEvent, handleLambdaEvent, handleLambdaEventWithStream, invokeLambdaHandler, toLambdaHandler };
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { errorPlugin, wrapFetch } from "../_chunks/_plugins.mjs";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { firstForwardedValue, isTrustedProxy } from "../_chunks/_trust-proxy.mjs";
|
|
3
|
+
function awsRequest(event, context, trustProxy) {
|
|
4
|
+
const sourceIp = awsEventIP(event);
|
|
5
|
+
const trusted = isTrustedProxy(trustProxy, sourceIp);
|
|
6
|
+
const req = new Request(awsEventURL(event, trusted), {
|
|
4
7
|
method: awsEventMethod(event),
|
|
5
8
|
headers: awsEventHeaders(event),
|
|
6
9
|
body: awsEventBody(event)
|
|
@@ -12,7 +15,7 @@ function awsRequest(event, context) {
|
|
|
12
15
|
context
|
|
13
16
|
}
|
|
14
17
|
};
|
|
15
|
-
req.ip =
|
|
18
|
+
req.ip = awsEventClientIP(event, sourceIp, trusted);
|
|
16
19
|
return req;
|
|
17
20
|
}
|
|
18
21
|
function awsEventMethod(event) {
|
|
@@ -21,11 +24,18 @@ function awsEventMethod(event) {
|
|
|
21
24
|
function awsEventIP(event) {
|
|
22
25
|
return event.requestContext?.http?.sourceIp || event.requestContext?.identity?.sourceIp;
|
|
23
26
|
}
|
|
24
|
-
function
|
|
25
|
-
|
|
27
|
+
function awsEventClientIP(event, sourceIp, trusted) {
|
|
28
|
+
if (trusted) {
|
|
29
|
+
const forwarded = firstForwardedValue(event.headers["X-Forwarded-For"] || event.headers["x-forwarded-for"]);
|
|
30
|
+
if (forwarded) return forwarded;
|
|
31
|
+
}
|
|
32
|
+
return sourceIp;
|
|
33
|
+
}
|
|
34
|
+
function awsEventURL(event, trusted) {
|
|
26
35
|
const path = event.path || event.rawPath;
|
|
27
36
|
const query = awsEventQuery(event);
|
|
28
|
-
const
|
|
37
|
+
const hostname = (trusted ? firstForwardedValue(event.headers["X-Forwarded-Host"] || event.headers["x-forwarded-host"]) : void 0) || event.headers.host || event.headers.Host || event.requestContext?.domainName || ".";
|
|
38
|
+
const protocol = (trusted ? firstForwardedValue(event.headers["X-Forwarded-Proto"] || event.headers["x-forwarded-proto"]) : void 0) === "http" ? "http" : "https";
|
|
29
39
|
return new URL(`${path}${query ? `?${query}` : ""}`, `${protocol}://${hostname}`);
|
|
30
40
|
}
|
|
31
41
|
function awsEventQuery(event) {
|
|
@@ -253,16 +263,16 @@ function toLambdaHandler(options) {
|
|
|
253
263
|
const server = new AWSLambdaServer(options);
|
|
254
264
|
return (event, context) => server.fetch(event, context);
|
|
255
265
|
}
|
|
256
|
-
async function handleLambdaEvent(fetchHandler, event, context) {
|
|
257
|
-
const response = await fetchHandler(awsRequest(event, context));
|
|
266
|
+
async function handleLambdaEvent(fetchHandler, event, context, trustProxy) {
|
|
267
|
+
const response = await fetchHandler(awsRequest(event, context, trustProxy));
|
|
258
268
|
return {
|
|
259
269
|
statusCode: response.status,
|
|
260
270
|
...awsResponseHeaders(response, event),
|
|
261
271
|
...await awsResponseBody(response)
|
|
262
272
|
};
|
|
263
273
|
}
|
|
264
|
-
async function handleLambdaEventWithStream(fetchHandler, event, responseStream, context) {
|
|
265
|
-
await awsStreamResponse(await fetchHandler(awsRequest(event, context)), responseStream, event);
|
|
274
|
+
async function handleLambdaEventWithStream(fetchHandler, event, responseStream, context, trustProxy) {
|
|
275
|
+
await awsStreamResponse(await fetchHandler(awsRequest(event, context, trustProxy)), responseStream, event);
|
|
266
276
|
}
|
|
267
277
|
async function invokeLambdaHandler(handler, request) {
|
|
268
278
|
return awsResultToResponse(await handler(await requestToAwsEvent(request), createMockContext()));
|
|
@@ -279,7 +289,7 @@ var AWSLambdaServer = class {
|
|
|
279
289
|
for (const plugin of options.plugins || []) plugin(this);
|
|
280
290
|
errorPlugin(this);
|
|
281
291
|
const fetchHandler = wrapFetch(this);
|
|
282
|
-
this.fetch = (event, context) => handleLambdaEvent(fetchHandler, event, context);
|
|
292
|
+
this.fetch = (event, context) => handleLambdaEvent(fetchHandler, event, context, this.options.trustProxy);
|
|
283
293
|
}
|
|
284
294
|
serve() {}
|
|
285
295
|
ready() {
|
package/dist/adapters/bun.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BunFetchHandler, Server, ServerOptions } from "../types.mjs";
|
|
1
|
+
import { BunFetchHandler, Server, ServerOptions } from "../_chunks/types.mjs";
|
|
2
2
|
import { FastURL } from "../_chunks/_url.mjs";
|
|
3
3
|
import * as bun from "bun";
|
|
4
4
|
declare const FastResponse: typeof globalThis.Response;
|
package/dist/adapters/bun.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FastURL } from "../_chunks/_url.mjs";
|
|
2
2
|
import { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions, toNativeResponse } from "../_chunks/_utils2.mjs";
|
|
3
3
|
import { gracefulShutdownPlugin, wrapFetch } from "../_chunks/_plugins.mjs";
|
|
4
|
+
import { trustProxyPlugin } from "../_chunks/_trust-proxy.mjs";
|
|
4
5
|
const FastResponse = Response;
|
|
5
6
|
function serve(options) {
|
|
6
7
|
return new BunServer(options);
|
|
@@ -19,6 +20,7 @@ var BunServer = class {
|
|
|
19
20
|
middleware: [...options.middleware || []]
|
|
20
21
|
};
|
|
21
22
|
for (const plugin of options.plugins || []) plugin(this);
|
|
23
|
+
trustProxyPlugin(this);
|
|
22
24
|
gracefulShutdownPlugin(this);
|
|
23
25
|
const fetchHandler = wrapFetch(this);
|
|
24
26
|
const loader = globalThis.__srvxLoader__;
|
|
@@ -41,6 +43,7 @@ var BunServer = class {
|
|
|
41
43
|
},
|
|
42
44
|
ip: {
|
|
43
45
|
enumerable: true,
|
|
46
|
+
configurable: true,
|
|
44
47
|
get() {
|
|
45
48
|
return server?.requestIP(request)?.address;
|
|
46
49
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Server, ServerOptions } from "../types.mjs";
|
|
1
|
+
import { Server, ServerOptions } from "../_chunks/types.mjs";
|
|
2
2
|
declare const FastURL: typeof globalThis.URL;
|
|
3
3
|
declare const FastResponse: typeof globalThis.Response;
|
|
4
4
|
declare function serve(options: ServerOptions): Server;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Server, ServerOptions } from "../types.mjs";
|
|
1
|
+
import { Server, ServerOptions } from "../_chunks/types.mjs";
|
|
2
2
|
import * as CF from "@cloudflare/workers-types";
|
|
3
3
|
declare const FastURL: typeof globalThis.URL;
|
|
4
4
|
declare const FastResponse: typeof globalThis.Response;
|
package/dist/adapters/deno.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DenoFetchHandler, Server, ServerOptions } from "../types.mjs";
|
|
1
|
+
import { DenoFetchHandler, Server, ServerOptions } from "../_chunks/types.mjs";
|
|
2
2
|
import { FastURL } from "../_chunks/_url.mjs";
|
|
3
3
|
declare const FastResponse: typeof globalThis.Response;
|
|
4
4
|
declare function serve(options: ServerOptions): DenoServer;
|
package/dist/adapters/deno.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FastURL } from "../_chunks/_url.mjs";
|
|
2
2
|
import { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions, toNativeResponse } from "../_chunks/_utils2.mjs";
|
|
3
3
|
import { gracefulShutdownPlugin, wrapFetch } from "../_chunks/_plugins.mjs";
|
|
4
|
+
import { trustProxyPlugin } from "../_chunks/_trust-proxy.mjs";
|
|
4
5
|
import { limitRequestBody } from "../_chunks/_body-limit.mjs";
|
|
5
6
|
const FastResponse = Response;
|
|
6
7
|
function serve(options) {
|
|
@@ -22,6 +23,7 @@ var DenoServer = class {
|
|
|
22
23
|
middleware: [...options.middleware || []]
|
|
23
24
|
};
|
|
24
25
|
for (const plugin of options.plugins || []) plugin(this);
|
|
26
|
+
trustProxyPlugin(this);
|
|
25
27
|
gracefulShutdownPlugin(this);
|
|
26
28
|
const fetchHandler = wrapFetch(this);
|
|
27
29
|
const loader = globalThis.__srvxLoader__;
|
|
@@ -49,6 +51,7 @@ var DenoServer = class {
|
|
|
49
51
|
},
|
|
50
52
|
ip: {
|
|
51
53
|
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
52
55
|
get() {
|
|
53
56
|
return (info?.remoteAddr)?.hostname;
|
|
54
57
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Server, ServerOptions } from "../types.mjs";
|
|
1
|
+
import { Server, ServerOptions } from "../_chunks/types.mjs";
|
|
2
2
|
declare const FastURL: typeof globalThis.URL;
|
|
3
3
|
declare const FastResponse: typeof globalThis.Response;
|
|
4
4
|
declare function serve(options: ServerOptions): Server;
|
package/dist/adapters/node.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FetchHandler, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerOptions, ServerRequest } from "../types.mjs";
|
|
1
|
+
import { FetchHandler, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerOptions, ServerRequest, TrustProxyOption } from "../_chunks/types.mjs";
|
|
2
2
|
import { FastURL } from "../_chunks/_url.mjs";
|
|
3
3
|
import { Readable } from "node:stream";
|
|
4
4
|
type NodeRequestContext = {
|
|
@@ -9,6 +9,11 @@ type NodeRequestContext = {
|
|
|
9
9
|
* buffered reads and the streamed body. See `ServerOptions.maxRequestBodySize`.
|
|
10
10
|
*/
|
|
11
11
|
maxRequestBodySize?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Whether to trust `X-Forwarded-*` / `:scheme` headers when deriving the
|
|
14
|
+
* request protocol, host and client IP. See `ServerOptions.trustProxy`.
|
|
15
|
+
*/
|
|
16
|
+
trustProxy?: TrustProxyOption;
|
|
12
17
|
};
|
|
13
18
|
declare const NodeRequest: {
|
|
14
19
|
new (nodeCtx: NodeRequestContext): ServerRequest;
|
|
@@ -68,6 +73,7 @@ type AdapterMeta = {
|
|
|
68
73
|
*/
|
|
69
74
|
declare function toNodeHandler(handler: FetchHandler & AdapterMeta, options?: {
|
|
70
75
|
maxRequestBodySize?: number;
|
|
76
|
+
trustProxy?: TrustProxyOption;
|
|
71
77
|
}): NodeHttpHandler & AdapterMeta;
|
|
72
78
|
/**
|
|
73
79
|
* Converts a Node.js HTTP handler into a Fetch API handler.
|
package/dist/adapters/node.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FastURL, lazyInherit } from "../_chunks/_url.mjs";
|
|
2
2
|
import { createWaitUntil, fmtURL, printListening, resolvePortAndHost, resolveTLSOptions } from "../_chunks/_utils2.mjs";
|
|
3
3
|
import { errorPlugin, gracefulShutdownPlugin, wrapFetch } from "../_chunks/_plugins.mjs";
|
|
4
|
+
import { HOST_RE, firstForwardedValue, isTrustedProxy } from "../_chunks/_trust-proxy.mjs";
|
|
4
5
|
import { createBodyTooLargeError, limitBodyStream } from "../_chunks/_body-limit.mjs";
|
|
5
6
|
import nodeHTTP, { IncomingMessage, ServerResponse } from "node:http";
|
|
6
7
|
import { Duplex, PassThrough, Readable, addAbortSignal } from "node:stream";
|
|
@@ -122,15 +123,16 @@ function streamBody(stream, nodeRes) {
|
|
|
122
123
|
nodeRes.off("error", streamCancel);
|
|
123
124
|
});
|
|
124
125
|
}
|
|
125
|
-
const HOST_RE = /^(\[(?:[A-Fa-f0-9:.]+)\]|(?:[A-Za-z0-9_-]+\.)*[A-Za-z0-9_-]+|(?:\d{1,3}\.){3}\d{1,3})(:\d{1,5})?$/;
|
|
126
126
|
var NodeRequestURL = class extends FastURL {
|
|
127
|
-
constructor({ req }) {
|
|
127
|
+
constructor({ req, trusted = false }) {
|
|
128
128
|
const path = req.url || "/";
|
|
129
|
-
|
|
129
|
+
const forwardedHost = trusted ? firstForwardedValue(req.headers["x-forwarded-host"]) : void 0;
|
|
130
|
+
let host = (forwardedHost && HOST_RE.test(forwardedHost) ? forwardedHost : void 0) || req.headers.host || req.headers[":authority"];
|
|
130
131
|
if (host && !HOST_RE.test(host)) host = "_invalid_";
|
|
131
132
|
else if (!host) if (req.socket) host = `${req.socket.localFamily === "IPv6" ? "[" + req.socket.localAddress + "]" : req.socket.localAddress}:${req.socket?.localPort || "80"}`;
|
|
132
133
|
else host = "localhost";
|
|
133
|
-
const
|
|
134
|
+
const forwardedProto = trusted ? firstForwardedValue(req.headers["x-forwarded-proto"]) : void 0;
|
|
135
|
+
const protocol = req.socket?.encrypted || forwardedProto === "https" || trusted && req.headers[":scheme"] === "https" ? "https:" : "http:";
|
|
134
136
|
if (path[0] === "/") {
|
|
135
137
|
const qIndex = path.indexOf("?");
|
|
136
138
|
super({
|
|
@@ -252,9 +254,15 @@ const NodeRequest = /* @__PURE__ */ (() => {
|
|
|
252
254
|
#headers;
|
|
253
255
|
#abortController;
|
|
254
256
|
#maxRequestBodySize;
|
|
257
|
+
#trustProxy;
|
|
258
|
+
#ip;
|
|
259
|
+
#ipResolved = false;
|
|
260
|
+
#remoteAddress;
|
|
261
|
+
#trusted;
|
|
255
262
|
constructor(ctx) {
|
|
256
263
|
this.#req = ctx.req;
|
|
257
264
|
this.#maxRequestBodySize = ctx.maxRequestBodySize;
|
|
265
|
+
this.#trustProxy = ctx.trustProxy;
|
|
258
266
|
this.runtime = {
|
|
259
267
|
name: "node",
|
|
260
268
|
node: ctx
|
|
@@ -263,15 +271,31 @@ const NodeRequest = /* @__PURE__ */ (() => {
|
|
|
263
271
|
static [Symbol.hasInstance](val) {
|
|
264
272
|
return val instanceof NativeRequest;
|
|
265
273
|
}
|
|
274
|
+
#resolveTrusted() {
|
|
275
|
+
if (this.#trusted === void 0) {
|
|
276
|
+
this.#remoteAddress = this.#req.socket?.remoteAddress;
|
|
277
|
+
this.#trusted = isTrustedProxy(this.#trustProxy, this.#remoteAddress);
|
|
278
|
+
}
|
|
279
|
+
return this.#trusted;
|
|
280
|
+
}
|
|
266
281
|
get ip() {
|
|
267
|
-
return this.#
|
|
282
|
+
if (this.#ipResolved) return this.#ip;
|
|
283
|
+
this.#ipResolved = true;
|
|
284
|
+
if (this.#resolveTrusted()) {
|
|
285
|
+
const forwarded = firstForwardedValue(this.#req.headers["x-forwarded-for"]);
|
|
286
|
+
if (forwarded) return this.#ip = forwarded;
|
|
287
|
+
}
|
|
288
|
+
return this.#ip = this.#remoteAddress;
|
|
268
289
|
}
|
|
269
290
|
get method() {
|
|
270
291
|
if (this.#request) return this.#request.method;
|
|
271
292
|
return this.#req.method || "GET";
|
|
272
293
|
}
|
|
273
294
|
get _url() {
|
|
274
|
-
return this.#url ||= new NodeRequestURL({
|
|
295
|
+
return this.#url ||= new NodeRequestURL({
|
|
296
|
+
req: this.#req,
|
|
297
|
+
trusted: this.#resolveTrusted()
|
|
298
|
+
});
|
|
275
299
|
}
|
|
276
300
|
set _url(url) {
|
|
277
301
|
this.#url = url;
|
|
@@ -813,7 +837,8 @@ function toNodeHandler(handler, options) {
|
|
|
813
837
|
const res = handler(new NodeRequest({
|
|
814
838
|
req: nodeReq,
|
|
815
839
|
res: nodeRes,
|
|
816
|
-
maxRequestBodySize: options?.maxRequestBodySize
|
|
840
|
+
maxRequestBodySize: options?.maxRequestBodySize,
|
|
841
|
+
trustProxy: options?.trustProxy
|
|
817
842
|
}));
|
|
818
843
|
return res instanceof Promise ? res.then((resolvedRes) => sendNodeResponse(nodeRes, resolvedRes)) : sendNodeResponse(nodeRes, res);
|
|
819
844
|
}
|
|
@@ -867,7 +892,8 @@ var NodeServer = class {
|
|
|
867
892
|
const request = new NodeRequest({
|
|
868
893
|
req: nodeReq,
|
|
869
894
|
res: nodeRes,
|
|
870
|
-
maxRequestBodySize: this.options.maxRequestBodySize
|
|
895
|
+
maxRequestBodySize: this.options.maxRequestBodySize,
|
|
896
|
+
trustProxy: this.options.trustProxy
|
|
871
897
|
});
|
|
872
898
|
request.waitUntil = this.#wait?.waitUntil;
|
|
873
899
|
const res = fetchHandler(request);
|
|
@@ -891,11 +917,7 @@ var NodeServer = class {
|
|
|
891
917
|
port,
|
|
892
918
|
host,
|
|
893
919
|
exclusive: !this.options.reusePort,
|
|
894
|
-
...tls
|
|
895
|
-
cert: tls.cert,
|
|
896
|
-
key: tls.key,
|
|
897
|
-
passphrase: tls.passphrase
|
|
898
|
-
} : {},
|
|
920
|
+
...tls,
|
|
899
921
|
...this.options.node
|
|
900
922
|
};
|
|
901
923
|
let server;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Server, ServerOptions, ServerRequest } from "../types.mjs";
|
|
1
|
+
import { Server, ServerOptions, ServerRequest } from "../_chunks/types.mjs";
|
|
2
2
|
declare const FastURL: typeof globalThis.URL;
|
|
3
3
|
declare const FastResponse: typeof globalThis.Response;
|
|
4
4
|
type ServiceWorkerHandler = (request: ServerRequest, event: FetchEvent) => Response | Promise<Response>;
|
package/dist/cli.mjs
CHANGED
package/dist/log.d.mts
CHANGED
package/dist/mtls.d.mts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { ServerPlugin } from "./_chunks/types.mjs";
|
|
2
|
+
import * as TLS from "node:tls";
|
|
3
|
+
/**
|
|
4
|
+
* TLS connection state for the current request.
|
|
5
|
+
*
|
|
6
|
+
* Available when the request was served over TLS. The peer certificate fields are populated only when the server requested a client certificate (`tls.requestCert`) and the client presented one.
|
|
7
|
+
*
|
|
8
|
+
* @note Available only on srvx's Node.js adapter — on Node.js, or on Deno (2.8+) via `node:https`. It is **not** available on Bun: neither native `Bun.serve` nor Bun's `node:http(s)` server exposes the peer certificate to the handler (they enforce `requestCert` / `rejectUnauthorized` at the handshake, but drop the certificate), so unlike Deno the `srvx/node` adapter is not a workaround. Verified against the real Bun runtime (Bun 1.3.14); `bun vitest` without the `--bun` flag silently falls back to Node, which can mask this. See https://github.com/oven-sh/bun/issues/16254
|
|
9
|
+
*/
|
|
10
|
+
interface ServerRequestTLS {
|
|
11
|
+
/**
|
|
12
|
+
* The client (peer) certificate, if one was requested and presented.
|
|
13
|
+
*
|
|
14
|
+
* Empty object (`{}`) if the peer did not provide a certificate.
|
|
15
|
+
*/
|
|
16
|
+
peerCertificate?: TLS.PeerCertificate;
|
|
17
|
+
/**
|
|
18
|
+
* `true` if the peer certificate was signed by one of the trusted CAs.
|
|
19
|
+
*/
|
|
20
|
+
authorized?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The reason the peer certificate failed verification, if any.
|
|
23
|
+
*/
|
|
24
|
+
authorizationError?: Error | string;
|
|
25
|
+
/**
|
|
26
|
+
* The negotiated TLS protocol version, e.g. `"TLSv1.3"`.
|
|
27
|
+
*/
|
|
28
|
+
protocol?: string | null;
|
|
29
|
+
/**
|
|
30
|
+
* The negotiated cipher suite.
|
|
31
|
+
*/
|
|
32
|
+
cipher?: TLS.CipherNameAndProtocol;
|
|
33
|
+
}
|
|
34
|
+
declare module "srvx" {
|
|
35
|
+
interface ServerRequest {
|
|
36
|
+
/**
|
|
37
|
+
* TLS connection state, including the client (peer) certificate for mutual TLS.
|
|
38
|
+
*
|
|
39
|
+
* Populated by the {@link mtls} plugin. `undefined` when the request was not served over TLS.
|
|
40
|
+
*/
|
|
41
|
+
tls?: ServerRequestTLS | undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
declare module "./types.ts" {
|
|
45
|
+
interface ServerRequest {
|
|
46
|
+
tls?: ServerRequestTLS | undefined;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Options for the {@link mtls} plugin.
|
|
51
|
+
*/
|
|
52
|
+
interface MTLSOptions {
|
|
53
|
+
/**
|
|
54
|
+
* File path(s) or inlined CA certificate(s) in PEM format used to verify client certificates.
|
|
55
|
+
*
|
|
56
|
+
* When set, the well-known Mozilla CAs are replaced by the provided ones.
|
|
57
|
+
*/
|
|
58
|
+
ca?: string | string[];
|
|
59
|
+
/**
|
|
60
|
+
* Request a certificate from connecting clients.
|
|
61
|
+
*
|
|
62
|
+
* @default true
|
|
63
|
+
*/
|
|
64
|
+
requestCert?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Reject the TLS handshake itself when the client certificate is not signed by one of
|
|
67
|
+
* the trusted `ca` certificates — the connection never reaches the `fetch` handler, so
|
|
68
|
+
* checking `request.tls.authorized` in application code is unreachable at this setting.
|
|
69
|
+
*
|
|
70
|
+
* Set to `false` to let the handshake complete regardless and instead expose the
|
|
71
|
+
* unverified certificate via `request.tls` with `authorized: false`, so your handler
|
|
72
|
+
* can decide how to respond.
|
|
73
|
+
*
|
|
74
|
+
* @default true (Node.js default when `requestCert` is enabled)
|
|
75
|
+
*/
|
|
76
|
+
rejectUnauthorized?: boolean;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Mutual TLS (mTLS) plugin for the Node.js adapter.
|
|
80
|
+
*
|
|
81
|
+
* Requests a client certificate during the TLS handshake and exposes it — together
|
|
82
|
+
* with the negotiated protocol and cipher — on {@link ServerRequestTLS | `request.tls`}.
|
|
83
|
+
*
|
|
84
|
+
* Only srvx's Node.js adapter can deliver this (`import { serve } from "srvx/node"`),
|
|
85
|
+
* on Node.js or Deno (via `node:https`). Native `Deno.serve` / `Bun.serve` and Bun's
|
|
86
|
+
* `node:http(s)` server do not expose the peer certificate, so the plugin throws there
|
|
87
|
+
* rather than silently doing nothing. It also requires the server to be configured for
|
|
88
|
+
* TLS (`tls.cert` / `tls.key`) and throws otherwise, since mutual TLS cannot run over
|
|
89
|
+
* plain HTTP.
|
|
90
|
+
*
|
|
91
|
+
* With the default `rejectUnauthorized: true`, unauthenticated clients are rejected
|
|
92
|
+
* during the TLS handshake and never reach the `fetch` handler. Set it to `false` to
|
|
93
|
+
* let every handshake complete and enforce authorization yourself via
|
|
94
|
+
* `request.tls.authorized`, as in the example below.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```js
|
|
98
|
+
* import { serve } from "srvx/node";
|
|
99
|
+
* import { mtls } from "srvx/mtls";
|
|
100
|
+
*
|
|
101
|
+
* serve({
|
|
102
|
+
* tls: { cert, key },
|
|
103
|
+
* plugins: [mtls({ ca, requestCert: true, rejectUnauthorized: false })],
|
|
104
|
+
* fetch: (request) => {
|
|
105
|
+
* if (!request.tls?.authorized) {
|
|
106
|
+
* return new Response("client certificate required", { status: 401 });
|
|
107
|
+
* }
|
|
108
|
+
* return new Response(`Hello, ${request.tls.peerCertificate?.subject?.CN}`);
|
|
109
|
+
* },
|
|
110
|
+
* });
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
declare function mtls(options?: MTLSOptions): ServerPlugin;
|
|
114
|
+
export { MTLSOptions, ServerRequestTLS, mtls };
|
package/dist/mtls.mjs
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { resolveCertOrKey } from "./_chunks/_utils2.mjs";
|
|
2
|
+
function mtls(options = {}) {
|
|
3
|
+
return (server) => {
|
|
4
|
+
if (server.runtime !== "node") throw new Error(`[srvx] mtls() requires srvx's Node.js adapter (import { serve } from "srvx/node"). The "${server.runtime}" server cannot request or expose client certificates.`);
|
|
5
|
+
if ("Bun" in globalThis) throw new Error("[srvx] mtls() is not available on Bun: Bun does not expose the peer certificate to node:http(s) request handlers. See https://github.com/oven-sh/bun/issues/16254");
|
|
6
|
+
if (server.options.protocol === "http" || !server.options.tls?.cert || !server.options.tls?.key) throw new Error("[srvx] mtls() requires an HTTPS server: set `tls.cert` and `tls.key`. Mutual TLS cannot run over plain HTTP.");
|
|
7
|
+
let ca;
|
|
8
|
+
if (options.ca !== void 0) ca = (Array.isArray(options.ca) ? options.ca : [options.ca]).map((entry) => {
|
|
9
|
+
const resolved = resolveCertOrKey(entry);
|
|
10
|
+
if (!resolved) throw new TypeError("mtls() `ca` entries must be non-empty PEM strings or file paths.");
|
|
11
|
+
return resolved;
|
|
12
|
+
});
|
|
13
|
+
server.options.node = {
|
|
14
|
+
...server.options.node,
|
|
15
|
+
...ca ? { ca } : {},
|
|
16
|
+
requestCert: options.requestCert ?? true,
|
|
17
|
+
...options.rejectUnauthorized === void 0 ? {} : { rejectUnauthorized: options.rejectUnauthorized }
|
|
18
|
+
};
|
|
19
|
+
server.options.middleware.unshift((request, next) => {
|
|
20
|
+
const socket = request.runtime?.node?.req?.socket;
|
|
21
|
+
if (socket && typeof socket.getPeerCertificate === "function") request.tls = {
|
|
22
|
+
peerCertificate: socket.getPeerCertificate(),
|
|
23
|
+
authorized: socket.authorized,
|
|
24
|
+
authorizationError: socket.authorizationError ?? void 0,
|
|
25
|
+
protocol: socket.getProtocol?.() ?? void 0,
|
|
26
|
+
cipher: socket.getCipher?.()
|
|
27
|
+
};
|
|
28
|
+
return next();
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export { mtls };
|
package/dist/static.d.mts
CHANGED
package/dist/tracing.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Server, ServerMiddleware, ServerPlugin, ServerRequest } from "./types.mjs";
|
|
1
|
+
import { Server, ServerMiddleware, ServerPlugin, ServerRequest } from "./_chunks/types.mjs";
|
|
2
2
|
/**
|
|
3
3
|
* @experimental Channel names, event types and config options may change in future releases.
|
|
4
4
|
*/
|
package/dist/types.d.mts
CHANGED
|
@@ -1,325 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import * as NodeHttp2 from "node:http2";
|
|
4
|
-
import * as AWS from "aws-lambda";
|
|
5
|
-
import * as NodeNet from "node:net";
|
|
6
|
-
import * as Bun from "bun";
|
|
7
|
-
import * as CF from "@cloudflare/workers-types";
|
|
8
|
-
type MaybePromise<T> = T | Promise<T>;
|
|
9
|
-
type IsAny<T> = Equal<T, any> extends true ? true : false;
|
|
10
|
-
type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;
|
|
11
|
-
/**
|
|
12
|
-
* Faster URL constructor with lazy access to pathname and search params (For Node, Deno, and Bun).
|
|
13
|
-
*/
|
|
14
|
-
declare const FastURL: typeof globalThis.URL;
|
|
15
|
-
/**
|
|
16
|
-
* Faster Response constructor optimized for Node.js (same as Response for other runtimes).
|
|
17
|
-
*/
|
|
18
|
-
declare const FastResponse: typeof globalThis.Response;
|
|
19
|
-
/**
|
|
20
|
-
* Create a new server instance.
|
|
21
|
-
*/
|
|
22
|
-
declare function serve(options: ServerOptions): Server;
|
|
23
|
-
/**
|
|
24
|
-
* Web fetch compatible request handler
|
|
25
|
-
*/
|
|
26
|
-
type ServerHandler = (request: ServerRequest) => MaybePromise<Response>;
|
|
27
|
-
type ServerMiddleware = (request: ServerRequest, next: () => Response | Promise<Response>) => Response | Promise<Response>;
|
|
28
|
-
type ServerPlugin = (server: Server) => void;
|
|
29
|
-
/**
|
|
30
|
-
* Server options
|
|
31
|
-
*/
|
|
32
|
-
interface ServerOptions {
|
|
33
|
-
/**
|
|
34
|
-
* The fetch handler handles incoming requests.
|
|
35
|
-
*/
|
|
36
|
-
fetch: ServerHandler;
|
|
37
|
-
/**
|
|
38
|
-
* Handle lifecycle errors.
|
|
39
|
-
*
|
|
40
|
-
* @note This handler will set built-in Bun and Deno error handler.
|
|
41
|
-
*/
|
|
42
|
-
error?: ErrorHandler;
|
|
43
|
-
/**
|
|
44
|
-
* Server middleware handlers to run before the main fetch handler.
|
|
45
|
-
*/
|
|
46
|
-
middleware?: ServerMiddleware[];
|
|
47
|
-
/**
|
|
48
|
-
* Server plugins.
|
|
49
|
-
*/
|
|
50
|
-
plugins?: ServerPlugin[];
|
|
51
|
-
/**
|
|
52
|
-
* If set to `true`, server will not start listening automatically.
|
|
53
|
-
*/
|
|
54
|
-
manual?: boolean;
|
|
55
|
-
/**
|
|
56
|
-
* The port server should be listening to.
|
|
57
|
-
*
|
|
58
|
-
* Default is read from `PORT` environment variable or will be `3000`.
|
|
59
|
-
*
|
|
60
|
-
* **Tip:** You can set the port to `0` to use a random port.
|
|
61
|
-
*/
|
|
62
|
-
port?: string | number;
|
|
63
|
-
/**
|
|
64
|
-
* The hostname (IP or resolvable host) server listener should bound to.
|
|
65
|
-
*
|
|
66
|
-
* When not provided, server with listen to all network interfaces by default.
|
|
67
|
-
*
|
|
68
|
-
* **Important:** If you are running a server that is not expected to be exposed to the network, use `hostname: "localhost"`.
|
|
69
|
-
*/
|
|
70
|
-
hostname?: string;
|
|
71
|
-
/**
|
|
72
|
-
* Enabling this option allows multiple processes to bind to the same port, which is useful for load balancing.
|
|
73
|
-
*
|
|
74
|
-
* **Note:** Despite Node.js built-in behavior that has `exclusive` flag (opposite of `reusePort`) enabled by default, srvx uses non-exclusive mode for consistency.
|
|
75
|
-
*/
|
|
76
|
-
reusePort?: boolean;
|
|
77
|
-
/**
|
|
78
|
-
* The protocol to use for the server.
|
|
79
|
-
*
|
|
80
|
-
* Possible values are `http` and `https`.
|
|
81
|
-
*
|
|
82
|
-
* If `protocol` is not set, Server will use `http` as the default protocol or `https` if both `tls.cert` and `tls.key` options are provided.
|
|
83
|
-
*/
|
|
84
|
-
protocol?: "http" | "https";
|
|
85
|
-
/**
|
|
86
|
-
* If set to `true`, server will not print the listening address.
|
|
87
|
-
*/
|
|
88
|
-
silent?: boolean;
|
|
89
|
-
/**
|
|
90
|
-
* Graceful shutdown on SIGINT and SIGTERM signals.
|
|
91
|
-
*
|
|
92
|
-
* Supported for Node.js, Deno and Bun runtimes.
|
|
93
|
-
*
|
|
94
|
-
* @default true (disabled in test and ci environments)
|
|
95
|
-
*/
|
|
96
|
-
gracefulShutdown?: boolean | {
|
|
97
|
-
gracefulTimeout?: number;
|
|
98
|
-
forceTimeout?: number;
|
|
99
|
-
};
|
|
100
|
-
/**
|
|
101
|
-
* Maximum allowed size (in bytes) for the request body.
|
|
102
|
-
*
|
|
103
|
-
* As the body is read, its accumulated length is tracked and, once it exceeds
|
|
104
|
-
* this limit, reading is aborted and rejects with a `413`-style error (the error
|
|
105
|
-
* has `statusCode: 413`, `status: 413` and `code: "ERR_BODY_TOO_LARGE"`) so a
|
|
106
|
-
* handler can map it to an HTTP 413 (Payload Too Large) response.
|
|
107
|
-
*
|
|
108
|
-
* The limit covers the buffered reads (`request.text()` / `request.json()`) as
|
|
109
|
-
* well as the streamed body (`request.body`, and therefore `arrayBuffer()` /
|
|
110
|
-
* `blob()` / `bytes()` / `formData()`).
|
|
111
|
-
*
|
|
112
|
-
* Runtime support:
|
|
113
|
-
* - **Node**: enforced by srvx (body stream is size-limited).
|
|
114
|
-
* - **Bun**: mapped to Bun's native `maxRequestBodySize` (413 before the handler).
|
|
115
|
-
* - **Deno**: enforced by srvx (request body stream is size-limited).
|
|
116
|
-
*
|
|
117
|
-
* @default undefined (no limit)
|
|
118
|
-
*/
|
|
119
|
-
maxRequestBodySize?: number;
|
|
120
|
-
/**
|
|
121
|
-
* TLS server options.
|
|
122
|
-
*/
|
|
123
|
-
tls?: {
|
|
124
|
-
/**
|
|
125
|
-
* File path or inlined TLS certificate in PEM format (required).
|
|
126
|
-
*/
|
|
127
|
-
cert?: string;
|
|
128
|
-
/**
|
|
129
|
-
* File path or inlined TLS private key in PEM format (required).
|
|
130
|
-
*/
|
|
131
|
-
key?: string;
|
|
132
|
-
/**
|
|
133
|
-
* Passphrase for the private key (optional).
|
|
134
|
-
*/
|
|
135
|
-
passphrase?: string;
|
|
136
|
-
};
|
|
137
|
-
/**
|
|
138
|
-
* Node.js server options.
|
|
139
|
-
*/
|
|
140
|
-
node?: (NodeHttp.ServerOptions | NodeHttps.ServerOptions | NodeHttp2.ServerOptions) & NodeNet.ListenOptions & {
|
|
141
|
-
http2?: boolean;
|
|
142
|
-
};
|
|
143
|
-
/**
|
|
144
|
-
* Bun server options
|
|
145
|
-
*
|
|
146
|
-
* @docs https://bun.sh/docs/api/http
|
|
147
|
-
*/
|
|
148
|
-
bun?: Omit<Bun.Serve.Options<any>, "fetch">;
|
|
149
|
-
/**
|
|
150
|
-
* Deno server options
|
|
151
|
-
*
|
|
152
|
-
* @docs https://docs.deno.com/api/deno/~/Deno.serve
|
|
153
|
-
*/
|
|
154
|
-
deno?: Deno.ServeOptions;
|
|
155
|
-
/**
|
|
156
|
-
* Service worker options
|
|
157
|
-
*/
|
|
158
|
-
serviceWorker?: {
|
|
159
|
-
/**
|
|
160
|
-
* The path to the service worker file to be registered.
|
|
161
|
-
*/
|
|
162
|
-
url?: string;
|
|
163
|
-
/**
|
|
164
|
-
* The scope of the service worker.
|
|
165
|
-
*
|
|
166
|
-
*/
|
|
167
|
-
scope?: string;
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
interface Server<Handler = ServerHandler> {
|
|
171
|
-
/**
|
|
172
|
-
* Current runtime name
|
|
173
|
-
*/
|
|
174
|
-
readonly runtime: "node" | "deno" | "bun" | "bunny" | "cloudflare" | "service-worker" | "aws-lambda" | "generic";
|
|
175
|
-
/**
|
|
176
|
-
* Server options
|
|
177
|
-
*/
|
|
178
|
-
readonly options: ServerOptions & {
|
|
179
|
-
middleware: ServerMiddleware[];
|
|
180
|
-
};
|
|
181
|
-
/**
|
|
182
|
-
* Server URL address.
|
|
183
|
-
*/
|
|
184
|
-
readonly url?: string;
|
|
185
|
-
/**
|
|
186
|
-
* Node.js context.
|
|
187
|
-
*/
|
|
188
|
-
readonly node?: {
|
|
189
|
-
server?: NodeHttp.Server | NodeHttp2.Http2Server;
|
|
190
|
-
handler: (req: NodeServerRequest, res: NodeServerResponse) => void | Promise<void>;
|
|
191
|
-
};
|
|
192
|
-
/**
|
|
193
|
-
* Bun context.
|
|
194
|
-
*/
|
|
195
|
-
readonly bun?: {
|
|
196
|
-
server?: Bun.Server<any>;
|
|
197
|
-
};
|
|
198
|
-
/**
|
|
199
|
-
* Deno context.
|
|
200
|
-
*/
|
|
201
|
-
readonly deno?: {
|
|
202
|
-
server?: Deno.HttpServer;
|
|
203
|
-
};
|
|
204
|
-
/**
|
|
205
|
-
* Server fetch handler
|
|
206
|
-
*/
|
|
207
|
-
readonly fetch: Handler;
|
|
208
|
-
/**
|
|
209
|
-
* Start listening for incoming requests.
|
|
210
|
-
* When `manual` option is enabled, this method needs to be called explicitly to begin accepting connections.
|
|
211
|
-
*/
|
|
212
|
-
serve(): void | Promise<Server<Handler>>;
|
|
213
|
-
/**
|
|
214
|
-
* Returns a promise that resolves when the server is ready.
|
|
215
|
-
*/
|
|
216
|
-
ready(): Promise<Server<Handler>>;
|
|
217
|
-
/**
|
|
218
|
-
* Register a background task that the server should await before closing.
|
|
219
|
-
*
|
|
220
|
-
* Same as `request.waitUntil` but available at the server level for use outside of request handlers.
|
|
221
|
-
*/
|
|
222
|
-
readonly waitUntil?: (promise: Promise<unknown>) => void;
|
|
223
|
-
/**
|
|
224
|
-
* Stop listening to prevent new connections from being accepted.
|
|
225
|
-
*
|
|
226
|
-
* By default, it does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops.
|
|
227
|
-
*
|
|
228
|
-
* @param closeActiveConnections Immediately terminate in-flight requests, websockets, and stop accepting new connections.
|
|
229
|
-
* @default false
|
|
230
|
-
*/
|
|
231
|
-
close(closeActiveConnections?: boolean): Promise<void>;
|
|
232
|
-
}
|
|
233
|
-
interface ServerRuntimeContext {
|
|
234
|
-
name: "node" | "deno" | "bun" | "bunny" | "cloudflare" | "aws-lambda" | (string & {});
|
|
235
|
-
/**
|
|
236
|
-
* Underlying Node.js server request info.
|
|
237
|
-
*/
|
|
238
|
-
node?: {
|
|
239
|
-
req: NodeServerRequest;
|
|
240
|
-
res?: NodeServerResponse;
|
|
241
|
-
};
|
|
242
|
-
/**
|
|
243
|
-
* Underlying Deno server request info.
|
|
244
|
-
*/
|
|
245
|
-
deno?: {
|
|
246
|
-
info: Deno.ServeHandlerInfo<Deno.NetAddr>;
|
|
247
|
-
};
|
|
248
|
-
/**
|
|
249
|
-
* Underlying Bun server request context.
|
|
250
|
-
*/
|
|
251
|
-
bun?: {
|
|
252
|
-
server: Bun.Server<any>;
|
|
253
|
-
};
|
|
254
|
-
/**
|
|
255
|
-
* Underlying Cloudflare request context.
|
|
256
|
-
*/
|
|
257
|
-
cloudflare?: {
|
|
258
|
-
context: CF.ExecutionContext;
|
|
259
|
-
env: IsAny<typeof import("cloudflare:workers")> extends true ? Record<string, unknown> : typeof import("cloudflare:workers").env;
|
|
260
|
-
};
|
|
261
|
-
awsLambda?: {
|
|
262
|
-
context: AWS.Context;
|
|
263
|
-
event: AWS.APIGatewayProxyEvent | AWS.APIGatewayProxyEventV2;
|
|
264
|
-
};
|
|
265
|
-
serviceWorker?: {
|
|
266
|
-
event: FetchEvent;
|
|
267
|
-
};
|
|
268
|
-
netlify?: {
|
|
269
|
-
context: any;
|
|
270
|
-
};
|
|
271
|
-
stormkit?: {
|
|
272
|
-
event: any;
|
|
273
|
-
context: any;
|
|
274
|
-
};
|
|
275
|
-
vercel?: {
|
|
276
|
-
context: {
|
|
277
|
-
waitUntil?: (promise: Promise<any>) => void;
|
|
278
|
-
};
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
interface ServerRequestContext {
|
|
282
|
-
[key: string]: unknown;
|
|
283
|
-
}
|
|
284
|
-
interface ServerRequest extends Request {
|
|
285
|
-
/**
|
|
286
|
-
* Access to Node.js native instance of request.
|
|
287
|
-
*
|
|
288
|
-
* See https://srvx.h3.dev/guide/node#noderequest
|
|
289
|
-
*/
|
|
290
|
-
_request?: Request;
|
|
291
|
-
/**
|
|
292
|
-
* Access to the parsed URL
|
|
293
|
-
*/
|
|
294
|
-
_url?: URL;
|
|
295
|
-
/**
|
|
296
|
-
* Runtime specific request context.
|
|
297
|
-
*/
|
|
298
|
-
runtime?: ServerRuntimeContext;
|
|
299
|
-
/**
|
|
300
|
-
* IP address of the client.
|
|
301
|
-
*/
|
|
302
|
-
ip?: string | undefined;
|
|
303
|
-
/**
|
|
304
|
-
* Arbitrary context related to the request.
|
|
305
|
-
*/
|
|
306
|
-
context?: ServerRequestContext;
|
|
307
|
-
/**
|
|
308
|
-
* Tell the runtime about an ongoing operation that shouldn't close until the promise resolves.
|
|
309
|
-
*/
|
|
310
|
-
waitUntil?: (promise: Promise<unknown>) => void | Promise<void>;
|
|
311
|
-
}
|
|
312
|
-
type FetchHandler = (request: Request) => Response | Promise<Response>;
|
|
313
|
-
type ErrorHandler = (error: unknown) => Response | Promise<Response>;
|
|
314
|
-
type BunFetchHandler = (request: Request, server?: Bun.Server<any>) => Response | Promise<Response>;
|
|
315
|
-
type DenoFetchHandler = (request: Request, info?: Deno.ServeHandlerInfo<Deno.NetAddr>) => Response | Promise<Response>;
|
|
316
|
-
type NodeServerRequest = NodeHttp.IncomingMessage | NodeHttp2.Http2ServerRequest;
|
|
317
|
-
type NodeServerResponse = NodeHttp.ServerResponse | NodeHttp2.Http2ServerResponse;
|
|
318
|
-
type NodeHttp1Handler = (req: NodeHttp.IncomingMessage, res: NodeHttp.ServerResponse) => void | Promise<void>;
|
|
319
|
-
type NodeHttp2Handler = (req: NodeHttp2.Http2ServerRequest, res: NodeHttp2.Http2ServerResponse) => void | Promise<void>;
|
|
320
|
-
type NodeHttpHandler = NodeHttp1Handler | NodeHttp2Handler;
|
|
321
|
-
type NodeHTTP1Middleware = (req: NodeHttp.IncomingMessage, res: NodeHttp.ServerResponse, next: (error?: Error) => void) => unknown | Promise<unknown>;
|
|
322
|
-
type NodeHTTP2Middleware = (req: NodeHttp2.Http2ServerRequest, res: NodeHttp2.Http2ServerResponse, next: (error?: Error) => void) => unknown | Promise<unknown>;
|
|
323
|
-
type NodeHTTPMiddleware = NodeHTTP1Middleware | NodeHTTP2Middleware;
|
|
324
|
-
type CloudflareFetchHandler = CF.ExportedHandlerFetchHandler;
|
|
325
|
-
export { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FastResponse, FastURL, FetchHandler, NodeHTTP1Middleware, NodeHTTP2Middleware, NodeHTTPMiddleware, NodeHttp1Handler, NodeHttp2Handler, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerRequest, ServerRequestContext, ServerRuntimeContext, serve };
|
|
1
|
+
import { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FastResponse, FastURL, FetchHandler, NodeHTTP1Middleware, NodeHTTP2Middleware, NodeHTTPMiddleware, NodeHttp1Handler, NodeHttp2Handler, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerRequest, ServerRequestContext, ServerRuntimeContext, TrustProxyOption, serve } from "./_chunks/types.mjs";
|
|
2
|
+
export { BunFetchHandler, CloudflareFetchHandler, DenoFetchHandler, ErrorHandler, FastResponse, FastURL, FetchHandler, NodeHTTP1Middleware, NodeHTTP2Middleware, NodeHTTPMiddleware, NodeHttp1Handler, NodeHttp2Handler, NodeHttpHandler, NodeServerRequest, NodeServerResponse, Server, ServerHandler, ServerMiddleware, ServerOptions, ServerPlugin, ServerRequest, ServerRequestContext, ServerRuntimeContext, type TrustProxyOption, serve };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "srvx-nightly",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.22-20260711-160642-e093402",
|
|
4
4
|
"description": "Universal Server.",
|
|
5
5
|
"homepage": "https://srvx.h3.dev",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"./service-worker": "./dist/adapters/service-worker.mjs",
|
|
26
26
|
"./aws-lambda": "./dist/adapters/aws-lambda.mjs",
|
|
27
27
|
"./cli": "./dist/cli.mjs",
|
|
28
|
+
"./mtls": "./dist/mtls.mjs",
|
|
28
29
|
"./static": "./dist/static.mjs",
|
|
29
30
|
"./log": "./dist/log.mjs",
|
|
30
31
|
"./tracing": "./dist/tracing.mjs",
|