@nodefony/http 10.0.0-beta.3 → 10.0.0-beta.4
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/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.155.0}/helpers/esm/decorate.js +1 -2
- package/dist/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.155.0}/helpers/esm/decorateParam.js +1 -2
- package/dist/index.js +12 -10
- package/dist/nodefony/command/assetsPublishCommand.js +5 -3
- package/dist/nodefony/command/certificatesCommand.js +5 -3
- package/dist/nodefony/command/networkCommand.js +5 -3
- package/dist/nodefony/command/proxyGenerateCommand.js +8 -3
- package/dist/nodefony/config/config.js +1 -2
- package/dist/nodefony/config/defineModuleConfig.js +1 -2
- package/dist/nodefony/service/HttpAdminApi.js +2 -2
- package/dist/nodefony/service/ProfilerAdminApi.js +1 -2
- package/dist/nodefony/service/audit-logger.js +20 -13
- package/dist/nodefony/service/certificates.js +97 -13
- package/dist/nodefony/service/error-renderer.js +29 -12
- package/dist/nodefony/service/http-kernel.js +118 -43
- package/dist/nodefony/service/pretty-request-logger.js +5 -4
- package/dist/nodefony/service/request-logger.js +24 -16
- package/dist/nodefony/service/reverse-proxy.js +3 -3
- package/dist/nodefony/service/servers/clientError.js +22 -3
- package/dist/nodefony/service/servers/server-h2c.js +126 -0
- package/dist/nodefony/service/servers/server-http.js +5 -8
- package/dist/nodefony/service/servers/server-https.js +12 -24
- package/dist/nodefony/service/servers/server-static.js +3 -3
- package/dist/nodefony/service/servers/server-websocket-secure.js +10 -18
- package/dist/nodefony/service/servers/server-websocket.js +10 -18
- package/dist/nodefony/service/servers/serverShutdown.js +78 -18
- package/dist/nodefony/service/servers/wsHeartbeat.js +1 -2
- package/dist/nodefony/service/sessions/sessions-service.js +7 -14
- package/dist/nodefony/service/trace.js +1 -2
- package/dist/nodefony/service/upload/upload-service.js +5 -8
- package/dist/nodefony/service/x509.js +1 -2
- package/dist/nodefony/src/assets/collectAssets.js +1 -2
- package/dist/nodefony/src/assets/prebuiltUi.js +1 -2
- package/dist/nodefony/src/context/Context.js +23 -31
- package/dist/nodefony/src/context/domainMatcher.js +1 -2
- package/dist/nodefony/src/context/forwarded.js +1 -2
- package/dist/nodefony/src/context/http/HttpContext.js +7 -6
- package/dist/nodefony/src/context/http/Request.js +33 -29
- package/dist/nodefony/src/context/http/Response.js +23 -6
- package/dist/nodefony/src/context/http/SseStream.js +1 -2
- package/dist/nodefony/src/context/http/parser.js +36 -10
- package/dist/nodefony/src/context/http/urlFastPath.js +1 -2
- package/dist/nodefony/src/context/http2/Request.js +4 -8
- package/dist/nodefony/src/context/http2/Response.js +22 -9
- package/dist/nodefony/src/context/metaData.js +1 -2
- package/dist/nodefony/src/context/requestId.js +1 -2
- package/dist/nodefony/src/context/responseEnded.js +1 -2
- package/dist/nodefony/src/context/transport.js +45 -0
- package/dist/nodefony/src/context/trustProxy.js +1 -2
- package/dist/nodefony/src/context/websocket/Response.js +33 -6
- package/dist/nodefony/src/context/websocket/WebsocketContext.js +92 -17
- package/dist/nodefony/src/context/websocket/isWebsocketContext.js +17 -0
- package/dist/nodefony/src/context/websocket/websocketUrl.js +1 -2
- package/dist/nodefony/src/context/websocket/wsBackpressure.js +1 -2
- package/dist/nodefony/src/context/websocket/wsCloseReason.js +1 -2
- package/dist/nodefony/src/context/websocket/wsLogContent.js +1 -2
- package/dist/nodefony/src/cookies/cookie.js +3 -7
- package/dist/nodefony/src/errors/httpError.js +1 -2
- package/dist/nodefony/src/errors/thrownMessage.js +1 -2
- package/dist/nodefony/src/profiler/FrameProfile.js +1 -2
- package/dist/nodefony/src/profiler/Profiler.js +102 -20
- package/dist/nodefony/src/profiler/aggregate.js +422 -0
- package/dist/nodefony/src/proxy/forward.js +29 -5
- package/dist/nodefony/src/proxy/generateProxyConfig.js +14 -6
- package/dist/nodefony/src/proxy/rules.js +12 -6
- package/dist/nodefony/src/rateLimit/MemoryRateLimitStore.js +1 -2
- package/dist/nodefony/src/rateLimit/WsConnectionCounter.js +1 -2
- package/dist/nodefony/src/rateLimit/rateLimitFilters.js +1 -2
- package/dist/nodefony/src/servers/http2Limits.js +50 -0
- package/dist/nodefony/src/servers/kernelServers.js +12 -3
- package/dist/nodefony/src/servers/portBinder.js +41 -10
- package/dist/nodefony/src/servers/upgradeDispatch.js +86 -7
- package/dist/nodefony/src/session/session.js +2 -3
- package/dist/nodefony/src/session/sessionStoreFailure.js +1 -2
- package/dist/nodefony/src/session/storage/MemorySessionStorage.js +1 -2
- package/dist/nodefony/src/session/storage/RevocationGuardStorage.js +1 -2
- package/dist/nodefony/src/session/storage/sessionFilters.js +1 -2
- package/dist/nodefony/src/session/storage/sessionSort.js +1 -2
- package/dist/types/index.d.ts +7 -3
- package/dist/types/nodefony/interfaces/IContext.d.ts +63 -4
- package/dist/types/nodefony/interfaces/IRequest.d.ts +9 -4
- package/dist/types/nodefony/interfaces/IRouting.d.ts +10 -0
- package/dist/types/nodefony/interfaces/index.d.ts +2 -2
- package/dist/types/nodefony/service/certificates.d.ts +55 -4
- package/dist/types/nodefony/service/error-renderer.d.ts +31 -0
- package/dist/types/nodefony/service/http-kernel.d.ts +46 -10
- package/dist/types/nodefony/service/servers/clientError.d.ts +16 -0
- package/dist/types/nodefony/service/servers/server-h2c.d.ts +51 -0
- package/dist/types/nodefony/service/servers/server-http.d.ts +3 -3
- package/dist/types/nodefony/service/servers/server-https.d.ts +4 -4
- package/dist/types/nodefony/service/servers/server-websocket-secure.d.ts +1 -3
- package/dist/types/nodefony/service/servers/server-websocket.d.ts +1 -3
- package/dist/types/nodefony/service/servers/serverShutdown.d.ts +30 -16
- package/dist/types/nodefony/src/context/Context.d.ts +13 -4
- package/dist/types/nodefony/src/context/http/HttpContext.d.ts +1 -1
- package/dist/types/nodefony/src/context/http/Request.d.ts +20 -15
- package/dist/types/nodefony/src/context/http/Response.d.ts +11 -0
- package/dist/types/nodefony/src/context/http/parser.d.ts +18 -2
- package/dist/types/nodefony/src/context/http2/Request.d.ts +1 -1
- package/dist/types/nodefony/src/context/http2/Response.d.ts +15 -5
- package/dist/types/nodefony/src/context/transport.d.ts +53 -0
- package/dist/types/nodefony/src/context/websocket/Response.d.ts +18 -2
- package/dist/types/nodefony/src/context/websocket/WebsocketContext.d.ts +57 -7
- package/dist/types/nodefony/src/context/websocket/isWebsocketContext.d.ts +15 -0
- package/dist/types/nodefony/src/profiler/FrameProfile.d.ts +13 -12
- package/dist/types/nodefony/src/profiler/Profiler.d.ts +68 -15
- package/dist/types/nodefony/src/profiler/aggregate.d.ts +215 -0
- package/dist/types/nodefony/src/proxy/forward.d.ts +14 -2
- package/dist/types/nodefony/src/proxy/generateProxyConfig.d.ts +16 -0
- package/dist/types/nodefony/src/proxy/rules.d.ts +3 -0
- package/dist/types/nodefony/src/servers/http2Limits.d.ts +37 -0
- package/dist/types/nodefony/src/servers/kernelServers.d.ts +10 -1
- package/dist/types/nodefony/src/servers/portBinder.d.ts +29 -5
- package/dist/types/nodefony/src/servers/upgradeDispatch.d.ts +33 -3
- package/docs/cookies.md +85 -78
- package/docs/observabilite.md +80 -80
- package/docs/rate-limit.md +83 -83
- package/docs/reverse-proxy.md +54 -54
- package/docs/servers.md +338 -224
- package/docs/session.md +179 -179
- package/docs/sse.md +24 -20
- package/docs/upload.md +120 -117
- package/package.json +8 -9
- package/dist/_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorateMetadata.js +0 -6
|
@@ -6,21 +6,20 @@ import { WsConnectionCounter } from "../src/rateLimit/WsConnectionCounter.js";
|
|
|
6
6
|
import { compileDomainPatterns, compileTrustedHosts, isDomainAllowed } from "../src/context/domainMatcher.js";
|
|
7
7
|
import { responseEnded } from "../src/context/responseEnded.js";
|
|
8
8
|
import { parseWebsocketUrl } from "../src/context/websocket/websocketUrl.js";
|
|
9
|
-
import WebsocketContext from "../src/context/websocket/WebsocketContext.js";
|
|
9
|
+
import WebsocketContext, { toHandshakeStatus } from "../src/context/websocket/WebsocketContext.js";
|
|
10
|
+
import { trackPong } from "./servers/wsHeartbeat.js";
|
|
10
11
|
import HttpContext from "../src/context/http/HttpContext.js";
|
|
11
12
|
import DefaultErrorRenderer from "./error-renderer.js";
|
|
12
|
-
import DefaultRequestLogger from "./request-logger.js";
|
|
13
13
|
import JsonAuditLogger from "./audit-logger.js";
|
|
14
|
+
import DefaultRequestLogger from "./request-logger.js";
|
|
14
15
|
import PrettyRequestLogger from "./pretty-request-logger.js";
|
|
15
16
|
import { resolveTraceparent } from "./trace.js";
|
|
16
17
|
import { asServersConfig, configuredServerPort } from "../src/servers/kernelServers.js";
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import { GcScheduler, IDENTITY_CHANGED_EVENT, Module, RequestContext, RevocationWatch, Service, finallyMaybe, injectable, isPromise, logColor, nodefonyError, servedUrl, thenMaybe, writeRuntimeState } from "nodefony";
|
|
18
|
+
import __decorate from "../../_virtual/_@oxc-project_runtime@0.155.0/helpers/esm/decorate.js";
|
|
19
|
+
import { GcScheduler, IDENTITY_CHANGED_EVENT, RequestContext, RevocationWatch, Service, finallyMaybe, injectable, isPromise, logColor, nodefonyError, servedUrl, thenMaybe, writeRuntimeState } from "nodefony";
|
|
20
20
|
import cluster from "node:cluster";
|
|
21
21
|
import http from "node:http";
|
|
22
|
-
|
|
23
|
-
//#region nodefony/service/http-kernel.ts
|
|
22
|
+
// nodefony/service/http-kernel.ts
|
|
24
23
|
const HEALTH_HEADERS = {
|
|
25
24
|
"content-type": "application/json",
|
|
26
25
|
"cache-control": "no-store"
|
|
@@ -126,9 +125,7 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
126
125
|
this.container?.addScope("request");
|
|
127
126
|
this.responseTimeout = {
|
|
128
127
|
http: this.options.http.responseTimeout,
|
|
129
|
-
https: this.options.https.responseTimeout
|
|
130
|
-
http2: this.options.https.responseTimeout,
|
|
131
|
-
http3: this.options.https.responseTimeout
|
|
128
|
+
https: this.options.https.responseTimeout
|
|
132
129
|
};
|
|
133
130
|
this.closeTimeOutWs = {
|
|
134
131
|
ws: this.options.websocket.closeTimeout,
|
|
@@ -356,7 +353,7 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
356
353
|
const policy = this.getWsOriginPolicy(secure ? "websocketSecure" : "websocket");
|
|
357
354
|
if (policy.disabled) return true;
|
|
358
355
|
if (!origin) return true;
|
|
359
|
-
let originHost
|
|
356
|
+
let originHost;
|
|
360
357
|
try {
|
|
361
358
|
originHost = new URL(origin).hostname;
|
|
362
359
|
} catch {
|
|
@@ -382,7 +379,7 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
382
379
|
* @throws {HttpError} code WS 1008 (Policy Violation) si l'Origin est refusée.
|
|
383
380
|
*/
|
|
384
381
|
checkWebsocketOrigin(context) {
|
|
385
|
-
const secure = context.
|
|
382
|
+
const secure = context.serverType === "wss";
|
|
386
383
|
const raw = context.origin;
|
|
387
384
|
if (this.isWebsocketOriginAllowed(raw, context.domain, secure)) return;
|
|
388
385
|
const error = new HttpError(`WebSocket Origin "${raw}" not allowed (CSWSH protection)`, 1008, context);
|
|
@@ -481,7 +478,14 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
481
478
|
context.resolver = resolver;
|
|
482
479
|
return resolver;
|
|
483
480
|
}
|
|
484
|
-
if (resolver.exception)
|
|
481
|
+
if (resolver.exception) {
|
|
482
|
+
const exception = resolver.exception;
|
|
483
|
+
if (context.secure && "code" in exception && exception.code === 426) {
|
|
484
|
+
context.resolver = resolver;
|
|
485
|
+
return resolver;
|
|
486
|
+
}
|
|
487
|
+
throw resolver.exception;
|
|
488
|
+
}
|
|
485
489
|
throw new HttpError("Not Found", 404, context);
|
|
486
490
|
}
|
|
487
491
|
/**
|
|
@@ -580,18 +584,26 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
580
584
|
await context.close();
|
|
581
585
|
return context;
|
|
582
586
|
}
|
|
583
|
-
if (context instanceof WebsocketContext)
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
context.
|
|
587
|
+
if (context instanceof WebsocketContext) {
|
|
588
|
+
if (context.admission !== null) {
|
|
589
|
+
const status = toHandshakeStatus("code" in error && typeof error.code === "number" ? error.code : void 0);
|
|
590
|
+
context.refuseHandshake(status);
|
|
591
|
+
if (this.kernel?.debug) this.log(`${status} ${error.message}`, "DEBUG", "WEBSOCKET REFUSED");
|
|
587
592
|
return context;
|
|
588
593
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
594
|
+
try {
|
|
595
|
+
const wsResult = this.errorRenderer.renderWebsocket(error, context);
|
|
596
|
+
if (context.response?.connection) {
|
|
597
|
+
context.close(wsResult.code, wsResult.reason);
|
|
598
|
+
return context;
|
|
599
|
+
}
|
|
600
|
+
if (context.request && !context.rejected) {
|
|
601
|
+
context.reject(wsResult.code, wsResult.reason);
|
|
602
|
+
return context;
|
|
603
|
+
}
|
|
604
|
+
} catch {
|
|
605
|
+
throw error;
|
|
592
606
|
}
|
|
593
|
-
} catch {
|
|
594
|
-
throw error;
|
|
595
607
|
}
|
|
596
608
|
throw error;
|
|
597
609
|
}
|
|
@@ -633,7 +645,7 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
633
645
|
if (headerServer != null && headerServer !== "") response.setHeader("Server", headerServer);
|
|
634
646
|
if (this.secContentTypeOptions !== null) response.setHeader("X-Content-Type-Options", this.secContentTypeOptions);
|
|
635
647
|
if (this.secFrameOptions !== null) response.setHeader("X-Frame-Options", this.secFrameOptions);
|
|
636
|
-
if (this.secHsts !== null &&
|
|
648
|
+
if (this.secHsts !== null && type === "https") response.setHeader("Strict-Transport-Security", this.secHsts);
|
|
637
649
|
if (this.#healthPaths !== null) {
|
|
638
650
|
const url = request.url;
|
|
639
651
|
if (url === this.#healthPaths.liveness) {
|
|
@@ -676,6 +688,11 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
676
688
|
await serverHttps.createServer();
|
|
677
689
|
servers.push(serverHttps);
|
|
678
690
|
}
|
|
691
|
+
const serverH2c = this.get("server-h2c");
|
|
692
|
+
if (serverH2c?.active) {
|
|
693
|
+
await serverH2c.createServer();
|
|
694
|
+
servers.push(serverH2c);
|
|
695
|
+
}
|
|
679
696
|
const serverWebsocket = this.get("server-websocket");
|
|
680
697
|
if (serverWebsocket && serverHttp?.active) {
|
|
681
698
|
await serverWebsocket.createServer(serverHttp);
|
|
@@ -686,7 +703,7 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
686
703
|
await serverWebsocketSecure.createServer(serverHttps);
|
|
687
704
|
servers.push(serverWebsocketSecure);
|
|
688
705
|
}
|
|
689
|
-
this.publishRuntimePorts(serverHttp, serverHttps);
|
|
706
|
+
this.publishRuntimePorts(serverHttp, serverHttps, serverH2c);
|
|
690
707
|
return servers;
|
|
691
708
|
}
|
|
692
709
|
/**
|
|
@@ -720,7 +737,7 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
720
737
|
* {@link readRuntimeState} — `status`/`stop` redeviendraient aveugles alors que
|
|
721
738
|
* l'app écoute toujours. Le master, lui, est le propriétaire du runtime.
|
|
722
739
|
*/
|
|
723
|
-
publishRuntimePorts(serverHttp, serverHttps) {
|
|
740
|
+
publishRuntimePorts(serverHttp, serverHttps, serverH2c) {
|
|
724
741
|
const ports = [];
|
|
725
742
|
const desired = [];
|
|
726
743
|
const urls = [];
|
|
@@ -736,6 +753,11 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
736
753
|
const port = configuredServerPort(asServersConfig(this.kernel?.options.servers), "https");
|
|
737
754
|
if (port) desired.push(port);
|
|
738
755
|
}
|
|
756
|
+
if (serverH2c?.active && serverH2c.port > 0) {
|
|
757
|
+
ports.push(serverH2c.port);
|
|
758
|
+
const port = configuredServerPort(asServersConfig(this.kernel?.options.servers), "h2c");
|
|
759
|
+
if (port) desired.push(port);
|
|
760
|
+
}
|
|
739
761
|
if (ports.length === 0) return;
|
|
740
762
|
writeRuntimeState(process.cwd(), {
|
|
741
763
|
pid: cluster.isWorker ? process.ppid : process.pid,
|
|
@@ -856,7 +878,7 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
856
878
|
response.on("close", () => {
|
|
857
879
|
if (!responseEnded(response)) {
|
|
858
880
|
context._abortIfPending("Connection closed before response finished");
|
|
859
|
-
if (
|
|
881
|
+
if (context.response.statusCode < 400) context.response.statusCode = 499;
|
|
860
882
|
}
|
|
861
883
|
this.teardownHttp(context, scope);
|
|
862
884
|
});
|
|
@@ -1019,9 +1041,15 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
1019
1041
|
await this.firewall?.handleSecurity(context);
|
|
1020
1042
|
if (this.listenerCount("afterAuth")) await this.fireAsync("afterAuth", context);
|
|
1021
1043
|
} catch (authError) {
|
|
1044
|
+
if (context.resolver?.exception) {
|
|
1045
|
+
context.response.response?.removeHeader("Upgrade");
|
|
1046
|
+
context.response.response?.removeHeader("Connection");
|
|
1047
|
+
}
|
|
1022
1048
|
await this.fireAsync("onAuthFailure", context, authError).catch((e) => this.log(e, "ERROR", "onAuthFailure"));
|
|
1023
1049
|
throw authError;
|
|
1024
1050
|
}
|
|
1051
|
+
const pending = context.resolver?.exception;
|
|
1052
|
+
if (pending) throw pending;
|
|
1025
1053
|
} finally {
|
|
1026
1054
|
context.phaseEnd("firewall");
|
|
1027
1055
|
}
|
|
@@ -1057,21 +1085,48 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
1057
1085
|
this.log(e, "ERROR", "WS onFinish");
|
|
1058
1086
|
}
|
|
1059
1087
|
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1088
|
+
/**
|
|
1089
|
+
* Point d'entrée d'un upgrade vers une route WebSocket de Nodefony, appelé
|
|
1090
|
+
* par le répartiteur d'upgrade AVANT le `101` (#596) : rien ne s'ouvre tant
|
|
1091
|
+
* que le pipeline n'a pas dit oui.
|
|
1092
|
+
*
|
|
1093
|
+
* Les bornes par IP passent en premier, avant tout scope, ALS ou pipeline
|
|
1094
|
+
* (symétrie avec le 429 HTTP et avec le proxy inverse) : le vrai vecteur DoS
|
|
1095
|
+
* est d'accumuler des sockets ouvertes. La place est rendue à la fermeture du
|
|
1096
|
+
* socket du client — même règle que pour un tunnel relayé.
|
|
1097
|
+
*
|
|
1098
|
+
* @param req - requête d'upgrade
|
|
1099
|
+
* @param admission - le verdict à rendre : accepter (`101`) ou refuser (HTTP)
|
|
1100
|
+
* @param type - serveur qui a reçu l'upgrade
|
|
1101
|
+
* @returns la promesse du traitement de la connexion
|
|
1102
|
+
*/
|
|
1103
|
+
async onWebsocketUpgrade(req, admission, type) {
|
|
1104
|
+
if (this.websocketQuotaRefusal(req, req.socket) !== null) {
|
|
1105
|
+
admission.refuse(429);
|
|
1064
1106
|
return;
|
|
1065
1107
|
}
|
|
1066
1108
|
await this.fireAsync("onServerRequest", req, null, type);
|
|
1067
1109
|
const scope = this.container?.enterScope("request");
|
|
1068
|
-
return this.handleWebsocket(scope,
|
|
1110
|
+
return this.handleWebsocket(scope, req, admission, type);
|
|
1069
1111
|
}
|
|
1070
|
-
|
|
1112
|
+
/**
|
|
1113
|
+
* Pipeline d'un handshake WebSocket, dans la bulle ALS de la connexion :
|
|
1114
|
+
* jugement (`onConnect`), pare-feu, gardes de l'action — PUIS seulement
|
|
1115
|
+
* l'acceptation, la socket et l'action de handshake. Tout refus antérieur à
|
|
1116
|
+
* l'acceptation part en statut HTTP (`onError` → `refuseHandshake`).
|
|
1117
|
+
*
|
|
1118
|
+
* @param scope - scope DI de la connexion
|
|
1119
|
+
* @param req - requête d'upgrade
|
|
1120
|
+
* @param admission - le verdict à rendre
|
|
1121
|
+
* @param type - serveur qui a reçu l'upgrade
|
|
1122
|
+
* @returns ce que rend l'action de handshake
|
|
1123
|
+
*/
|
|
1124
|
+
async handleWebsocket(scope, req, admission, type) {
|
|
1071
1125
|
let context = null;
|
|
1072
1126
|
let error = null;
|
|
1073
1127
|
try {
|
|
1074
|
-
context = this.createWebsocketContext(scope, req,
|
|
1128
|
+
context = this.createWebsocketContext(scope, req, null, type);
|
|
1129
|
+
context.admission = admission;
|
|
1075
1130
|
} catch (e) {
|
|
1076
1131
|
error = e;
|
|
1077
1132
|
}
|
|
@@ -1107,22 +1162,34 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
1107
1162
|
context.phaseEnd("firewall");
|
|
1108
1163
|
}
|
|
1109
1164
|
}
|
|
1110
|
-
if (context)
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1165
|
+
if (!context) return;
|
|
1166
|
+
const guarded = context.resolver?.authorizeAction();
|
|
1167
|
+
if (guarded !== void 0) await guarded;
|
|
1168
|
+
const accepted = admission.accept();
|
|
1169
|
+
const ws = accepted instanceof Promise ? await accepted : accepted;
|
|
1170
|
+
if (ws === null) {
|
|
1171
|
+
this.releaseOrphanWsScope(scope, context);
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
1174
|
+
trackPong(ws);
|
|
1175
|
+
context.acceptConnection(ws);
|
|
1176
|
+
await context.connect();
|
|
1177
|
+
context.phaseStart("action");
|
|
1178
|
+
try {
|
|
1179
|
+
return await context.handle();
|
|
1180
|
+
} finally {
|
|
1181
|
+
context.phaseEnd("action");
|
|
1117
1182
|
}
|
|
1118
1183
|
});
|
|
1119
1184
|
} catch (e) {
|
|
1120
1185
|
try {
|
|
1121
1186
|
await this.onError(e, context);
|
|
1122
1187
|
} catch (errorHandlingError) {
|
|
1188
|
+
admission.refuse(500);
|
|
1123
1189
|
this.releaseOrphanWsScope(scope, context);
|
|
1124
1190
|
throw errorHandlingError;
|
|
1125
1191
|
}
|
|
1192
|
+
admission.refuse(500);
|
|
1126
1193
|
this.releaseOrphanWsScope(scope, context);
|
|
1127
1194
|
throw e;
|
|
1128
1195
|
}
|
|
@@ -1137,6 +1204,16 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
1137
1204
|
this.container?.leaveScope(scope);
|
|
1138
1205
|
context.clean();
|
|
1139
1206
|
}
|
|
1207
|
+
/**
|
|
1208
|
+
* Juge un handshake WebSocket AVANT son acceptation : hôte, origine,
|
|
1209
|
+
* `beforeResolve`, contrôleur (protocole négocié), session. N'ouvre rien —
|
|
1210
|
+
* l'acceptation n'a lieu qu'après le pare-feu et les gardes de l'action
|
|
1211
|
+
* (cf {@link handleWebsocket}).
|
|
1212
|
+
*
|
|
1213
|
+
* @param context - contexte du handshake, encore sans socket
|
|
1214
|
+
* @param error - erreur levée à la construction du contexte, relancée telle quelle
|
|
1215
|
+
* @throws la première erreur du jugement — rendue en statut HTTP par `onError`
|
|
1216
|
+
*/
|
|
1140
1217
|
async onConnect(context, error = null) {
|
|
1141
1218
|
if (error) throw error;
|
|
1142
1219
|
if (!context) throw new nodefonyError("Bad context", 500);
|
|
@@ -1150,7 +1227,6 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
1150
1227
|
throw e;
|
|
1151
1228
|
}
|
|
1152
1229
|
if (!context.sessionStarting) await this.startSession(context);
|
|
1153
|
-
return context.connect();
|
|
1154
1230
|
}
|
|
1155
1231
|
checkValidDomain(context) {
|
|
1156
1232
|
if (context.validDomain) return 200;
|
|
@@ -1301,7 +1377,6 @@ let HttpKernel = class HttpKernel extends Service {
|
|
|
1301
1377
|
return this.#streams?.revalidate() ?? Promise.resolve();
|
|
1302
1378
|
}
|
|
1303
1379
|
};
|
|
1304
|
-
HttpKernel = __decorate([injectable()
|
|
1380
|
+
HttpKernel = __decorate([injectable()], HttpKernel);
|
|
1305
1381
|
var http_kernel_default = HttpKernel;
|
|
1306
|
-
//#endregion
|
|
1307
1382
|
export { http_kernel_default as default, responseEnded };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { handshakeRefusalStatus } from "../src/context/websocket/WebsocketContext.js";
|
|
1
2
|
import { computeDurationMs, severityFromStatus } from "./audit-logger.js";
|
|
2
3
|
import { logColor } from "nodefony";
|
|
3
|
-
|
|
4
|
+
// nodefony/service/pretty-request-logger.ts
|
|
4
5
|
/**
|
|
5
6
|
* Pretty single-line logger for dev (P3.2) — the biggest gain for humans.
|
|
6
7
|
*
|
|
@@ -34,12 +35,13 @@ var PrettyRequestLogger = class {
|
|
|
34
35
|
}
|
|
35
36
|
renderWebsocket(context, error, acceptedProtocol) {
|
|
36
37
|
const ctx = context;
|
|
37
|
-
const
|
|
38
|
+
const refused = error ? handshakeRefusalStatus(context, error) : null;
|
|
39
|
+
const status = refused ?? ctx.response?.statusCode ?? (error ? 500 : null);
|
|
38
40
|
const duration = computeDurationMs(ctx.phases);
|
|
39
41
|
const proto = acceptedProtocol ? `[${acceptedProtocol}]` : "";
|
|
40
42
|
return {
|
|
41
43
|
text: `${logColor.cyan("WS ")} ${colorizeStatus(status)} ${ctx.url} ${logColor.blackBright(proto)} ${logColor.blackBright(formatDuration(duration))} ${logColor.blackBright(ctx.remoteAddress ?? "-")} ` + logColor.magenta(`[${shortId(ctx.requestId)}]`) + (error ? ` ${logColor.red(error.message)}` : ""),
|
|
42
|
-
severity: error ? "ERROR" : "INFO",
|
|
44
|
+
severity: refused !== null ? severityFromStatus(refused) : error ? "ERROR" : "INFO",
|
|
43
45
|
msgid: "req"
|
|
44
46
|
};
|
|
45
47
|
}
|
|
@@ -61,5 +63,4 @@ function formatDuration(ms) {
|
|
|
61
63
|
function shortId(id) {
|
|
62
64
|
return id.length > 8 ? id.slice(0, 8) : id;
|
|
63
65
|
}
|
|
64
|
-
//#endregion
|
|
65
66
|
export { PrettyRequestLogger as default };
|
|
@@ -1,5 +1,15 @@
|
|
|
1
|
+
import { handshakeRefusalStatus } from "../src/context/websocket/WebsocketContext.js";
|
|
2
|
+
import { severityFromStatus } from "./audit-logger.js";
|
|
1
3
|
import { logColor } from "nodefony";
|
|
2
|
-
|
|
4
|
+
// nodefony/service/request-logger.ts
|
|
5
|
+
/**
|
|
6
|
+
* Statut de la réponse : le contrat ne type `response` qu'en `object` ; une
|
|
7
|
+
* annotation (vérifiée, pas une assertion) le lit — le reste passe par le contrat, que le
|
|
8
|
+
* compilateur surveille.
|
|
9
|
+
*/
|
|
10
|
+
const statusOf = (context) => {
|
|
11
|
+
return context.response?.statusCode;
|
|
12
|
+
};
|
|
3
13
|
/**
|
|
4
14
|
* Default Nodefony per-request logger — preserves the legacy colored format.
|
|
5
15
|
*
|
|
@@ -13,14 +23,13 @@ import { logColor } from "nodefony";
|
|
|
13
23
|
*/
|
|
14
24
|
var DefaultRequestLogger = class {
|
|
15
25
|
renderHttp(context, error) {
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const err = error ?? ctx.error;
|
|
26
|
+
const txt = `${logColor.cyan("URL")} : ${context.url} ${logColor.cyan("FROM")} : ${context.remoteAddress} ${logColor.cyan("ORIGIN")} : ${context.originUrl?.host} ${logColor.cyan("ID")} : ${context.requestId}`;
|
|
27
|
+
const err = error ?? context.error;
|
|
19
28
|
if (err) {
|
|
20
|
-
const errCode = err.code ??
|
|
21
|
-
const msgid = `${
|
|
29
|
+
const errCode = err.code ?? statusOf(context) ?? 500;
|
|
30
|
+
const msgid = `${context.serverType} ${logColor.magenta(errCode)} ${logColor.red(context.method ?? "")}`;
|
|
22
31
|
return {
|
|
23
|
-
text:
|
|
32
|
+
text: context.kernel?.environment === "production" ? `${txt} ${err}` : `${txt}\n ${err}`,
|
|
24
33
|
severity: "ERROR",
|
|
25
34
|
msgid
|
|
26
35
|
};
|
|
@@ -28,27 +37,26 @@ var DefaultRequestLogger = class {
|
|
|
28
37
|
return {
|
|
29
38
|
text: txt,
|
|
30
39
|
severity: "INFO",
|
|
31
|
-
msgid: `${
|
|
40
|
+
msgid: `${context.serverType} ${logColor.magenta(statusOf(context) ?? "")} ${context.method}`
|
|
32
41
|
};
|
|
33
42
|
}
|
|
34
43
|
renderWebsocket(context, error, acceptedProtocol) {
|
|
35
|
-
const ctx = context;
|
|
36
44
|
if (error) {
|
|
37
|
-
const
|
|
38
|
-
const
|
|
45
|
+
const refused = handshakeRefusalStatus(context, error);
|
|
46
|
+
const errCode = refused ?? error.code ?? statusOf(context) ?? 500;
|
|
47
|
+
const msgid = `${context.serverType} ${logColor.magenta(errCode)} ${logColor.red(context.method ?? "")}`;
|
|
39
48
|
return {
|
|
40
|
-
text: `${logColor.cyan("URL")} : ${
|
|
41
|
-
severity: "ERROR",
|
|
49
|
+
text: `${logColor.cyan("URL")} : ${context.url} ${logColor.cyan("FROM")} : ${context.remoteAddress} ${logColor.cyan("ORIGIN")} : ${context.originUrl?.host} ${logColor.cyan("ID")} : ${context.requestId}\n ` + error.toString(),
|
|
50
|
+
severity: refused !== null ? severityFromStatus(refused) : "ERROR",
|
|
42
51
|
msgid
|
|
43
52
|
};
|
|
44
53
|
}
|
|
45
|
-
const msgid = `${
|
|
54
|
+
const msgid = `${context.serverType} ${logColor.magenta(statusOf(context) ?? "")} ${context.method}`;
|
|
46
55
|
return {
|
|
47
|
-
text: `${logColor.cyan("URL")} : ${
|
|
56
|
+
text: `${logColor.cyan("URL")} : ${context.url} ${logColor.cyan("Accept-Protocol")} : ${acceptedProtocol || "*"} ${logColor.cyan("FROM")} : ${context.remoteAddress} ${logColor.cyan("ORIGIN")} : ${context.originUrl?.host} ${logColor.cyan("ID")} : ${context.requestId}`,
|
|
48
57
|
severity: "INFO",
|
|
49
58
|
msgid
|
|
50
59
|
};
|
|
51
60
|
}
|
|
52
61
|
};
|
|
53
|
-
//#endregion
|
|
54
62
|
export { DefaultRequestLogger as default };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { isAmbiguousPath, normalizePrefix, parseProxyOrigin, proxyMountProblems, websocketHandshakeProblem } from "../src/proxy/rules.js";
|
|
2
|
+
import { requestAuthority } from "../src/context/transport.js";
|
|
2
3
|
import { forwardRequest, forwardUpgrade, refuseUpgrade } from "../src/proxy/forward.js";
|
|
3
4
|
import { Service } from "nodefony";
|
|
4
5
|
import http from "node:http";
|
|
5
6
|
import { randomBytes } from "node:crypto";
|
|
6
7
|
import https from "node:https";
|
|
7
8
|
import { TLSSocket } from "node:tls";
|
|
8
|
-
|
|
9
|
+
// nodefony/service/reverse-proxy.ts
|
|
9
10
|
/** Replis si la section `proxy` manque (module construit hors configuration). */
|
|
10
11
|
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
11
12
|
const DEFAULT_CONNECT_TIMEOUT_MS = 5e3;
|
|
@@ -240,7 +241,7 @@ var ReverseProxy = class extends Service {
|
|
|
240
241
|
const target = this.targetOf(mount);
|
|
241
242
|
if (target === void 0) return answerPlain(res, 503, "Service Unavailable", "1");
|
|
242
243
|
if (isAmbiguousPath(req.url ?? "/")) return answerPlain(res, 400, "Bad Request");
|
|
243
|
-
const host = req.headers
|
|
244
|
+
const host = requestAuthority(req.headers);
|
|
244
245
|
return forwardRequest(req, res, mount, target, this.fromOf(req, scheme, host), this.relayFor(mount, target));
|
|
245
246
|
}
|
|
246
247
|
/**
|
|
@@ -332,5 +333,4 @@ function hostnameOf(host) {
|
|
|
332
333
|
return null;
|
|
333
334
|
}
|
|
334
335
|
}
|
|
335
|
-
//#endregion
|
|
336
336
|
export { ReverseProxy as default };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { isPeerGoneError } from "../../src/context/websocket/Response.js";
|
|
2
|
+
// nodefony/service/servers/clientError.ts
|
|
2
3
|
/**
|
|
3
4
|
* Gère l'event `clientError` d'un `http.Server` / `https.Server`.
|
|
4
5
|
*
|
|
@@ -16,5 +17,23 @@ function handleClientError(error, socket) {
|
|
|
16
17
|
const statusLine = error.code === "HPE_HEADER_OVERFLOW" ? "431 Request Header Fields Too Large" : "400 Bad Request";
|
|
17
18
|
socket.end(`HTTP/1.1 ${statusLine}\r\nConnection: close\r\n\r\n`);
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Gère l'event `sessionError` d'un serveur HTTP/2 (h2c ou TLS) : un pair PARTI
|
|
22
|
+
* se tait, toute autre erreur est rapportée.
|
|
23
|
+
*
|
|
24
|
+
* Une session réinitialisée par le pair n'a rien à diagnostiquer. C'est la
|
|
25
|
+
* signature d'une sonde de port — `nodefony status`, `doctor`, le superviseur
|
|
26
|
+
* de développement, la sonde `tcpSocket` d'un orchestrateur — qui se connecte
|
|
27
|
+
* puis ferme sans lire le `SETTINGS` que le serveur envoie dès l'ouverture : le
|
|
28
|
+
* système ferme alors par un RST plutôt qu'un FIN, et Node lève `ECONNRESET`.
|
|
29
|
+
* La rapporter imprimait une pile entière par sonde. La règle « client parti »
|
|
30
|
+
* est celle des frames WebSocket ({@link isPeerGoneError}), pas une copie.
|
|
31
|
+
*
|
|
32
|
+
* @param error - erreur de session émise par `node:http2`
|
|
33
|
+
* @param report - rapporte une erreur réelle, à la sévérité choisie par le serveur
|
|
34
|
+
*/
|
|
35
|
+
function handleSessionError(error, report) {
|
|
36
|
+
if (isPeerGoneError(error)) return;
|
|
37
|
+
report(error);
|
|
38
|
+
}
|
|
39
|
+
export { handleClientError, handleSessionError };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { asServersConfig, configuredServerPort, isH2cEnabled } from "../../src/servers/kernelServers.js";
|
|
2
|
+
import __decorate from "../../../_virtual/_@oxc-project_runtime@0.155.0/helpers/esm/decorate.js";
|
|
3
|
+
import { handleSessionError } from "./clientError.js";
|
|
4
|
+
import { createDrainTerminator } from "./serverShutdown.js";
|
|
5
|
+
import { bindWithFallback, buildBindPlan, h2cPortConflict } from "../../src/servers/portBinder.js";
|
|
6
|
+
import __decorateParam from "../../../_virtual/_@oxc-project_runtime@0.155.0/helpers/esm/decorateParam.js";
|
|
7
|
+
import { http2ServerLimits, setHttp2SessionTimeout } from "../../src/servers/http2Limits.js";
|
|
8
|
+
import { BootConfigurationError, Inject, Service, nodefonyError } from "nodefony";
|
|
9
|
+
import http2 from "node:http2";
|
|
10
|
+
// nodefony/service/servers/server-h2c.ts
|
|
11
|
+
/**
|
|
12
|
+
* Serveur HTTP/2 en clair (h2c, connaissance préalable — RFC 9113 §3.3), sur un
|
|
13
|
+
* port DÉDIÉ (`servers.h2c`, 5153 par défaut), pour un proxy inverse qui parle
|
|
14
|
+
* HTTP/2 à ses amonts.
|
|
15
|
+
*
|
|
16
|
+
* Il partage le chemin HTTP/2 du 5152 — même `onHttpRequest`, mêmes limites
|
|
17
|
+
* anti-DoS (`http2ServerLimits`), même drain par GOAWAY — sans TLS : `serverType`
|
|
18
|
+
* vaut `"http"`, le schéma vient du transport ou d'un proxy de confiance, jamais
|
|
19
|
+
* du pseudo-en-tête `:scheme`. Le protocole du saut (`"h2c"`) se constate sur la
|
|
20
|
+
* requête (`transport.ts#alpnProtocolOf`).
|
|
21
|
+
*
|
|
22
|
+
* Hors de son périmètre, délibérément : HTTP/1.1 (refusé par la préface HTTP/2 —
|
|
23
|
+
* sondes et clients HTTP/1.1 restent sur le port HTTP), WebSocket (aucun CONNECT
|
|
24
|
+
* étendu, RFC 8441 : un proxy route `Upgrade: websocket` vers le port HTTP) et la
|
|
25
|
+
* bascule `Upgrade: h2c` (retirée par RFC 9113 §3.1).
|
|
26
|
+
*/
|
|
27
|
+
let ServerH2c = class ServerH2c extends Service {
|
|
28
|
+
httpKernel;
|
|
29
|
+
module;
|
|
30
|
+
server = null;
|
|
31
|
+
httpTerminator = null;
|
|
32
|
+
port;
|
|
33
|
+
protocol = "2.0";
|
|
34
|
+
ready = false;
|
|
35
|
+
type = "http";
|
|
36
|
+
domain;
|
|
37
|
+
scheme = "http";
|
|
38
|
+
address = null;
|
|
39
|
+
family = null;
|
|
40
|
+
active = false;
|
|
41
|
+
infos = null;
|
|
42
|
+
constructor(module, httpKernel) {
|
|
43
|
+
super("server-h2c", module.container ?? void 0, module.notificationsCenter, module.config.http);
|
|
44
|
+
this.httpKernel = httpKernel;
|
|
45
|
+
this.module = module;
|
|
46
|
+
this.active = isH2cEnabled(asServersConfig(module.kernel?.options.servers)?.h2c);
|
|
47
|
+
this.port = configuredServerPort(asServersConfig(module.kernel?.options.servers), "h2c") ?? 0;
|
|
48
|
+
this.domain = this.module.kernel?.domain ?? null;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Crée et met en écoute le serveur h2c.
|
|
52
|
+
*
|
|
53
|
+
* @returns le serveur à l'écoute
|
|
54
|
+
* @throws BootConfigurationError si `servers.h2c.port` est celui du serveur
|
|
55
|
+
* HTTP ou HTTPS — un port partagé n'est pas un conflit à contourner
|
|
56
|
+
*/
|
|
57
|
+
createServer() {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
try {
|
|
60
|
+
if (!this.active) return reject(/* @__PURE__ */ new Error(`Server h2c is not allowed in config file`));
|
|
61
|
+
const domain = this.domain;
|
|
62
|
+
if (domain === null) return reject(/* @__PURE__ */ new Error(`Server h2c : aucun domaine d'écoute (kernel absent)`));
|
|
63
|
+
const servers = asServersConfig(this.module.kernel?.options.servers);
|
|
64
|
+
const conflict = h2cPortConflict(servers);
|
|
65
|
+
if (conflict !== null) return reject(new BootConfigurationError(`servers.h2c.port (${this.port}) est aussi celui de servers.${conflict}.port : HTTP/1.1 et h2c ne partagent pas un port. Choisir un port distinct pour servers.h2c.port.`));
|
|
66
|
+
if (!servers?.http) this.log("servers.h2c actif sans servers.http : les sondes de santé et les WebSocket (HTTP/1.1) n'ont plus de port où arriver.", "WARNING");
|
|
67
|
+
const server = http2.createServer(http2ServerLimits(this.module.config.http2));
|
|
68
|
+
this.server = server;
|
|
69
|
+
this.httpTerminator = createDrainTerminator(server, this.options.shutdownTimeout);
|
|
70
|
+
setHttp2SessionTimeout(server, this.options.timeout, () => {
|
|
71
|
+
this.fire("onTimeout", this);
|
|
72
|
+
});
|
|
73
|
+
server.on("request", (request, response) => {
|
|
74
|
+
this.httpKernel.onHttpRequest(request, response, this.type);
|
|
75
|
+
});
|
|
76
|
+
server.on("sessionError", (error) => {
|
|
77
|
+
handleSessionError(error, (e) => this.log(e, "DEBUG", "H2C sessionError"));
|
|
78
|
+
});
|
|
79
|
+
server.on("streamError", (error) => {
|
|
80
|
+
this.log(error, "ERROR", "H2C streamError");
|
|
81
|
+
});
|
|
82
|
+
this.module.fire("onCreateServer", this.type, this);
|
|
83
|
+
bindWithFallback(server, domain, buildBindPlan("h2c", servers, this.module.kernel?.environment)).then(({ address, shiftedFrom }) => {
|
|
84
|
+
this.infos = address;
|
|
85
|
+
this.port = address.port;
|
|
86
|
+
this.address = address.address;
|
|
87
|
+
this.family = familyOf(address);
|
|
88
|
+
if (shiftedFrom !== null) this.log(`Port ${shiftedFrom} déjà occupé → h2c écoute sur ${this.port}. Figer le port : servers.h2c.port ; échouer au lieu de glisser : servers.portPolicy = "strict".`, "WARNING");
|
|
89
|
+
this.ready = true;
|
|
90
|
+
this.module.fire("onServersReady", this.type, this);
|
|
91
|
+
server.on("error", (error) => {
|
|
92
|
+
this.log(new nodefonyError(error), "CRITIC");
|
|
93
|
+
});
|
|
94
|
+
resolve(server);
|
|
95
|
+
}).catch((e) => {
|
|
96
|
+
const error = e instanceof Error ? e : new Error(String(e));
|
|
97
|
+
this.log(new nodefonyError(error), "CRITIC");
|
|
98
|
+
server.close();
|
|
99
|
+
reject(error);
|
|
100
|
+
});
|
|
101
|
+
this.kernel?.once("onTerminate", async () => {
|
|
102
|
+
if (!this.server) return;
|
|
103
|
+
try {
|
|
104
|
+
await this.httpTerminator?.terminate();
|
|
105
|
+
this.log(`h2c SHUTDOWN PORT : ${this.port}`, "INFO");
|
|
106
|
+
} catch (e) {
|
|
107
|
+
this.log(e, "ERROR", "TERMINATE");
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
} catch (e) {
|
|
111
|
+
this.log(e, "CRITIC");
|
|
112
|
+
return reject(e instanceof Error ? e : new Error(String(e)));
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
showBanner() {
|
|
117
|
+
if (this.infos) this.log(`Server Listen on h2c://${this.infos.address}:${this.infos.port} Family: ${this.infos.family} Protocol : ${this.protocol}`);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
ServerH2c = __decorate([__decorateParam(1, Inject("HttpKernel"))], ServerH2c);
|
|
121
|
+
/** Famille d'une adresse d'écoute, lue sans conversion (`AddressInfo.family` est une chaîne). */
|
|
122
|
+
function familyOf(address) {
|
|
123
|
+
return address.family === "IPv6" ? "IPv6" : "IPv4";
|
|
124
|
+
}
|
|
125
|
+
var server_h2c_default = ServerH2c;
|
|
126
|
+
export { server_h2c_default as default };
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { asServersConfig, configuredServerPort } from "../../src/servers/kernelServers.js";
|
|
2
|
-
import
|
|
3
|
-
import __decorate from "../../../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorate.js";
|
|
4
|
-
import http_kernel_default from "../http-kernel.js";
|
|
2
|
+
import __decorate from "../../../_virtual/_@oxc-project_runtime@0.155.0/helpers/esm/decorate.js";
|
|
5
3
|
import { handleClientError } from "./clientError.js";
|
|
6
4
|
import { createDrainTerminator } from "./serverShutdown.js";
|
|
7
5
|
import { bindWithFallback, buildBindPlan } from "../../src/servers/portBinder.js";
|
|
8
|
-
import __decorateParam from "../../../_virtual/_@oxc-project_runtime@0.
|
|
9
|
-
import {
|
|
6
|
+
import __decorateParam from "../../../_virtual/_@oxc-project_runtime@0.155.0/helpers/esm/decorateParam.js";
|
|
7
|
+
import { Inject, Service, extend, nodefonyError } from "nodefony";
|
|
10
8
|
import http from "node:http";
|
|
11
|
-
|
|
9
|
+
// nodefony/service/servers/server-http.ts
|
|
12
10
|
let ServerHttp = class ServerHttp extends Service {
|
|
13
11
|
httpKernel;
|
|
14
12
|
module;
|
|
@@ -129,7 +127,6 @@ let ServerHttp = class ServerHttp extends Service {
|
|
|
129
127
|
if (this.infos) this.log(`Server Listen on ${this.scheme}://${this.infos.address}:${this.infos.port} Family: ${this.infos.family} Protocol : ${this.protocol}`);
|
|
130
128
|
}
|
|
131
129
|
};
|
|
132
|
-
ServerHttp = __decorate([__decorateParam(1,
|
|
130
|
+
ServerHttp = __decorate([__decorateParam(1, Inject("HttpKernel"))], ServerHttp);
|
|
133
131
|
var server_http_default = ServerHttp;
|
|
134
|
-
//#endregion
|
|
135
132
|
export { server_http_default as default };
|