@sourceregistry/node-webserver 1.3.1 → 1.5.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/dist/index.es.js CHANGED
@@ -1,36 +1,37 @@
1
- import { createServer as e } from "http";
2
- import { createServer as t } from "https";
3
- import { TLSSocket as n } from "tls";
4
- import { Readable as r, Transform as i, Writable as a } from "stream";
5
- import { WebSocket as o, WebSocketServer as s } from "ws";
6
- import { parse as c, serialize as l } from "cookie";
7
- import { createReadStream as u } from "node:fs";
8
- import { lstat as d, realpath as f, stat as p } from "node:fs/promises";
9
- import { extname as m, isAbsolute as h, relative as g, resolve as _, sep as v } from "node:path";
10
- import { Readable as y } from "node:stream";
1
+ import { randomUUID as e } from "node:crypto";
2
+ import { createServer as t } from "http";
3
+ import { createServer as n } from "https";
4
+ import { TLSSocket as r } from "tls";
5
+ import { Readable as i, Transform as a, Writable as o } from "stream";
6
+ import { WebSocket as s, WebSocketServer as c } from "ws";
7
+ import { parse as l, serialize as u } from "cookie";
8
+ import { createReadStream as d } from "node:fs";
9
+ import { lstat as f, realpath as p, stat as m } from "node:fs/promises";
10
+ import { extname as h, isAbsolute as g, relative as _, resolve as v, sep as y } from "node:path";
11
+ import { Readable as b } from "node:stream";
11
12
  //#region \0rolldown/runtime.js
