@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
|
@@ -11,11 +11,13 @@ import type { IncomingHttpHeaders, IncomingMessage } from "node:http";
|
|
|
11
11
|
import Ws from "ws";
|
|
12
12
|
import httpServer from "../service/servers/server-http.js";
|
|
13
13
|
import httpsServer from "../service/servers/server-https.js";
|
|
14
|
+
import h2cServer from "../service/servers/server-h2c.js";
|
|
14
15
|
import websocketServer from "../service/servers/server-websocket.js";
|
|
15
16
|
import websocketSecureServer from "../service/servers/server-websocket-secure.js";
|
|
16
17
|
import Statics from "./servers/server-static.js";
|
|
17
18
|
import type ReverseProxy from "./reverse-proxy.js";
|
|
18
19
|
import WebsocketContext from "../src/context/websocket/WebsocketContext.js";
|
|
20
|
+
import type { IUpgradeAdmission } from "../src/servers/upgradeDispatch.js";
|
|
19
21
|
import HttpContext from "../src/context/http/HttpContext.js";
|
|
20
22
|
import Context, { HTTPMethod, WebSocketState } from "../src/context/Context.js";
|
|
21
23
|
import Certicates from "./certificates.js";
|
|
@@ -42,9 +44,8 @@ export type httpRequest = http.IncomingMessage | http2.Http2ServerRequest;
|
|
|
42
44
|
export type httpResponse = http.ServerResponse | http2.Http2ServerResponse;
|
|
43
45
|
export { responseEnded } from "../src/context/responseEnded.js";
|
|
44
46
|
export type ContextType = WebsocketContext | HttpContext | Context;
|
|
45
|
-
export type ServerType
|
|
46
|
-
|
|
47
|
-
export type SchemeType = "http" | "https" | "ws" | "wss";
|
|
47
|
+
export type { ServerType, SchemeType } from "../interfaces/IContext.js";
|
|
48
|
+
import type { ServerType, SchemeType } from "../interfaces/IContext.js";
|
|
48
49
|
export interface WsMetaData {
|
|
49
50
|
type?: "message" | "handshake" | undefined;
|
|
50
51
|
state?: WebSocketState | undefined;
|
|
@@ -119,8 +120,6 @@ declare class HttpKernel extends Service implements IHttpKernelInterface {
|
|
|
119
120
|
responseTimeout: {
|
|
120
121
|
http: number;
|
|
121
122
|
https: number;
|
|
122
|
-
http2: number;
|
|
123
|
-
http3: number;
|
|
124
123
|
};
|
|
125
124
|
closeTimeOutWs: {
|
|
126
125
|
ws: number;
|
|
@@ -383,7 +382,7 @@ declare class HttpKernel extends Service implements IHttpKernelInterface {
|
|
|
383
382
|
* pipeline.
|
|
384
383
|
*/
|
|
385
384
|
private dispatchHttpRequest;
|
|
386
|
-
initServers(): Promise<(httpServer | httpsServer | websocketServer | websocketSecureServer)[]>;
|
|
385
|
+
initServers(): Promise<(httpServer | httpsServer | h2cServer | websocketServer | websocketSecureServer)[]>;
|
|
387
386
|
/**
|
|
388
387
|
* Publie les ports EFFECTIFS du runtime (state file), une fois l'écoute établie.
|
|
389
388
|
*
|
|
@@ -542,7 +541,7 @@ declare class HttpKernel extends Service implements IHttpKernelInterface {
|
|
|
542
541
|
* @throws (rejet) le refus du pare-feu, après `onAuthFailure`.
|
|
543
542
|
*/
|
|
544
543
|
private runFirewall;
|
|
545
|
-
createWebsocketContext(scope: Scope, req: IncomingMessage, ws: Ws, type: ServerType): WebsocketContext;
|
|
544
|
+
createWebsocketContext(scope: Scope, req: IncomingMessage, ws: Ws | null, type: ServerType): WebsocketContext;
|
|
546
545
|
/**
|
|
547
546
|
* Teardown d'une connexion WS à sa fermeture : signal d'abandon, hooks
|
|
548
547
|
* post-réponse, persistance de la session, puis libération du scope.
|
|
@@ -550,10 +549,47 @@ declare class HttpKernel extends Service implements IHttpKernelInterface {
|
|
|
550
549
|
* écouteur d'événement synchrone, qui n'attend rien).
|
|
551
550
|
*/
|
|
552
551
|
private finishWebsocket;
|
|
553
|
-
|
|
554
|
-
|
|
552
|
+
/**
|
|
553
|
+
* Point d'entrée d'un upgrade vers une route WebSocket de Nodefony, appelé
|
|
554
|
+
* par le répartiteur d'upgrade AVANT le `101` (#596) : rien ne s'ouvre tant
|
|
555
|
+
* que le pipeline n'a pas dit oui.
|
|
556
|
+
*
|
|
557
|
+
* Les bornes par IP passent en premier, avant tout scope, ALS ou pipeline
|
|
558
|
+
* (symétrie avec le 429 HTTP et avec le proxy inverse) : le vrai vecteur DoS
|
|
559
|
+
* est d'accumuler des sockets ouvertes. La place est rendue à la fermeture du
|
|
560
|
+
* socket du client — même règle que pour un tunnel relayé.
|
|
561
|
+
*
|
|
562
|
+
* @param req - requête d'upgrade
|
|
563
|
+
* @param admission - le verdict à rendre : accepter (`101`) ou refuser (HTTP)
|
|
564
|
+
* @param type - serveur qui a reçu l'upgrade
|
|
565
|
+
* @returns la promesse du traitement de la connexion
|
|
566
|
+
*/
|
|
567
|
+
onWebsocketUpgrade(req: IncomingMessage, admission: IUpgradeAdmission, type: ServerType): Promise<unknown>;
|
|
568
|
+
/**
|
|
569
|
+
* Pipeline d'un handshake WebSocket, dans la bulle ALS de la connexion :
|
|
570
|
+
* jugement (`onConnect`), pare-feu, gardes de l'action — PUIS seulement
|
|
571
|
+
* l'acceptation, la socket et l'action de handshake. Tout refus antérieur à
|
|
572
|
+
* l'acceptation part en statut HTTP (`onError` → `refuseHandshake`).
|
|
573
|
+
*
|
|
574
|
+
* @param scope - scope DI de la connexion
|
|
575
|
+
* @param req - requête d'upgrade
|
|
576
|
+
* @param admission - le verdict à rendre
|
|
577
|
+
* @param type - serveur qui a reçu l'upgrade
|
|
578
|
+
* @returns ce que rend l'action de handshake
|
|
579
|
+
*/
|
|
580
|
+
handleWebsocket(scope: Scope, req: IncomingMessage, admission: IUpgradeAdmission, type: ServerType): Promise<unknown>;
|
|
555
581
|
private releaseOrphanWsScope;
|
|
556
|
-
|
|
582
|
+
/**
|
|
583
|
+
* Juge un handshake WebSocket AVANT son acceptation : hôte, origine,
|
|
584
|
+
* `beforeResolve`, contrôleur (protocole négocié), session. N'ouvre rien —
|
|
585
|
+
* l'acceptation n'a lieu qu'après le pare-feu et les gardes de l'action
|
|
586
|
+
* (cf {@link handleWebsocket}).
|
|
587
|
+
*
|
|
588
|
+
* @param context - contexte du handshake, encore sans socket
|
|
589
|
+
* @param error - erreur levée à la construction du contexte, relancée telle quelle
|
|
590
|
+
* @throws la première erreur du jugement — rendue en statut HTTP par `onError`
|
|
591
|
+
*/
|
|
592
|
+
onConnect(context: WebsocketContext | null, error?: unknown): Promise<void>;
|
|
557
593
|
checkValidDomain(context: ContextType): number;
|
|
558
594
|
isValidDomain(context: ContextType): boolean;
|
|
559
595
|
/**
|
|
@@ -12,3 +12,19 @@ import type { Duplex } from "node:stream";
|
|
|
12
12
|
* @param socket - flux client brut (l'event `clientError` fournit un `Duplex`).
|
|
13
13
|
*/
|
|
14
14
|
export declare function handleClientError(error: NodeJS.ErrnoException, socket: Duplex): void;
|
|
15
|
+
/**
|
|
16
|
+
* Gère l'event `sessionError` d'un serveur HTTP/2 (h2c ou TLS) : un pair PARTI
|
|
17
|
+
* se tait, toute autre erreur est rapportée.
|
|
18
|
+
*
|
|
19
|
+
* Une session réinitialisée par le pair n'a rien à diagnostiquer. C'est la
|
|
20
|
+
* signature d'une sonde de port — `nodefony status`, `doctor`, le superviseur
|
|
21
|
+
* de développement, la sonde `tcpSocket` d'un orchestrateur — qui se connecte
|
|
22
|
+
* puis ferme sans lire le `SETTINGS` que le serveur envoie dès l'ouverture : le
|
|
23
|
+
* système ferme alors par un RST plutôt qu'un FIN, et Node lève `ECONNRESET`.
|
|
24
|
+
* La rapporter imprimait une pile entière par sonde. La règle « client parti »
|
|
25
|
+
* est celle des frames WebSocket ({@link isPeerGoneError}), pas une copie.
|
|
26
|
+
*
|
|
27
|
+
* @param error - erreur de session émise par `node:http2`
|
|
28
|
+
* @param report - rapporte une erreur réelle, à la sévérité choisie par le serveur
|
|
29
|
+
*/
|
|
30
|
+
export declare function handleSessionError(error: Error, report: (error: Error) => void): void;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Service, type Module, FamilyType } from "nodefony";
|
|
2
|
+
import HttpKernel, { ProtocolType, ServerType, SchemeType } from "../http-kernel.js";
|
|
3
|
+
import http2 from "node:http2";
|
|
4
|
+
import { AddressInfo } from "node:net";
|
|
5
|
+
import { type IDrainTerminator } from "./serverShutdown.js";
|
|
6
|
+
import type { IHttpConfig } from "../../config/config.js";
|
|
7
|
+
import type { DefaultOptionsService } from "nodefony";
|
|
8
|
+
/**
|
|
9
|
+
* Serveur HTTP/2 en clair (h2c, connaissance préalable — RFC 9113 §3.3), sur un
|
|
10
|
+
* port DÉDIÉ (`servers.h2c`, 5153 par défaut), pour un proxy inverse qui parle
|
|
11
|
+
* HTTP/2 à ses amonts.
|
|
12
|
+
*
|
|
13
|
+
* Il partage le chemin HTTP/2 du 5152 — même `onHttpRequest`, mêmes limites
|
|
14
|
+
* anti-DoS (`http2ServerLimits`), même drain par GOAWAY — sans TLS : `serverType`
|
|
15
|
+
* vaut `"http"`, le schéma vient du transport ou d'un proxy de confiance, jamais
|
|
16
|
+
* du pseudo-en-tête `:scheme`. Le protocole du saut (`"h2c"`) se constate sur la
|
|
17
|
+
* requête (`transport.ts#alpnProtocolOf`).
|
|
18
|
+
*
|
|
19
|
+
* Hors de son périmètre, délibérément : HTTP/1.1 (refusé par la préface HTTP/2 —
|
|
20
|
+
* sondes et clients HTTP/1.1 restent sur le port HTTP), WebSocket (aucun CONNECT
|
|
21
|
+
* étendu, RFC 8441 : un proxy route `Upgrade: websocket` vers le port HTTP) et la
|
|
22
|
+
* bascule `Upgrade: h2c` (retirée par RFC 9113 §3.1).
|
|
23
|
+
*/
|
|
24
|
+
declare class ServerH2c extends Service {
|
|
25
|
+
private readonly httpKernel;
|
|
26
|
+
options: IHttpConfig["http"] & DefaultOptionsService;
|
|
27
|
+
module: Module<IHttpConfig>;
|
|
28
|
+
server: http2.Http2Server | null;
|
|
29
|
+
httpTerminator: IDrainTerminator | null;
|
|
30
|
+
port: number;
|
|
31
|
+
protocol: ProtocolType;
|
|
32
|
+
ready: boolean;
|
|
33
|
+
type: ServerType;
|
|
34
|
+
domain: string | null;
|
|
35
|
+
scheme: SchemeType;
|
|
36
|
+
address: string | null;
|
|
37
|
+
family: FamilyType | null;
|
|
38
|
+
active: boolean;
|
|
39
|
+
infos: AddressInfo | null;
|
|
40
|
+
constructor(module: Module<IHttpConfig>, httpKernel: HttpKernel);
|
|
41
|
+
/**
|
|
42
|
+
* Crée et met en écoute le serveur h2c.
|
|
43
|
+
*
|
|
44
|
+
* @returns le serveur à l'écoute
|
|
45
|
+
* @throws BootConfigurationError si `servers.h2c.port` est celui du serveur
|
|
46
|
+
* HTTP ou HTTPS — un port partagé n'est pas un conflit à contourner
|
|
47
|
+
*/
|
|
48
|
+
createServer(): Promise<http2.Http2Server>;
|
|
49
|
+
showBanner(): void;
|
|
50
|
+
}
|
|
51
|
+
export default ServerH2c;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Service, Module, FamilyType } from "nodefony";
|
|
1
|
+
import { Service, type Module, FamilyType } from "nodefony";
|
|
2
2
|
import HttpKernel, { ProtocolType, ServerType, SchemeType } from "../http-kernel.js";
|
|
3
3
|
import http from "node:http";
|
|
4
4
|
import http2 from "node:http2";
|
|
5
5
|
import { AddressInfo } from "node:net";
|
|
6
|
-
import {
|
|
6
|
+
import { type IDrainTerminator } from "./serverShutdown.js";
|
|
7
7
|
import type { IHttpConfig } from "../../config/config.js";
|
|
8
8
|
import type { DefaultOptionsService } from "nodefony";
|
|
9
9
|
declare class ServerHttp extends Service {
|
|
@@ -11,7 +11,7 @@ declare class ServerHttp extends Service {
|
|
|
11
11
|
options: IHttpConfig["http"] & DefaultOptionsService;
|
|
12
12
|
module: Module;
|
|
13
13
|
server: http.Server | http2.Http2Server | null;
|
|
14
|
-
httpTerminator:
|
|
14
|
+
httpTerminator: IDrainTerminator | null;
|
|
15
15
|
port: number;
|
|
16
16
|
protocol: ProtocolType;
|
|
17
17
|
ready: boolean;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { Service, Module, FamilyType } from "nodefony";
|
|
1
|
+
import { Service, type Module, FamilyType } from "nodefony";
|
|
2
2
|
import HttpKernel, { ProtocolType, ServerType, SchemeType } from "../http-kernel.js";
|
|
3
3
|
import https from "node:https";
|
|
4
4
|
import http2 from "node:http2";
|
|
5
|
-
import {
|
|
5
|
+
import { type IDrainTerminator } from "./serverShutdown.js";
|
|
6
6
|
import { AddressInfo } from "node:net";
|
|
7
7
|
import type { IHttpConfig } from "../../config/config.js";
|
|
8
8
|
import type { DefaultOptionsService } from "nodefony";
|
|
9
9
|
declare class ServerHttps extends Service {
|
|
10
10
|
private readonly httpKernel;
|
|
11
11
|
options: IHttpConfig["https"] & DefaultOptionsService;
|
|
12
|
-
httpTerminator:
|
|
12
|
+
httpTerminator: IDrainTerminator | null;
|
|
13
13
|
module: Module;
|
|
14
14
|
server: https.Server | http2.Http2SecureServer | null;
|
|
15
15
|
port: number;
|
|
@@ -23,7 +23,7 @@ declare class ServerHttps extends Service {
|
|
|
23
23
|
active: boolean;
|
|
24
24
|
infos: AddressInfo | null;
|
|
25
25
|
constructor(module: Module, httpKernel: HttpKernel);
|
|
26
|
-
terminator():
|
|
26
|
+
terminator(): IDrainTerminator;
|
|
27
27
|
setPort(): number;
|
|
28
28
|
createServer(): Promise<https.Server | http2.Http2SecureServer>;
|
|
29
29
|
createServerH2(): Promise<http2.Http2SecureServer>;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { WebSocketServer } from "ws";
|
|
2
2
|
import { Service, Module, FamilyType } from "nodefony";
|
|
3
3
|
import type { DefaultOptionsService } from "nodefony";
|
|
4
4
|
import type { IHttpConfig } from "../../config/config.js";
|
|
5
5
|
import HttpKernel, { ProtocolType, ServerType, SchemeType } from "../http-kernel.js";
|
|
6
6
|
import { AddressInfo } from "node:net";
|
|
7
|
-
import type { IncomingMessage } from "node:http";
|
|
8
7
|
import httpsServers from "./server-https.js";
|
|
9
8
|
declare class WebsocketSecure extends Service {
|
|
10
9
|
#private;
|
|
@@ -26,7 +25,6 @@ declare class WebsocketSecure extends Service {
|
|
|
26
25
|
constructor(module: Module, httpKernel: HttpKernel);
|
|
27
26
|
setPort(): number;
|
|
28
27
|
createServer(serverHttps: httpsServers): Promise<WebSocketServer>;
|
|
29
|
-
onConnection(ws: Ws, req: IncomingMessage): void;
|
|
30
28
|
terminate(): Promise<boolean>;
|
|
31
29
|
showBanner(): void;
|
|
32
30
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { WebSocketServer } from "ws";
|
|
2
2
|
import { Service, Module, FamilyType } from "nodefony";
|
|
3
3
|
import type { DefaultOptionsService } from "nodefony";
|
|
4
4
|
import type { IHttpConfig } from "../../config/config.js";
|
|
5
5
|
import HttpKernel, { ProtocolType, ServerType, SchemeType } from "../http-kernel.js";
|
|
6
6
|
import { AddressInfo } from "node:net";
|
|
7
|
-
import type { IncomingMessage } from "node:http";
|
|
8
7
|
import httpServer from "./server-http.js";
|
|
9
8
|
declare class Websocket extends Service {
|
|
10
9
|
#private;
|
|
@@ -26,7 +25,6 @@ declare class Websocket extends Service {
|
|
|
26
25
|
constructor(module: Module, httpKernel: HttpKernel);
|
|
27
26
|
setPort(): number;
|
|
28
27
|
createServer(serverHttp: httpServer): Promise<WebSocketServer>;
|
|
29
|
-
onConnection(ws: Ws, req: IncomingMessage): void;
|
|
30
28
|
terminate(): Promise<boolean>;
|
|
31
29
|
showBanner(): void;
|
|
32
30
|
}
|
|
@@ -1,27 +1,41 @@
|
|
|
1
|
-
import { HttpTerminator } from "http-terminator";
|
|
2
1
|
import type { Server as HttpServer } from "node:http";
|
|
3
2
|
import type { Server as HttpsServer } from "node:https";
|
|
4
|
-
import type { Http2SecureServer } from "node:http2";
|
|
3
|
+
import type { Http2SecureServer, Http2Server } from "node:http2";
|
|
4
|
+
/** Serveur que `createDrainTerminator` sait drainer. */
|
|
5
|
+
export type DrainableServer = HttpServer | HttpsServer | Http2Server | Http2SecureServer;
|
|
6
|
+
/** Arrêt gracieux d'un serveur, rendu par `createDrainTerminator`. */
|
|
7
|
+
export interface IDrainTerminator {
|
|
8
|
+
/**
|
|
9
|
+
* Draine puis ferme le serveur ; idempotent (le deuxième appel rend la même promesse).
|
|
10
|
+
*
|
|
11
|
+
* @returns une promesse résolue quand toutes les connexions sont fermées
|
|
12
|
+
*/
|
|
13
|
+
terminate(): Promise<void>;
|
|
14
|
+
}
|
|
5
15
|
/**
|
|
6
|
-
* Fabrique
|
|
16
|
+
* Fabrique l'arrêt gracieux d'un serveur HTTP/1.1, HTTPS, HTTP/2 sur TLS ou h2c.
|
|
7
17
|
*
|
|
8
|
-
* Au `terminate()` (
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
18
|
+
* Au `terminate()` (SIGTERM, `docker stop`), le serveur cesse d'accepter, puis :
|
|
19
|
+
* - **HTTP/2** : chaque session reçoit un GOAWAY (`session.close()`) — les flux
|
|
20
|
+
* en vol se terminent, les nouveaux sont refusés, et le client sait qu'il doit
|
|
21
|
+
* rouvrir ailleurs au lieu de constater une coupure ;
|
|
22
|
+
* - **HTTP/1.1** : la réponse en vol part avec `Connection: close`, la socket
|
|
23
|
+
* inactive est fermée tout de suite, une requête qui arrive encore sur une
|
|
24
|
+
* socket gardée ouverte reçoit aussi `Connection: close`.
|
|
25
|
+
*
|
|
26
|
+
* Ce qui reste après `shutdownTimeout` ms est détruit. `server.close()` est
|
|
27
|
+
* appelé ici : ne pas le rappeler derrière.
|
|
13
28
|
*
|
|
14
29
|
* ⚠️ Les sockets WebSocket upgradées (sans réponse HTTP en cours) sont détruites
|
|
15
|
-
* SANS frame Close
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* HTTP en `once`.
|
|
30
|
+
* SANS frame Close → les serveurs WS doivent fermer leurs clients (close 1001)
|
|
31
|
+
* AVANT ce drain. Garanti par l'ordre des listeners `onTerminate` : WS/WSS
|
|
32
|
+
* s'attachent en `prependOnceListener`, les serveurs HTTP en `once`.
|
|
19
33
|
*
|
|
20
|
-
* @param server - serveur Node à drainer (
|
|
34
|
+
* @param server - serveur Node à drainer, créé AVANT son `listen` (le suivi des
|
|
35
|
+
* connexions commence ici)
|
|
21
36
|
* @param shutdownTimeout - délai de drain en ms avant destruction forcée
|
|
22
|
-
* @returns
|
|
37
|
+
* @returns l'arrêt à invoquer au shutdown
|
|
23
38
|
*/
|
|
24
|
-
export declare function createDrainTerminator(server:
|
|
39
|
+
export declare function createDrainTerminator(server: DrainableServer, shutdownTimeout?: number): IDrainTerminator;
|
|
25
40
|
/** Drain par défaut (ms) — même valeur que le défaut Zod `servers.*.shutdownTimeout`. */
|
|
26
41
|
export declare const DEFAULT_SHUTDOWN_TIMEOUT = 5000;
|
|
27
|
-
export type { HttpTerminator };
|
|
@@ -7,6 +7,7 @@ import http2 from "node:http2";
|
|
|
7
7
|
import http from "node:http";
|
|
8
8
|
import https from "node:https";
|
|
9
9
|
import HttpKernel, { ServerType, Data, SchemeType } from "../../service/http-kernel.js";
|
|
10
|
+
import type { AlpnProtocol, ProtocolName } from "../../interfaces/IContext.js";
|
|
10
11
|
import HttpResponse from "./http/Response.js";
|
|
11
12
|
import Http2Response from "./http2/Response.js";
|
|
12
13
|
import WebsocketResponse from "./websocket/Response.js";
|
|
@@ -50,7 +51,15 @@ declare class Context extends Service implements IContextInterface {
|
|
|
50
51
|
requested: boolean;
|
|
51
52
|
sessionStarting: boolean;
|
|
52
53
|
domain: string;
|
|
53
|
-
|
|
54
|
+
/** Famille traitée (`network.protocol.name` d'OpenTelemetry) — union ouverte. */
|
|
55
|
+
type: ProtocolName;
|
|
56
|
+
/** Serveur qui a reçu la requête — choisit la configuration par serveur. */
|
|
57
|
+
serverType: ServerType;
|
|
58
|
+
/**
|
|
59
|
+
* Protocole du saut local (registre IANA ALPN) — union ouverte. Une connexion
|
|
60
|
+
* WebSocket naît d'un upgrade HTTP/1.1 ; `HttpContext` le constate sur la requête.
|
|
61
|
+
*/
|
|
62
|
+
alpnProtocol: AlpnProtocol;
|
|
54
63
|
server?: WebSocketServer | http.Server | https.Server | http2.Http2SecureServer | null | undefined;
|
|
55
64
|
httpKernel: HttpKernel | null;
|
|
56
65
|
request: contextRequest | null;
|
|
@@ -128,7 +137,7 @@ declare class Context extends Service implements IContextInterface {
|
|
|
128
137
|
metaData: Data;
|
|
129
138
|
scheme: SchemeType;
|
|
130
139
|
webSocketState: WebSocketState;
|
|
131
|
-
constructor(container: Container | Scope,
|
|
140
|
+
constructor(container: Container | Scope, serverType: ServerType);
|
|
132
141
|
/**
|
|
133
142
|
* Assemble l'enveloppe `metaData` de la requête (`nodefony.*` + `route`
|
|
134
143
|
* snapshot per-requête + overrides appelant). Délègue au builder monomorphe
|
|
@@ -183,8 +192,8 @@ declare class Context extends Service implements IContextInterface {
|
|
|
183
192
|
clean(): void;
|
|
184
193
|
/**
|
|
185
194
|
* Log d'un event du cycle de vie — gate boot-time (V2.1) : en production le
|
|
186
|
-
* Pdu n'est PAS construit (return avant toute allocation). Hors prod,
|
|
187
|
-
*
|
|
195
|
+
* Pdu n'est PAS construit (return avant toute allocation). Hors prod : DEBUG,
|
|
196
|
+
* pour le Suivi de requête de Studio — la ligne `req` porte le bilan.
|
|
188
197
|
*/
|
|
189
198
|
private logEvent;
|
|
190
199
|
fire(event: KernelEventsType, ...args: unknown[]): boolean;
|
|
@@ -53,7 +53,7 @@ declare class HttpContext extends Context implements IHttpContextInterface {
|
|
|
53
53
|
request: HttpRequestType;
|
|
54
54
|
response: HttpRsponseType;
|
|
55
55
|
uploadService: uploadService | null;
|
|
56
|
-
constructor(container: Container | Scope, request: http.IncomingMessage | http2.Http2ServerRequest, response: http.ServerResponse | http2.Http2ServerResponse,
|
|
56
|
+
constructor(container: Container | Scope, request: http.IncomingMessage | http2.Http2ServerRequest, response: http.ServerResponse | http2.Http2ServerResponse, serverType: ServerType);
|
|
57
57
|
/**
|
|
58
58
|
* URL d'origine effective, construite À LA DEMANDE (1ʳᵉ lecture, puis
|
|
59
59
|
* mémoïsée). `Origin` invalide ou `null` (RFC 6454) → repli sur l'URL de la
|
|
@@ -5,6 +5,7 @@ import { URL } from "node:url";
|
|
|
5
5
|
import { HTTPMethod, Cookies } from "../Context.js";
|
|
6
6
|
import QS from "qs";
|
|
7
7
|
import { ParserXml, ParserQs, Parser, acceptParser } from "./parser.js";
|
|
8
|
+
import type { RequestBody } from "../../../interfaces/IRequest.js";
|
|
8
9
|
import { UploadedFile } from "../../../service/upload/upload-service.js";
|
|
9
10
|
import type { IParsedUploadFile, IUploadOptions } from "../../../interfaces/IUpload.js";
|
|
10
11
|
import { Pci, Pdu, Message, Severity, Msgid } from "nodefony";
|
|
@@ -75,22 +76,24 @@ declare class HttpRequest {
|
|
|
75
76
|
get url(): URL;
|
|
76
77
|
set url(u: URL);
|
|
77
78
|
parser: ParserType | null;
|
|
78
|
-
queryPost: Record<string, unknown>;
|
|
79
|
-
queryGet: Record<string, unknown>;
|
|
80
|
-
queryFile: UploadedFile[];
|
|
81
|
-
query: Record<string, unknown>;
|
|
82
79
|
/**
|
|
83
|
-
* Le CORPS de la requête, parsé
|
|
84
|
-
* Fastify, NestJS)
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
80
|
+
* Le CORPS de la requête, parsé (JSON, urlencoded, XML, champs multipart) —
|
|
81
|
+
* nom universel de l'écosystème (Express, Fastify, NestJS) et celui
|
|
82
|
+
* d'`IAdminRequest.body`. Jamais un paramètre d'URL : ceux-là sont dans
|
|
83
|
+
* {@link query}, et les deux ne fusionnent pas.
|
|
84
|
+
*/
|
|
85
|
+
body: RequestBody;
|
|
86
|
+
/**
|
|
87
|
+
* Les fichiers reçus dans un corps multipart, déjà écrits dans le répertoire
|
|
88
|
+
* temporaire — lus par `@UploadedFile()` / `@UploadedFiles()`. Les champs
|
|
89
|
+
* texte du même corps sont dans {@link body}.
|
|
90
90
|
*
|
|
91
|
-
*
|
|
91
|
+
* Lecture seule : une requête sans upload rend un vide partagé et gelé,
|
|
92
|
+
* aucune allocation.
|
|
92
93
|
*/
|
|
93
|
-
get
|
|
94
|
+
get files(): readonly UploadedFile[];
|
|
95
|
+
/** Les paramètres d'URL, seuls — jamais un champ du corps ({@link body}). */
|
|
96
|
+
query: Record<string, unknown>;
|
|
94
97
|
queryStringOptions: (QS.IParseOptions & {
|
|
95
98
|
decoder?: undefined;
|
|
96
99
|
}) | undefined;
|
|
@@ -112,7 +115,7 @@ declare class HttpRequest {
|
|
|
112
115
|
* remplace le `once("onRequestEnd")` du ctor qui allouait 1 onceWrapper +
|
|
113
116
|
* 1 closure à CHAQUE requête.
|
|
114
117
|
*
|
|
115
|
-
* Il porte le CORPS (`
|
|
118
|
+
* Il porte le CORPS (`body`), jamais les paramètres d'URL : un seul sens de
|
|
116
119
|
* `body` dans tout le framework, celui de l'écosystème et d'`IAdminRequest`.
|
|
117
120
|
*/
|
|
118
121
|
private fireRequestEnd;
|
|
@@ -228,7 +231,9 @@ declare class HttpRequest {
|
|
|
228
231
|
/**
|
|
229
232
|
* Scheme effectif côté client : `Forwarded`/`X-Forwarded-*` résolu de façon
|
|
230
233
|
* canonique (this.forwarded, gated proxy de confiance) ; sinon le transport
|
|
231
|
-
* réel. HTTP/2
|
|
234
|
+
* réel. Vaut pour HTTP/2 aussi : le pseudo-en-tête `:scheme` vient du client
|
|
235
|
+
* (RFC 9113 §8.3.1) et n'est jamais cru — sur h2c, `:scheme: https` ferait
|
|
236
|
+
* passer une connexion claire pour chiffrée.
|
|
232
237
|
*/
|
|
233
238
|
protected resolveScheme(request: http.IncomingMessage | http2.Http2ServerRequest): string;
|
|
234
239
|
getFullUrl(request?: http.IncomingMessage | http2.Http2ServerRequest): string;
|
|
@@ -50,6 +50,17 @@ declare class HttpResponse {
|
|
|
50
50
|
deleteCookieByName(name: string): boolean;
|
|
51
51
|
setCookies(): void | http.ServerResponse<http.IncomingMessage>;
|
|
52
52
|
setCookie(cookie: Cookie): void | http.ServerResponse<http.IncomingMessage>;
|
|
53
|
+
/**
|
|
54
|
+
* Journalise en DEBUG un cookie posé, sa VALEUR MASQUÉE : nom et attributs
|
|
55
|
+
* seulement. Le journal de développement se lit par le plan d'administration
|
|
56
|
+
* — un identifiant de session y entrerait chez quiconque le consulte.
|
|
57
|
+
* La ligne n'est construite que si DEBUG passe le gate du syslog pour ce
|
|
58
|
+
* `msgid` (debug ciblé compris) : rien n'est alloué en production.
|
|
59
|
+
*
|
|
60
|
+
* @param cookie - le cookie posé.
|
|
61
|
+
* @param serialized - sa forme `Set-Cookie`, déjà calculée pour l'en-tête.
|
|
62
|
+
*/
|
|
63
|
+
private logCookie;
|
|
53
64
|
setHeader(name: string, value: number | string | readonly string[]): void | http.ServerResponse<http.IncomingMessage>;
|
|
54
65
|
setHeaders(obj: OutgoingHttpHeaders): OutgoingHttpHeaders;
|
|
55
66
|
setContentType(type?: string, encoding?: BufferEncoding): void | http.ServerResponse<http.IncomingMessage>;
|
|
@@ -22,6 +22,22 @@ declare class Parser {
|
|
|
22
22
|
protected ended(): Promise<void>;
|
|
23
23
|
parse(): Promise<this>;
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Corps d'un type que le framework ne décode pas : livré TEL QU'IL EST REÇU,
|
|
27
|
+
* jamais remplacé par un objet vide qui mentirait.
|
|
28
|
+
*
|
|
29
|
+
* - `text/*` → une chaîne, décodée au `charset` du `Content-Type` (UTF-8 par
|
|
30
|
+
* défaut) — comme une trame texte RFC 6455 ;
|
|
31
|
+
* - tout autre type, et un corps sans `Content-Type` (RFC 9110 §8.3 : supposé
|
|
32
|
+
* `application/octet-stream`) → les OCTETS : le `Buffer` déjà assemblé dans
|
|
33
|
+
* `request.data`, sans copie — donc un `Uint8Array`, le type d'octets que
|
|
34
|
+
* la socket livrera aussi (#618). Un même schéma passe par les deux portes.
|
|
35
|
+
*
|
|
36
|
+
* Un corps VIDE laisse `body` tel quel : une requête sans charge ne change pas.
|
|
37
|
+
*/
|
|
38
|
+
declare class ParserRaw extends Parser {
|
|
39
|
+
parse(): Promise<this>;
|
|
40
|
+
}
|
|
25
41
|
declare class ParserQs extends Parser {
|
|
26
42
|
parserOptions: QS.IParseOptions;
|
|
27
43
|
charset: BufferEncoding;
|
|
@@ -35,7 +51,7 @@ declare class ParserXml extends Parser {
|
|
|
35
51
|
parse(): Promise<this>;
|
|
36
52
|
}
|
|
37
53
|
/**
|
|
38
|
-
* Parse un corps `application/json` (ou `*+json`) en objet → `
|
|
54
|
+
* Parse un corps `application/json` (ou `*+json`) en objet → `body`
|
|
39
55
|
* (source lue par le décorateur `@Body`). Reprend le rôle de l'ancien plugin
|
|
40
56
|
* `json` de formidable, supprimé avec le passage à busboy (multipart seul).
|
|
41
57
|
* Lenient : un corps JSON malformé est ignoré (pas de throw — `parse()` est
|
|
@@ -62,4 +78,4 @@ type AcceptEntry = {
|
|
|
62
78
|
[key: string]: RegExp | number | string | undefined;
|
|
63
79
|
};
|
|
64
80
|
declare const acceptParser: (acc?: string) => AcceptEntry[];
|
|
65
|
-
export { Parser, ParserXml, ParserQs, ParserJson, acceptParser };
|
|
81
|
+
export { Parser, ParserRaw, ParserXml, ParserQs, ParserJson, acceptParser };
|
|
@@ -5,10 +5,10 @@ import { HTTPMethod } from "../Context.js";
|
|
|
5
5
|
declare class Http2Request extends HttpRequest {
|
|
6
6
|
request: http2.Http2ServerRequest;
|
|
7
7
|
constructor(request: http2.Http2ServerRequest, context: HttpContext);
|
|
8
|
+
/** `:authority`, sinon `Host` — cf `requestAuthority` (RFC 9113 §8.3.1). */
|
|
8
9
|
getHost(): string | undefined;
|
|
9
10
|
getUserAgent(): string | undefined;
|
|
10
11
|
getMethod(): HTTPMethod;
|
|
11
12
|
getRawTarget(): string | undefined;
|
|
12
|
-
protected resolveScheme(): string;
|
|
13
13
|
}
|
|
14
14
|
export default Http2Request;
|
|
@@ -3,6 +3,11 @@ import type { MaybePromise } from "nodefony";
|
|
|
3
3
|
import http from "node:http";
|
|
4
4
|
import HttpContext from "../http/HttpContext.js";
|
|
5
5
|
import HttpResponse from "../http/Response.js";
|
|
6
|
+
/** Ce que la fusion lit d'une réponse Node : ses en-têtes posés, nom par nom. */
|
|
7
|
+
interface IHeaderSource {
|
|
8
|
+
getHeaderNames(): string[];
|
|
9
|
+
getHeader(name: string): http.OutgoingHttpHeader | undefined;
|
|
10
|
+
}
|
|
6
11
|
/**
|
|
7
12
|
* Compose les en-têtes d'une réponse HTTP/2 : ceux posés sur la réponse, puis
|
|
8
13
|
* ceux passés à `writeHead`, qui gagnent.
|
|
@@ -13,12 +18,17 @@ import HttpResponse from "../http/Response.js";
|
|
|
13
18
|
* (`ERR_HTTP2_HEADER_SINGLE_VALUE`), soit une 500 sur tout média servi en
|
|
14
19
|
* HTTP/2. HTTP/2 n'a de toute façon que des noms en minuscules (RFC 9113 §8.2.1).
|
|
15
20
|
*
|
|
21
|
+
* Les en-têtes posés se lisent nom par nom (`getHeaderNames`, déjà en
|
|
22
|
+
* minuscules) : `getHeaders()` les recopiait d'abord dans un objet sans
|
|
23
|
+
* prototype, avant cette fusion — 3,8 µs par réponse pour 12 en-têtes,
|
|
24
|
+
* contre 1,1 µs en une passe.
|
|
25
|
+
*
|
|
16
26
|
* @param statusMessage - message de statut, recopié en `x-status-message`
|
|
17
|
-
* @param current - en-têtes déjà posés
|
|
27
|
+
* @param current - la réponse Node qui porte les en-têtes déjà posés
|
|
18
28
|
* @param extra - en-têtes passés à `writeHead` (objet, ou liste plate clé/valeur)
|
|
19
29
|
* @returns les en-têtes à transmettre à `respond()`
|
|
20
30
|
*/
|
|
21
|
-
export declare function mergeResponseHeaders(statusMessage: string, current:
|
|
31
|
+
export declare function mergeResponseHeaders(statusMessage: string, current: IHeaderSource, extra?: http.OutgoingHttpHeaders | http.OutgoingHttpHeader[]): http.OutgoingHttpHeaders;
|
|
22
32
|
declare class Http2Response extends HttpResponse {
|
|
23
33
|
statusCode: number;
|
|
24
34
|
stream: http2.ServerHttp2Stream | null;
|
|
@@ -27,9 +37,9 @@ declare class Http2Response extends HttpResponse {
|
|
|
27
37
|
isHeaderSent(): boolean;
|
|
28
38
|
writeHead(statusCode?: number, headers?: http.OutgoingHttpHeaders | http.OutgoingHttpHeader[]): void;
|
|
29
39
|
/**
|
|
30
|
-
* Écrit le corps sur le flux HTTP/2
|
|
31
|
-
*
|
|
32
|
-
*
|
|
40
|
+
* Écrit le corps sur le flux HTTP/2 et, pour une réponse unique, le termine
|
|
41
|
+
* d'un seul `end(corps)`. Synchrone, sauf en streaming (`flush()`) : une
|
|
42
|
+
* promesse réglée par le rappel d'écriture, la contre-pression (#505).
|
|
33
43
|
*
|
|
34
44
|
* @returns la réponse, ou sa promesse.
|
|
35
45
|
*/
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { AlpnProtocol, ProtocolName, ServerType } from "../../interfaces/IContext.js";
|
|
2
|
+
/**
|
|
3
|
+
* Famille du protocole traité par un contexte, déduite du serveur qui l'a
|
|
4
|
+
* reçu. Règle UNIQUE : `Context` la pose à la construction.
|
|
5
|
+
*
|
|
6
|
+
* @param serverType - identité du serveur (`http`, `https`, `ws`, `wss`)
|
|
7
|
+
* @returns `"websocket"` pour `ws`/`wss`, `"http"` sinon
|
|
8
|
+
*/
|
|
9
|
+
export declare function protocolNameOf(serverType: ServerType): ProtocolName;
|
|
10
|
+
/**
|
|
11
|
+
* Ce que la détection lit d'une requête Node, et rien d'autre : `http.IncomingMessage`
|
|
12
|
+
* (HTTP/1.1) et `http2.Http2ServerRequest` (h2, h2c) le satisfont par leur forme, sans
|
|
13
|
+
* transtypage — et une doublure de test s'écrit en littéral.
|
|
14
|
+
*/
|
|
15
|
+
export interface IAlpnSource {
|
|
16
|
+
readonly httpVersionMajor: number;
|
|
17
|
+
readonly stream?: {
|
|
18
|
+
readonly session?: {
|
|
19
|
+
readonly alpnProtocol?: string | undefined;
|
|
20
|
+
} | undefined;
|
|
21
|
+
} | undefined;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Protocole du saut qui a porté cette requête jusqu'au processus, au sens du
|
|
25
|
+
* registre IANA des identifiants ALPN. Règle UNIQUE : `HttpContext` la lit pour
|
|
26
|
+
* choisir ses classes de requête et de réponse.
|
|
27
|
+
*
|
|
28
|
+
* La valeur se CONSTATE sur la requête, elle ne se déduit pas du serveur : un
|
|
29
|
+
* même serveur TLS reçoit HTTP/1.1 et h2 (`allowHTTP1`). Pour h2, c'est la
|
|
30
|
+
* session de Node qui tranche — `Http2Session.alpnProtocol` vaut `"h2c"` sur
|
|
31
|
+
* une session en clair, l'ALPN négocié (`"h2"`) sur une session TLS.
|
|
32
|
+
*
|
|
33
|
+
* @param request - la requête Node reçue par le serveur
|
|
34
|
+
* @returns `"http/1.1"`, `"h2"` ou `"h2c"`
|
|
35
|
+
*/
|
|
36
|
+
export declare function alpnProtocolOf(request: IAlpnSource): AlpnProtocol;
|
|
37
|
+
/**
|
|
38
|
+
* Autorité (hôte et port) d'une requête, HTTP/1.1 comme HTTP/2. Règle UNIQUE
|
|
39
|
+
* des lecteurs du serveur.
|
|
40
|
+
*
|
|
41
|
+
* `:authority` d'abord, puis `Host` (RFC 9113 §8.3.1). Le repli n'est pas un
|
|
42
|
+
* confort : un intermédiaire qui convertit une requête HTTP/1.1 de forme origine
|
|
43
|
+
* (`GET /chemin`) en HTTP/2 ne DOIT PAS fabriquer `:authority` — il garde
|
|
44
|
+
* `Host`. C'est ce que fait HAProxy `proto h2` vers un port h2c : sans ce repli,
|
|
45
|
+
* l'hôte est introuvable et la requête part en 421.
|
|
46
|
+
*
|
|
47
|
+
* @param headers - en-têtes de la requête Node (`IncomingMessage` ou `Http2ServerRequest`).
|
|
48
|
+
* @returns l'autorité, ou `undefined` si la requête n'en porte aucune.
|
|
49
|
+
*/
|
|
50
|
+
export declare function requestAuthority(headers: {
|
|
51
|
+
host?: string | undefined;
|
|
52
|
+
":authority"?: string | undefined;
|
|
53
|
+
}): string | undefined;
|