12
- var b = Object.defineProperty, x = (e, t) => {
13
+ var x = Object.defineProperty, S = (e, t) => {
13
14
  let n = {};
14
- for (var r in e) b(n, r, {
15
+ for (var r in e) x(n, r, {
15
16
  get: e[r],
16
17
  enumerable: !0
17
18
  });
18
- return t || b(n, Symbol.toStringTag, { value: "Module" }), n;
19
+ return t || x(n, Symbol.toStringTag, { value: "Module" }), n;
19
20
  };
20
21
  //#endregion
21
22
  //#region src/utils.ts
22
- function S(e) {
23
- return w(e) && e.status >= 400 && e.status < 600;
24
- }
25
23
  function C(e) {
26
- return w(e) && e.status >= 300 && e.status < 400;
24
+ return T(e) && e.status >= 400 && e.status < 600;
27
25
  }
28
26
  function w(e) {
27
+ return T(e) && e.status >= 300 && e.status < 400;
28
+ }
29
+ function T(e) {
29
30
  return e instanceof Response;
30
31
  }
31
32
  //#endregion
32
33
  //#region src/middlewares/ratelimiter/InMemory.ts
33
- var T = class {
34
+ var ee = class {
34
35
  constructor(e) {
35
36
  this.data = /* @__PURE__ */ new Map(), this.windowMs = e.windowMs, this.startCleanup();
36
37
  }
@@ -56,35 +57,37 @@ var T = class {
56
57
  async resetAll() {
57
58
  this.data.clear();
58
59
  }
59
- }, E = /* @__PURE__ */ x({ fixedWindowLimit: () => D });
60
+ }, E = /* @__PURE__ */ S({ fixedWindowLimit: () => D });
60
61
  function D(e) {
61
- let { windowMs: t = 6e4, max: n, key: r = (e) => e.getClientAddress(), message: i = "Too many requests, please try again later.", statusCode: a = 429, headers: o = "include", onRateLimit: s, store: c = new T({ windowMs: t }) } = e;
62
+ let { windowMs: t = 6e4, max: n, key: r = (e) => e.getClientAddress(), message: i = "Too many requests, please try again later.", statusCode: a = 429, headers: o = "include", onRateLimit: s, store: c = new ee({ windowMs: t }) } = e;
62
63
  return async (e, t) => {
63
- let l = `rl:${r(e)}`, { current: u, reset: d } = await c.incr(l), f = Math.ceil((d - Date.now()) / 1e3);
64
- if (u > n) {
64
+ let l = r(e);
65
+ if (typeof l != "string" || !/^[a-zA-Z0-9_.-]+$/.test(l)) throw Error("Invalid rate limit key: only alphanumeric, underscore, dot, and hyphen allowed");
66
+ let u = `rl:${l}`, { current: d, reset: f } = await c.incr(u), p = Math.ceil((f - Date.now()) / 1e3);
67
+ if (d > n) {
65
68
  s && s(e, {
66
- current: u,
69
+ current: d,
67
70
  max: n,
68
- key: l
71
+ key: u
69
72
  });
70
73
  let t = {
71
74
  status: a,
72
75
  headers: new Headers()
73
76
  }, r = t.headers;
74
- o === "include" && (r.set("X-RateLimit-Limit", String(n)), r.set("X-RateLimit-Remaining", "0"), r.set("X-RateLimit-Reset", String(Math.floor(d / 1e3))), r.set("Retry-After", String(f)));
77
+ o === "include" && (r.set("X-RateLimit-Limit", String(n)), r.set("X-RateLimit-Remaining", "0"), r.set("X-RateLimit-Reset", String(Math.floor(f / 1e3))), r.set("Retry-After", String(p)));
75
78
  let c;
76
79
  return typeof i == "string" ? (c = i, r.set("Content-Type", "text/plain")) : (c = JSON.stringify(i), r.set("Content-Type", "application/json")), new Response(c, t);
77
80
  }
78
81
  if (e.rateLimit = {
79
- current: u,
82
+ current: d,
80
83
  limit: n,
81
- reset: new Date(d),
82
- remaining: n - u
84
+ reset: new Date(f),
85
+ remaining: n - d
83
86
  }, o === "include") {
84
87
  let t = {
85
88
  "X-RateLimit-Limit": String(n),
86
- "X-RateLimit-Remaining": String(n - u),
87
- "X-RateLimit-Reset": String(Math.floor(d / 1e3))
89
+ "X-RateLimit-Remaining": String(n - d),
90
+ "X-RateLimit-Reset": String(Math.floor(f / 1e3))
88
91
  }, r = e.setHeaders;
89
92
  e.setHeaders = (e) => {
90
93
  r({
@@ -98,7 +101,7 @@ function D(e) {
98
101
  }
99
102
  //#endregion
100
103
  //#region src/middlewares/cros/index.ts
101
- var O = /* @__PURE__ */ x({ policy: () => P }), k = [
104
+ var te = /* @__PURE__ */ S({ policy: () => j }), ne = [
102
105
  "GET",
103
106
  "POST",
104
107
  "PUT",
@@ -106,13 +109,13 @@ var O = /* @__PURE__ */ x({ policy: () => P }), k = [
106
109
  "PATCH",
107
110
  "HEAD",
108
111
  "OPTIONS"
109
- ], A = [
112
+ ], re = [
110
113
  "Accept",
111
114
  "Accept-Language",
112
115
  "Content-Language",
113
116
  "Content-Type",
114
117
  "Range"
115
- ], j = [
118
+ ], O = [
116
119
  "Authorization",
117
120
  "X-Auth-Token",
118
121
  "X-Requested-With",
@@ -122,21 +125,21 @@ var O = /* @__PURE__ */ x({ policy: () => P }), k = [
122
125
  "X-Real-IP",
123
126
  "X-Custom-Header"
124
127
  ];
125
- function M(e, t) {
126
- return !e || !t ? !1 : t === "*" ? !0 : t === "null" ? e === "null" : Array.isArray(t) ? t.some((t) => M(e, t)) : typeof t == "function" ? t(e) : t instanceof RegExp ? t.test(e) : e === t;
128
+ function k(e, t) {
129
+ return !e || !t ? !1 : t === "*" ? !0 : t === "null" ? e === "null" : Array.isArray(t) ? t.some((t) => k(e, t)) : typeof t == "function" ? t(e) : t instanceof RegExp ? t.test(e) : e === t;
127
130
  }
128
- function N(e, t) {
131
+ function A(e, t) {
129
132
  let { origin: n = "*" } = t;
130
- return e ? n === "*" ? t.credentials ? e : "*" : M(e, n) ? e : null : n === "*" ? "*" : null;
133
+ return e ? n === "*" ? t.credentials ? e : "*" : k(e, n) ? e : null : n === "*" ? "*" : null;
131
134
  }
132
- function P(e = {}) {
133
- let { methods: t = k, allowedHeaders: n = j, exposedHeaders: r, credentials: i = !1, maxAge: a = 86400, onResponse: o } = e, s = t.join(","), c = [...A, ...n].join(","), l = [
135
+ function j(e = {}) {
136
+ let { methods: t = ne, allowedHeaders: n = O, exposedHeaders: r, credentials: i = !1, maxAge: a = 86400, onResponse: o } = e, s = t.join(","), c = [...re, ...n].join(","), l = [
134
137
  ["Vary", "Origin,Access-Control-Request-Method,Access-Control-Request-Headers"],
135
138
  ["Access-Control-Allow-Methods", s],
136
139
  ["Access-Control-Allow-Headers", c]
137
140
  ];
138
141
  return r && l.push(["Access-Control-Expose-Headers", r.join(",")]), i && l.push(["Access-Control-Allow-Credentials", "true"]), a && l.push(["Access-Control-Max-Age", a.toString()]), async (t, n) => {
139
- let r = t.request, i = r.headers.get("Origin"), a = r.method === "OPTIONS" && i !== null && r.headers.has("Access-Control-Request-Method"), s = N(i, e);
142
+ let r = t.request, i = r.headers.get("Origin"), a = r.method === "OPTIONS" && i !== null && r.headers.has("Access-Control-Request-Method"), s = A(i, e);
140
143
  if (a) {
141
144
  if (!s) return new Response(null, { status: 403 });
142
145
  let e = new Response(null, { status: 204 });
@@ -158,8 +161,93 @@ function P(e = {}) {
158
161
  };
159
162
  }
160
163
  //#endregion
164
+ //#region src/middlewares/security/index.ts
165
+ var M = /* @__PURE__ */ S({ headers: () => P }), N = {
166
+ contentSecurityPolicy: "default-src 'self'; base-uri 'self'; frame-ancestors 'none'; object-src 'none'",
167
+ frameOptions: "DENY",
168
+ referrerPolicy: "no-referrer",
169
+ permissionsPolicy: "geolocation=(), microphone=(), camera=()",
170
+ crossOriginOpenerPolicy: "same-origin",
171
+ crossOriginResourcePolicy: "same-origin",
172
+ strictTransportSecurity: !1
173
+ };
174
+ function P(e = {}) {
175
+ let t = {
176
+ ...N,
177
+ ...e
178
+ };
179
+ return async (e, n) => {
180
+ let r = await n();
181
+ if (!r) return;
182
+ let i = new Headers(r.headers);
183
+ return F(i, "content-security-policy", t.contentSecurityPolicy), F(i, "x-frame-options", t.frameOptions), F(i, "referrer-policy", t.referrerPolicy), F(i, "permissions-policy", t.permissionsPolicy), F(i, "cross-origin-opener-policy", t.crossOriginOpenerPolicy), F(i, "cross-origin-resource-policy", t.crossOriginResourcePolicy), F(i, "strict-transport-security", t.strictTransportSecurity), new Response(r.body, {
184
+ status: r.status,
185
+ statusText: r.statusText,
186
+ headers: i
187
+ });
188
+ };
189
+ }
190
+ function F(e, t, n) {
191
+ !n || e.has(t) || e.set(t, n);
192
+ }
193
+ //#endregion
194
+ //#region src/middlewares/requestid/index.ts
195
+ var I = /* @__PURE__ */ S({ assign: () => L });
196
+ function L(t = {}) {
197
+ let n = t.headerName?.toLowerCase() ?? "x-request-id", r = t.generate ?? e, i = t.clientRequestId ?? !1;
198
+ return async (e, t) => {
199
+ let a = e.request.headers.get(n) ?? r();
200
+ if (i) {
201
+ let t = e.request.headers.get("x-client-request-id");
202
+ if (t !== null) {
203
+ if (!R(t) || t.length > 512) return new Response("Invalid X-Client-Request-Id header", { status: 400 });
204
+ a = t;
205
+ }
206
+ }
207
+ Object.assign(e.locals, { requestId: a });
208
+ let o = await t();
209
+ if (!o) return;
210
+ if (o.headers.has(n)) return o;
211
+ let s = new Headers(o.headers);
212
+ return s.set(n, a), new Response(o.body, {
213
+ status: o.status,
214
+ statusText: o.statusText,
215
+ headers: s
216
+ });
217
+ };
218
+ }
219
+ function R(e) {
220
+ return /^[\x00-\x7F]*$/.test(e);
221
+ }
222
+ //#endregion
223
+ //#region src/middlewares/timeout/index.ts
224
+ var z = /* @__PURE__ */ S({ deadline: () => B });
225
+ function B(e) {
226
+ let { ms: t, status: n = 504, body: r = "Gateway Timeout", onTimeout: i } = e;
227
+ if (!Number.isFinite(t) || t <= 0) throw TypeError("Timeout.deadline requires a positive ms value");
228
+ return async (e, a) => {
229
+ let o = e.request, s = new AbortController(), c = () => s.abort();
230
+ o.signal.addEventListener("abort", c, { once: !0 });
231
+ let l = AbortSignal.any([o.signal, s.signal]);
232
+ e.request = new Request(o, {
233
+ signal: l,
234
+ duplex: o.body ? "half" : void 0
235
+ });
236
+ let u;
237
+ try {
238
+ return await Promise.race([a(), new Promise((e) => {
239
+ u = setTimeout(() => {
240
+ s.abort(), i?.(), e(new Response(r, { status: n }));
241
+ }, t);
242
+ })]);
243
+ } finally {
244
+ o.signal.removeEventListener("abort", c), u && clearTimeout(u);
245
+ }
246
+ };
247
+ }
248
+ //#endregion
161
249
  //#region src/types/RequestMethod.ts
162
- var F = [
250
+ var V = [
163
251
  "GET",
164
252
  "PUT",
165
253
  "POST",
@@ -167,7 +255,7 @@ var F = [
167
255
  "PATCH",
168
256
  "HEAD",
169
257
  "OPTIONS"
170
- ], I = class {
258
+ ], H = class {
171
259
  static {
172
260
  this.cache = /* @__PURE__ */ new Map();
173
261
  }
@@ -177,7 +265,7 @@ var F = [
177
265
  static set(e, t) {
178
266
  this.cache.set(e, t);
179
267
  }
180
- }, L = class e {
268
+ }, U = class {
181
269
  constructor() {
182
270
  this._routes = [], this._wsRoutes = [], this._nestedRouters = [], this._middlewares = [], this._preHandlers = [], this._postHandlers = [], this.routesSorted = !1, this.wsRoutesSorted = !1;
183
271
  }
@@ -209,7 +297,7 @@ var F = [
209
297
  return this.addHandler("OPTIONS", e, t, n);
210
298
  }
211
299
  USE(e, t, ...n) {
212
- return F.forEach((r) => this.addHandler(r, e, t, n)), this;
300
+ return V.forEach((r) => this.addHandler(r, e, t, n)), this;
213
301
  }
214
302
  action(e, t, ...n) {
215
303
  return this.addHandler("POST", e, async (e) => {
@@ -300,7 +388,10 @@ var F = [
300
388
  if (!r.regex.test(n)) continue;
301
389
  let i = n.match(r.regex);
302
390
  if (!i) continue;
303
- let a = Object.fromEntries(r.paramNames.map((e, t) => [e, i[t + 1] || ""])), o = {
391
+ let a = Object.fromEntries(r.paramNames.map((e, t) => {
392
+ let n = i[t + 1];
393
+ return n === void 0 ? void 0 : [e, decodeURIComponent(n)];
394
+ }).filter((e) => e !== void 0)), o = {
304
395
  ...e,
305
396
  params: {
306
397
  ...e.params,
@@ -312,7 +403,7 @@ var F = [
312
403
  },
313
404
  websocket: t
314
405
  }, s = [...this._middlewares, ...r.middlewares];
315
- if (await this.applyMiddlewaresWithList(o, s, () => r.handler(o)) === void 0) return !0;
406
+ if (await this.applyMiddlewaresWithList(o, s, () => r.handler(o)) !== void 0) return !0;
316
407
  }
317
408
  return !1;
318
409
  }
@@ -326,7 +417,7 @@ var F = [
326
417
  let i = r || new Response("No Content", { status: 204 });
327
418
  return await this.runPostHandlers(e, i);
328
419
  } catch (e) {
329
- if (w(e)) return e;
420
+ if (T(e)) return e;
330
421
  throw e;
331
422
  }
332
423
  }
@@ -362,7 +453,7 @@ var F = [
362
453
  }), this.routesSorted = !1, this;
363
454
  }
364
455
  createPathRegex(e) {
365
- let t = I.get(e);
456
+ let t = H.get(e);
366
457
  if (t) return t;
367
458
  let n = [], r = !1, i, a = e.split("/").filter(Boolean);
368
459
  i = a.reduce((e, t) => t.startsWith("[...") ? e - 10 : t.startsWith("[[") ? e - 5 : t.startsWith("[") ? e - 1 : e + 1, 0);
@@ -385,7 +476,7 @@ var F = [
385
476
  isCatchAll: r,
386
477
  priority: i
387
478
  };
388
- return I.set(e, s), s;
479
+ return H.set(e, s), s;
389
480
  }
390
481
  createPrefixRegex(e) {
391
482
  let t = [], n = !1, r, i = e.split("/").filter(Boolean);
@@ -416,9 +507,14 @@ var F = [
416
507
  let n = t.match(e.regex);
417
508
  if (!n) return {};
418
509
  let r = {};
419
- return e.isCatchAll && e.paramNames.length === 1 ? r[e.paramNames[0]] = n[1]?.replace(/^\//, "") || "" : e.paramNames.forEach((e, t) => {
420
- r[e] = n[t + 1] || "";
421
- }), r;
510
+ if (e.isCatchAll && e.paramNames.length === 1) {
511
+ let t = n[1]?.replace(/^\//, "");
512
+ t !== void 0 && (r[e.paramNames[0]] = decodeURIComponent(t));
513
+ } else e.paramNames.forEach((e, t) => {
514
+ let i = n[t + 1];
515
+ i !== void 0 && (r[e] = decodeURIComponent(i));
516
+ });
517
+ return r;
422
518
  }
423
519
  async handleNestedRouters(e, t) {
424
520
  let n = [...this._nestedRouters].sort((e, t) => t.priority - e.priority);
@@ -442,7 +538,10 @@ var F = [
442
538
  if (!a.regex.test(n) || (r.add(a.method), a.method === "GET" && (i = !0, r.add("HEAD")), !(a.method === t || t === "HEAD" && a.method === "GET"))) continue;
443
539
  let o = n.match(a.regex);
444
540
  if (!o) continue;
445
- let s = Object.fromEntries(a.paramNames.map((e, t) => [e, o[t + 1] || ""]));
541
+ let s = Object.fromEntries(a.paramNames.map((e, t) => {
542
+ let n = o[t + 1];
543
+ return n === void 0 ? void 0 : [e, decodeURIComponent(n)];
544
+ }).filter((e) => e !== void 0));
446
545
  return e.params = {
447
546
  ...e.params,
448
547
  ...s
@@ -470,20 +569,17 @@ var F = [
470
569
  this._wsRoutes.sort((e, t) => t.priority - e.priority), this.wsRoutesSorted = !0;
471
570
  }
472
571
  formatActionResult(e) {
473
- return e instanceof Response ? e : e?.type === "failure" && "status" in e ? R.fail(e.status, e.data) : R.success(200, e ?? void 0);
572
+ return e instanceof Response ? e : e?.type === "failure" && "status" in e ? W.fail(e.status, e.data) : W.success(200, e ?? void 0);
474
573
  }
475
574
  handleActionError(e) {
476
- if (S(e)) return R.error(e.status, { message: e.statusText || "Error" });
477
- if (C(e)) {
575
+ if (C(e)) return W.error(e.status, { message: e.statusText || "Error" });
576
+ if (w(e)) {
478
577
  let t = e.headers.get("Location") || "/";
479
- return R.redirect(e.status, t);
578
+ return W.redirect(e.status, t);
480
579
  }
481
- return console.error(e), R.error(500, { message: "Internal Server Error" });
482
- }
483
- static New() {
484
- return new e();
580
+ return console.error(e), W.error(500, { message: "Internal Server Error" });
485
581
  }
486
- }, R = {
582
+ }, W = {
487
583
  success: (e = 200, t) => new Response(JSON.stringify({
488
584
  data: t,
489
585
  type: "success",
@@ -516,21 +612,21 @@ var F = [
516
612
  status: e,
517
613
  headers: { "Content-Type": "application/json" }
518
614
  })
519
- }, z = class {
615
+ }, G = class {
520
616
  constructor(e, t) {
521
617
  this.raw = e.headers.get("cookie") ?? "", this.setCookieHeader = t;
522
618
  }
523
619
  get(e, t) {
524
- return c(this.raw, t)[e];
620
+ return l(this.raw, t)[e];
525
621
  }
526
622
  getAll(e) {
527
- return Object.entries(c(this.raw, e)).filter(([, e]) => e !== void 0).map(([e, t]) => ({
623
+ return Object.entries(l(this.raw, e)).filter(([, e]) => e !== void 0).map(([e, t]) => ({
528
624
  name: e,
529
625
  value: t
530
626
  }));
531
627
  }
532
628
  set(e, t, n) {
533
- this.setCookieHeader(l(e, t, n));
629
+ this.setCookieHeader(u(e, t, n));
534
630
  }
535
631
  delete(e, t) {
536
632
  this.set(e, "", {
@@ -538,28 +634,28 @@ var F = [
538
634
  maxAge: 0
539
635
  });
540
636
  }
541
- }, B = class extends Error {
637
+ }, K = class extends Error {
542
638
  constructor(e = "Payload Too Large") {
543
639
  super(e), this.status = 413, this.name = "PayloadTooLargeError";
544
640
  }
545
- }, V = class extends L {
641
+ }, q = class extends U {
546
642
  constructor(e) {
547
643
  super(), this.upgradeHandlerInstalled = !1, this.config = e ?? {
548
644
  type: "http",
549
645
  options: {}
550
- }, this.wss = new s({
646
+ }, this.wss = new c({
551
647
  noServer: !0,
552
648
  maxPayload: this.config.security?.maxWebSocketPayload ?? 1024 * 1024
553
649
  });
554
650
  }
555
651
  get server() {
556
652
  if (!this._server) {
557
- let n = (e, t) => {
653
+ let e = (e, t) => {
558
654
  this.handleRequest(e, t).catch((e) => {
559
655
  console.error("Unhandled request error:", e), t.statusCode = 500, t.end("Internal Server Error");
560
656
  });
561
657
  };
562
- this._server = this.config.type === "https" ? t(this.config.options, n) : e(this.config.options, n);
658
+ this._server = this.config.type === "https" ? n(this.config.options, e) : t(this.config.options, e), this.configureServerTimeouts(this._server);
563
659
  }
564
660
  return this._server;
565
661
  }
@@ -580,7 +676,7 @@ var F = [
580
676
  return;
581
677
  }
582
678
  let a = this.toRequestEvent(i, r, {
583
- getClientAddress: () => e.socket.remoteAddress ?? "127.0.0.1",
679
+ getClientAddress: () => this.getClientAddress(e),
584
680
  setHeader: () => {},
585
681
  pushSetCookie: () => {}
586
682
  });
@@ -591,9 +687,9 @@ var F = [
591
687
  }
592
688
  this.wss.handleUpgrade(e, t, n, (e) => {
593
689
  this.handleWebSocket(a, e).then((t) => {
594
- !t && e.readyState === o.OPEN && e.close(1008, "Route not found");
690
+ !t && e.readyState === s.OPEN && e.close(1008, "Route not found");
595
691
  }).catch((t) => {
596
- console.error("WebSocket routing error:", t), e.readyState === o.OPEN && e.close(1011, "Internal error");
692
+ console.error("WebSocket routing error:", t), e.readyState === s.OPEN && e.close(1011, "Internal error");
597
693
  });
598
694
  });
599
695
  }).catch(() => t.destroy());
@@ -618,7 +714,7 @@ var F = [
618
714
  let n = new AbortController(), r = () => n.abort();
619
715
  e.once("aborted", r), e.once("close", r), t.once("close", r);
620
716
  let i = this.toWebRequest(e, n.signal), a = new URL(i.url), o = {}, s = [], c = this.toRequestEvent(i, a, {
621
- getClientAddress: () => e.socket.remoteAddress ?? "127.0.0.1",
717
+ getClientAddress: () => this.getClientAddress(e),
622
718
  setHeader: (e, t) => {
623
719
  o[e.toLowerCase()] = t;
624
720
  },
@@ -638,21 +734,21 @@ var F = [
638
734
  let n = this.toURL(e, !1);
639
735
  return this.toRequest(e, n, !1, t);
640
736
  }
641
- toRequest(e, t, n, i) {
737
+ toRequest(e, t, n, r) {
642
738
  let a = {
643
739
  method: n ? "GET" : e.method,
644
740
  headers: this.toHeaders(e.headers),
645
- signal: i,
741
+ signal: r,
646
742
  duplex: "half"
647
743
  };
648
- return !n && e.method !== "GET" && e.method !== "HEAD" && (a.body = r.toWeb(this.wrapRequestBody(e))), new Request(t, a);
744
+ return !n && e.method !== "GET" && e.method !== "HEAD" && (a.body = i.toWeb(this.wrapRequestBody(e))), new Request(t, a);
649
745
  }
650
746
  wrapRequestBody(e) {
651
747
  let t = this.config.security?.maxRequestBodySize;
652
748
  if (!t) return e;
653
- let n = 0, r = new i({ transform(e, r, i) {
749
+ let n = 0, r = new a({ transform(e, r, i) {
654
750
  if (n += Buffer.byteLength(e), n > t) {
655
- i(new B());
751
+ i(new K());
656
752
  return;
657
753
  }
658
754
  i(null, e);
@@ -660,14 +756,31 @@ var F = [
660
756
  return e.on("aborted", () => r.destroy(/* @__PURE__ */ Error("Request aborted"))), e.on("error", (e) => r.destroy(e)), e.pipe(r), r;
661
757
  }
662
758
  toURL(e, t) {
663
- let r = e.socket instanceof n ? t ? "wss" : "https" : t ? "ws" : "http", i = this.resolveAuthority(e);
664
- return new URL(e.url ?? "/", `${r}://${i}`);
759
+ let n = this.resolveProtocol(e, t), r = this.resolveAuthority(e);
760
+ return new URL(e.url ?? "/", `${n}://${r}`);
761
+ }
762
+ resolveProtocol(e, t) {
763
+ let n = this.getTrustedForwardedHeader(e, "x-forwarded-proto")?.split(",")[0]?.trim().toLowerCase();
764
+ return n === "http" || n === "https" ? t ? n === "https" ? "wss" : "ws" : n : e.socket instanceof r ? t ? "wss" : "https" : t ? "ws" : "http";
665
765
  }
666
766
  resolveAuthority(e) {
667
- let t = this.config.security?.trustHostHeader ? this.normalizeTrustedHost(e.headers.host) : null;
668
- if (t) return t;
669
- let n = this.server.address();
670
- return n && typeof n == "object" ? `${n.address.includes(":") ? `[${n.address}]` : n.address}:${n.port}` : e.socket.localPort ? `127.0.0.1:${e.socket.localPort}` : "localhost";
767
+ let t = this.getTrustedForwardedHeader(e, "x-forwarded-host") ?? e.headers.host, n = this.config.security?.trustHostHeader ? this.normalizeTrustedHost(t) : null;
768
+ if (n) return n;
769
+ let r = this.server.address();
770
+ return r && typeof r == "object" ? `${r.address.includes(":") ? `[${r.address}]` : r.address}:${r.port}` : e.socket.localPort ? `127.0.0.1:${e.socket.localPort}` : "localhost";
771
+ }
772
+ getClientAddress(e) {
773
+ let t = e.socket.remoteAddress ?? "127.0.0.1";
774
+ if (!this.isTrustedProxy(t)) return this.normalizeAddress(t);
775
+ let n = e.headers["x-forwarded-for"];
776
+ if (!n) return this.normalizeAddress(t);
777
+ let r = this.parseForwardedHeader(n).filter((e) => this.isValidIP(e));
778
+ r.push(t);
779
+ for (let e = r.length - 1; e >= 0; --e) {
780
+ let t = r[e];
781
+ if (!this.isTrustedProxy(t)) return this.normalizeAddress(t);
782
+ }
783
+ return this.normalizeAddress(r[0] ?? t);
671
784
  }
672
785
  normalizeTrustedHost(e) {
673
786
  if (!e) return null;
@@ -684,6 +797,43 @@ var F = [
684
797
  matchesValue(e, t) {
685
798
  return (Array.isArray(t) ? t : [t]).some((t) => typeof t == "string" ? t === e : t instanceof RegExp ? t.test(e) : t(e));
686
799
  }
800
+ configureServerTimeouts(e) {
801
+ let t = this.config.security, n = this.isDevelopment();
802
+ e.headersTimeout = t?.headersTimeoutMs ?? 3e4, e.requestTimeout = t?.requestTimeoutMs ?? (n ? 0 : 6e4), e.keepAliveTimeout = t?.keepAliveTimeoutMs ?? 5e3;
803
+ }
804
+ isDevelopment() {
805
+ return process.env.NODE_ENV !== "production";
806
+ }
807
+ getTrustedForwardedHeader(e, t) {
808
+ if (!this.isTrustedProxy(e.socket.remoteAddress ?? "")) return;
809
+ let n = e.headers[t];
810
+ return Array.isArray(n) ? n[0] : n;
811
+ }
812
+ isTrustedProxy(e) {
813
+ let t = this.config.security?.trustedProxies;
814
+ if (!t) return !1;
815
+ let n = this.normalizeAddress(e);
816
+ return n !== e && this.matchesValue(n, t) ? !0 : this.matchesValue(e, t);
817
+ }
818
+ normalizeAddress(e) {
819
+ return e.startsWith("::ffff:") ? e.slice(7) : e;
820
+ }
821
+ isValidIP(e) {
822
+ if (e.includes(":")) {
823
+ if (e.includes(":::")) return !1;
824
+ let t = e.split(":");
825
+ return t.length <= 8 && t.every((e) => e === "" || /^[0-9a-fA-F]+$/.test(e));
826
+ }
827
+ let t = e.split(".");
828
+ return t.length === 4 && t.every((e) => {
829
+ if (e === "" || e.length > 3) return !1;
830
+ let t = parseInt(e, 10);
831
+ return !isNaN(t) && t >= 0 && t <= 255 && e === String(t);
832
+ });
833
+ }
834
+ parseForwardedHeader(e) {
835
+ return (Array.isArray(e) ? e.join(",") : e).split(",").map((e) => this.normalizeAddress(e.trim())).filter(Boolean);
836
+ }
687
837
  toHeaders(e) {
688
838
  let t = new Headers();
689
839
  for (let [n, r] of Object.entries(e)) if (r !== void 0) {
@@ -705,15 +855,15 @@ var F = [
705
855
  return Number.isFinite(r) && r <= t;
706
856
  }
707
857
  handleError(e) {
708
- if (e instanceof B) return new Response(e.message, { status: e.status });
709
- if (S(e)) return new Response(JSON.stringify({
858
+ if (e instanceof K) return new Response(e.message, { status: e.status });
859
+ if (C(e)) return new Response(JSON.stringify({
710
860
  error: e.statusText || "Error",
711
861
  status: e.status
712
862
  }), {
713
863
  status: e.status,
714
864
  headers: { "Content-Type": "application/json" }
715
865
  });
716
- if (C(e)) {
866
+ if (w(e)) {
717
867
  let t = e.headers.get("Location") || "/";
718
868
  return new Response(null, {
719
869
  status: e.status,
@@ -729,10 +879,10 @@ var F = [
729
879
  e.end();
730
880
  return;
731
881
  }
732
- let n = t.body.getReader(), r = a.toWeb(e).getWriter(), i = !1, o = async () => {
882
+ let n = t.body.getReader(), r = o.toWeb(e).getWriter(), i = !1, a = async () => {
733
883
  i || (i = !0, await n.cancel().catch(() => {}));
734
884
  }, s = () => {
735
- o();
885
+ a();
736
886
  };
737
887
  e.once("close", s);
738
888
  try {
@@ -743,7 +893,7 @@ var F = [
743
893
  }
744
894
  i = !0;
745
895
  } catch (e) {
746
- if (await o(), !this.isPrematureCloseError(e)) throw e;
896
+ if (await a(), !this.isPrematureCloseError(e)) throw e;
747
897
  } finally {
748
898
  e.off("close", s), await r.close().catch(() => {});
749
899
  }
@@ -803,7 +953,10 @@ var F = [
803
953
  r && t.set(n, r);
804
954
  }
805
955
  toRequestEvent(e, t, n) {
806
- let r = new z(e, n.pushSetCookie), i = this.config, a = {}, o = { name: "WebHTTPServer" }, s = /* @__PURE__ */ new Set(), c = {
956
+ let r = new G(e, n.pushSetCookie), i = this.config, a = {}, o = {
957
+ name: "node-webserver",
958
+ dev: this.isDevelopment()
959
+ }, s = /* @__PURE__ */ new Set(), c = {
807
960
  request: e,
808
961
  url: t,
809
962
  cookies: r,
@@ -828,7 +981,7 @@ var F = [
828
981
  }, l = this.createEventFetch(c, n);
829
982
  return i.locals && Object.assign(a, i.locals(c)), i.platform && Object.assign(o, i.platform(c)), c;
830
983
  }
831
- }, H = {
984
+ }, J = {
832
985
  ".avif": "image/avif",
833
986
  ".css": "text/css; charset=utf-8",
834
987
  ".gif": "image/gif",
@@ -846,24 +999,24 @@ var F = [
846
999
  ".wasm": "application/wasm",
847
1000
  ".webp": "image/webp",
848
1001
  ".xml": "application/xml; charset=utf-8"
849
- }, U = {
1002
+ }, Y = {
850
1003
  index: "index.html",
851
1004
  cacheControl: "public, max-age=0",
852
1005
  dotFiles: "ignore"
853
1006
  };
854
- async function W(e, t, n = {}) {
855
- let r = Z(t), i = {
856
- ...U,
1007
+ async function X(e, t, n = {}) {
1008
+ let r = se(t), i = {
1009
+ ...Y,
857
1010
  ...n
858
- }, a = await G(e), o = K(r, i.dotFiles);
1011
+ }, a = await ie(e), o = ae(r, i.dotFiles);
859
1012
  if (o instanceof Response) return o;
860
- let s = _(a, o.length > 0 ? o.join(v) : "");
861
- if (!Y(a, s)) return new Response("Forbidden", { status: 403 });
862
- let c = await q(s, a, i.index);
1013
+ let s = v(a, o.length > 0 ? o.join(y) : "");
1014
+ if (!Q(a, s)) return new Response("Forbidden", { status: 403 });
1015
+ let c = await oe(s, a, i.index);
863
1016
  if (c instanceof Response) return c;
864
- let l = await p(c), d = new Headers({
1017
+ let l = await m(c), u = new Headers({
865
1018
  "content-length": String(l.size),
866
- "content-type": X(c),
1019
+ "content-type": $(c),
867
1020
  "cache-control": i.cacheControl,
868
1021
  "last-modified": l.mtime.toUTCString(),
869
1022
  "x-content-type-options": "nosniff"
@@ -871,18 +1024,18 @@ async function W(e, t, n = {}) {
871
1024
  if (n.headers) {
872
1025
  let e = typeof n.headers == "function" ? n.headers(c, l) : n.headers;
873
1026
  new Headers(e).forEach((e, t) => {
874
- d.set(t, e);
1027
+ u.set(t, e);
875
1028
  });
876
1029
  }
877
- return new Response(y.toWeb(u(c)), {
1030
+ return new Response(b.toWeb(d(c)), {
878
1031
  status: 200,
879
- headers: d
1032
+ headers: u
880
1033
  });
881
1034
  }
882
- async function G(e) {
883
- return f(e);
1035
+ async function ie(e) {
1036
+ return p(e);
884
1037
  }
885
- function K(e, t) {
1038
+ function ae(e, t) {
886
1039
  if (e.includes("\0")) return new Response("Bad Request", { status: 400 });
887
1040
  let n = e.replace(/\\/g, "/").split("/").filter(Boolean), r = [];
888
1041
  for (let e of n) {
@@ -903,52 +1056,55 @@ function K(e, t) {
903
1056
  }
904
1057
  return r;
905
1058
  }
906
- async function q(e, t, n) {
1059
+ async function oe(e, t, n) {
907
1060
  try {
908
- return (await d(e)).isDirectory() ? J(_(e, n), t) : J(e, t);
1061
+ return (await f(e)).isDirectory() ? Z(v(e, n), t) : Z(e, t);
909
1062
  } catch {
910
1063
  return new Response("Not Found", { status: 404 });
911
1064
  }
912
1065
  }
913
- async function J(e, t) {
1066
+ async function Z(e, t) {
914
1067
  try {
915
- let n = await f(e);
916
- return Y(t, n) ? (await p(n)).isFile() ? n : new Response("Not Found", { status: 404 }) : new Response("Forbidden", { status: 403 });
1068
+ let n = await p(e);
1069
+ return Q(t, n) ? (await m(n)).isFile() ? n : new Response("Not Found", { status: 404 }) : new Response("Forbidden", { status: 403 });
917
1070
  } catch {
918
1071
  return new Response("Not Found", { status: 404 });
919
1072
  }
920
1073
  }
921
- function Y(e, t) {
922
- let n = g(e, t);
923
- return n === "" || !n.startsWith("..") && !h(n);
1074
+ function Q(e, t) {
1075
+ let n = _(e, t);
1076
+ return n === "" || !n.startsWith("..") && !g(n);
924
1077
  }
925
- function X(e) {
926
- return H[m(e).toLowerCase()] ?? "application/octet-stream";
1078
+ function $(e) {
1079
+ return J[h(e).toLowerCase()] ?? "application/octet-stream";
927
1080
  }
928
- function Z(e) {
1081
+ function se(e) {
929
1082
  return typeof e.params.path == "string" ? e.params.path : e.url.pathname.replace(/^\/+/, "");
930
1083
  }
931
- var Q = (e, t = {}) => (n) => W(e, n, t), $ = (e, ...t) => async (n) => {
1084
+ var ce = (e, t = {}) => (n) => X(e, n, t), le = (e, ...t) => async (n) => {
932
1085
  let r = {};
933
1086
  for (let e of t) {
934
1087
  let t = await e(n);
935
- if (w(t)) return t;
1088
+ if (T(t)) return t;
936
1089
  t && typeof t == "object" && Object.assign(r, t);
937
1090
  }
938
1091
  return e(Object.assign(n, { context: r }));
939
1092
  };
940
1093
  //#endregion
941
1094
  //#region src/helpers/sse.ts
942
- function ee(e, t = {}) {
1095
+ function ue(e, t = {}) {
943
1096
  let n = [];
944
- if (t.comment) for (let e of t.comment.split(/\r?\n/)) n.push(`: ${e}`);
1097
+ if (t.comment) {
1098
+ let e = t.comment.replace(/\r\n/g, " ").replace(/\r/g, " ").replace(/\n/g, " ");
1099
+ n.push(`: ${e}`);
1100
+ }
945
1101
  if (t.event && n.push(`event: ${t.event}`), t.id && n.push(`id: ${t.id}`), t.retry !== void 0 && n.push(`retry: ${t.retry}`), e !== void 0) {
946
1102
  let t = typeof e == "string" ? e : JSON.stringify(e);
947
1103
  for (let e of t.split(/\r?\n/)) n.push(`data: ${e}`);
948
1104
  }
949
1105
  return `${n.join("\n")}\n\n`;
950
1106
  }
951
- var te = (e, t = {}) => (n) => {
1107
+ var de = (e, t = {}) => (n) => {
952
1108
  let r = new TextEncoder(), i = null, a = !1, o, s = async () => {
953
1109
  if (!a) {
954
1110
  a = !0;
@@ -964,7 +1120,7 @@ var te = (e, t = {}) => (n) => {
964
1120
  async start(t) {
965
1121
  i = t;
966
1122
  let c = (e, n = {}) => {
967
- a || t.enqueue(r.encode(ee(e, n)));
1123
+ a || t.enqueue(r.encode(ue(e, n)));
968
1124
  };
969
1125
  n.request.signal.addEventListener("abort", () => {
970
1126
  s();
@@ -992,7 +1148,7 @@ var te = (e, t = {}) => (n) => {
992
1148
  ...t.headers
993
1149
  }
994
1150
  });
995
- }, ne = async (e, t) => {
1151
+ }, fe = async (e, t) => {
996
1152
  let n = JSON.stringify(await e);
997
1153
  return new Response(n, {
998
1154
  ...t,
@@ -1003,19 +1159,19 @@ var te = (e, t = {}) => (n) => {
1003
1159
  }
1004
1160
  });
1005
1161
  };
1006
- function re(e, t) {
1162
+ function pe(e, t) {
1007
1163
  throw new Response(null, {
1008
1164
  status: e,
1009
1165
  headers: { location: t.toString() }
1010
1166
  });
1011
1167
  }
1012
- function ie(e, t) {
1168
+ function me(e, t) {
1013
1169
  throw new Response(JSON.stringify(typeof t == "string" ? { message: t } : t), {
1014
1170
  status: e,
1015
1171
  headers: { "content-type": "application/json" }
1016
1172
  });
1017
1173
  }
1018
- var ae = async (e, t) => {
1174
+ var he = async (e, t) => {
1019
1175
  let n = await e;
1020
1176
  return new Response(n, {
1021
1177
  ...t,
@@ -1025,7 +1181,7 @@ var ae = async (e, t) => {
1025
1181
  ...t?.headers
1026
1182
  }
1027
1183
  });
1028
- }, oe = async (e, t) => {
1184
+ }, ge = async (e, t) => {
1029
1185
  let n = await e;
1030
1186
  return new Response(n, {
1031
1187
  ...t,
@@ -1037,6 +1193,6 @@ var ae = async (e, t) => {
1037
1193
  });
1038
1194
  };
1039
1195
  //#endregion
1040
- export { R as Action, O as CORS, E as RateLimiter, F as RequestMethods, L as Router, V as WebServer, Q as dir, $ as enhance, ie as error, oe as html, S as isHttpError, C as isRedirect, w as isResponse, ne as json, re as redirect, W as serveStatic, te as sse, ae as text };
1196
+ export { W as Action, te as CORS, E as RateLimiter, I as RequestId, V as RequestMethods, U as Router, M as Security, z as Timeout, q as WebServer, ce as dir, le as enhance, me as error, ge as html, C as isHttpError, w as isRedirect, T as isResponse, fe as json, pe as redirect, X as serveStatic, de as sse, he as text };
1041
1197
 
1042
1198
  //# sourceMappingURL=index.es.js.map