@nodefony/http 10.0.0-beta.5 → 10.0.0-beta.7
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/README.md +24 -0
- package/dist/_virtual/{_@oxc-project_runtime@0.155.0 → _@oxc-project_runtime@0.158.0}/helpers/esm/decorate.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.155.0 → _@oxc-project_runtime@0.158.0}/helpers/esm/decorateParam.js +1 -1
- package/dist/index.js +30 -26
- package/dist/nodefony/command/proxyGenerateCommand.js +2 -2
- package/dist/nodefony/config/config.js +29 -4
- package/dist/nodefony/grpc/GrpcCall.js +298 -0
- package/dist/nodefony/grpc/GrpcEndpoint.js +528 -0
- package/dist/nodefony/grpc/index.js +4 -0
- package/dist/nodefony/interfaces/IRpcCall.js +1 -0
- package/dist/nodefony/service/ProfilerAdminApi.js +5 -2
- package/dist/nodefony/service/audit-logger.js +52 -6
- package/dist/nodefony/service/error-renderer.js +47 -13
- package/dist/nodefony/service/http-kernel.js +306 -49
- package/dist/nodefony/service/pretty-request-logger.js +5 -3
- package/dist/nodefony/service/request-logger.js +21 -6
- package/dist/nodefony/service/reverse-proxy.js +8 -3
- package/dist/nodefony/service/servers/clientError.js +53 -4
- package/dist/nodefony/service/servers/server-h2c.js +6 -6
- package/dist/nodefony/service/servers/server-http.js +6 -4
- package/dist/nodefony/service/servers/server-https.js +14 -7
- package/dist/nodefony/service/servers/server-static.js +1 -6
- package/dist/nodefony/service/servers/server-websocket-secure.js +7 -11
- package/dist/nodefony/service/servers/server-websocket.js +7 -11
- package/dist/nodefony/service/servers/serverShutdown.js +43 -6
- package/dist/nodefony/service/sessions/sessions-service.js +7 -7
- package/dist/nodefony/service/upload/upload-service.js +2 -2
- package/dist/nodefony/src/assets/prebuiltUi.js +23 -5
- package/dist/nodefony/src/context/Context.js +12 -1
- package/dist/nodefony/src/context/http/ByteStream.js +364 -0
- package/dist/nodefony/src/context/http/HttpContext.js +139 -32
- package/dist/nodefony/src/context/http/Request.js +111 -22
- package/dist/nodefony/src/context/http/Response.js +459 -37
- package/dist/nodefony/src/context/http/SseStream.js +83 -148
- package/dist/nodefony/src/context/http/StreamLifecycle.js +582 -0
- package/dist/nodefony/src/context/http/parser.js +29 -11
- package/dist/nodefony/src/context/http/urlFastPath.js +80 -1
- package/dist/nodefony/src/context/http/webResponse.js +56 -0
- package/dist/nodefony/src/context/http2/Request.js +1 -1
- package/dist/nodefony/src/context/http2/Response.js +55 -12
- package/dist/nodefony/src/context/requestTrace.js +6 -2
- package/dist/nodefony/src/context/rpcOutcome.js +20 -0
- package/dist/nodefony/src/context/transport.js +20 -1
- package/dist/nodefony/src/context/websocket/Response.js +15 -3
- package/dist/nodefony/src/context/websocket/WebsocketContext.js +86 -18
- package/dist/nodefony/src/context/websocket/websocketUrl.js +7 -0
- package/dist/nodefony/src/context/websocket/wsBackpressure.js +15 -15
- package/dist/nodefony/src/context/websocket/wsFrameRate.js +71 -0
- package/dist/nodefony/src/context/websocket/wsLogContent.js +55 -17
- package/dist/nodefony/src/cookies/cookie.js +57 -14
- package/dist/nodefony/src/errors/httpError.js +58 -25
- package/dist/nodefony/src/grpc/cors.js +59 -0
- package/dist/nodefony/src/grpc/limits.js +16 -0
- package/dist/nodefony/src/grpc/refusal.js +271 -0
- package/dist/nodefony/src/profiler/Profiler.js +14 -1
- package/dist/nodefony/src/profiler/aggregate.js +2 -2
- package/dist/nodefony/src/proxy/forward.js +109 -9
- package/dist/nodefony/src/proxy/generateProxyConfig.js +97 -17
- package/dist/nodefony/src/proxy/rules.js +29 -14
- package/dist/nodefony/src/servers/http2Goaway.js +76 -0
- package/dist/nodefony/src/servers/http2Limits.js +41 -15
- package/dist/nodefony/src/servers/http2StreamGrace.js +100 -0
- package/dist/nodefony/src/servers/receiveDeadline.js +177 -0
- package/dist/nodefony/src/servers/upgradeDispatch.js +62 -4
- package/dist/types/index.d.ts +11 -2
- package/dist/types/nodefony/config/config.d.ts +14 -0
- package/dist/types/nodefony/grpc/GrpcCall.d.ts +142 -0
- package/dist/types/nodefony/grpc/GrpcEndpoint.d.ts +98 -0
- package/dist/types/nodefony/grpc/index.d.ts +15 -0
- package/dist/types/nodefony/interfaces/IContext.d.ts +9 -0
- package/dist/types/nodefony/interfaces/IErrorRenderer.d.ts +14 -0
- package/dist/types/nodefony/interfaces/IRequest.d.ts +2 -1
- package/dist/types/nodefony/interfaces/IRequestTrace.d.ts +10 -0
- package/dist/types/nodefony/interfaces/IRouting.d.ts +19 -0
- package/dist/types/nodefony/interfaces/IRpcCall.d.ts +83 -0
- package/dist/types/nodefony/interfaces/ISecurity.d.ts +27 -2
- package/dist/types/nodefony/interfaces/IUpload.d.ts +51 -4
- package/dist/types/nodefony/interfaces/index.d.ts +2 -1
- package/dist/types/nodefony/service/ProfilerAdminApi.d.ts +2 -1
- package/dist/types/nodefony/service/audit-logger.d.ts +33 -3
- package/dist/types/nodefony/service/error-renderer.d.ts +27 -5
- package/dist/types/nodefony/service/http-kernel.d.ts +36 -3
- package/dist/types/nodefony/service/request-logger.d.ts +10 -0
- package/dist/types/nodefony/service/servers/clientError.d.ts +3 -2
- package/dist/types/nodefony/service/servers/serverShutdown.d.ts +7 -5
- package/dist/types/nodefony/src/assets/prebuiltUi.d.ts +9 -4
- package/dist/types/nodefony/src/context/Context.d.ts +9 -1
- package/dist/types/nodefony/src/context/http/ByteStream.d.ts +109 -0
- package/dist/types/nodefony/src/context/http/HttpContext.d.ts +99 -3
- package/dist/types/nodefony/src/context/http/Request.d.ts +46 -9
- package/dist/types/nodefony/src/context/http/Response.d.ts +188 -8
- package/dist/types/nodefony/src/context/http/SseStream.d.ts +33 -8
- package/dist/types/nodefony/src/context/http/StreamLifecycle.d.ts +106 -0
- package/dist/types/nodefony/src/context/http/parser.d.ts +17 -3
- package/dist/types/nodefony/src/context/http/urlFastPath.d.ts +40 -0
- package/dist/types/nodefony/src/context/http/webResponse.d.ts +31 -0
- package/dist/types/nodefony/src/context/http2/Response.d.ts +40 -5
- package/dist/types/nodefony/src/context/requestTrace.d.ts +3 -1
- package/dist/types/nodefony/src/context/rpcOutcome.d.ts +11 -0
- package/dist/types/nodefony/src/context/transport.d.ts +17 -0
- package/dist/types/nodefony/src/context/websocket/Response.d.ts +6 -1
- package/dist/types/nodefony/src/context/websocket/WebsocketContext.d.ts +48 -0
- package/dist/types/nodefony/src/context/websocket/websocketUrl.d.ts +4 -0
- package/dist/types/nodefony/src/context/websocket/wsBackpressure.d.ts +12 -2
- package/dist/types/nodefony/src/context/websocket/wsFrameRate.d.ts +69 -0
- package/dist/types/nodefony/src/context/websocket/wsLogContent.d.ts +16 -8
- package/dist/types/nodefony/src/cookies/cookie.d.ts +20 -2
- package/dist/types/nodefony/src/errors/httpError.d.ts +29 -4
- package/dist/types/nodefony/src/grpc/cors.d.ts +32 -0
- package/dist/types/nodefony/src/grpc/limits.d.ts +14 -0
- package/dist/types/nodefony/src/grpc/refusal.d.ts +136 -0
- package/dist/types/nodefony/src/profiler/Profiler.d.ts +11 -1
- package/dist/types/nodefony/src/proxy/forward.d.ts +37 -2
- package/dist/types/nodefony/src/proxy/generateProxyConfig.d.ts +15 -2
- package/dist/types/nodefony/src/proxy/rules.d.ts +20 -0
- package/dist/types/nodefony/src/servers/http2Goaway.d.ts +41 -0
- package/dist/types/nodefony/src/servers/http2Limits.d.ts +27 -14
- package/dist/types/nodefony/src/servers/http2StreamGrace.d.ts +34 -0
- package/dist/types/nodefony/src/servers/receiveDeadline.d.ts +77 -0
- package/dist/types/nodefony/src/servers/upgradeDispatch.d.ts +41 -1
- package/docs/byte-stream.md +406 -0
- package/docs/cookies.md +13 -3
- package/docs/diagnostics-channel.md +45 -1
- package/docs/index.md +8 -0
- package/docs/reverse-proxy.md +15 -3
- package/docs/servers.md +67 -43
- package/docs/session.md +3 -3
- package/docs/sse.md +27 -20
- package/docs/upload.md +43 -17
- package/package.json +38 -18
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import HttpError from "../../errors/httpError.js";
|
|
2
|
-
import { hasForwardingHeaders, resolveForwarded } from "../forwarded.js";
|
|
3
1
|
import { hostnameOf } from "../domainMatcher.js";
|
|
4
2
|
import { Parser, ParserJson, ParserQs, ParserRaw, ParserXml, acceptParser } from "./parser.js";
|
|
5
|
-
import { isCanonicalAuthority, splitTarget } from "./urlFastPath.js";
|
|
3
|
+
import { isCanonicalAuthority, splitAbsoluteForm, splitTarget } from "./urlFastPath.js";
|
|
4
|
+
import HttpError from "../../errors/httpError.js";
|
|
5
|
+
import { hasForwardingHeaders, resolveForwarded } from "../forwarded.js";
|
|
6
6
|
import { RequestContext, useConfig } from "nodefony";
|
|
7
7
|
import { createHash, randomUUID } from "node:crypto";
|
|
8
8
|
import { URL } from "node:url";
|
|
@@ -23,6 +23,18 @@ const reg = /(.*)[[][\]]$/u;
|
|
|
23
23
|
const unlinkQuiet = (p) => fsp.unlink(p).catch(() => void 0);
|
|
24
24
|
var BodyHandled = class {};
|
|
25
25
|
const BODY_DONE = new BodyHandled();
|
|
26
|
+
/**
|
|
27
|
+
* Une réception multipart EN COURS, interruptible de l'extérieur : `fail` rompt
|
|
28
|
+
* la lecture comme le ferait un dépassement de limite (temporaires nettoyés).
|
|
29
|
+
* Posée dans `request.parser` le temps de la lecture seulement — l'allocation
|
|
30
|
+
* est réservée au multipart, déjà lourd.
|
|
31
|
+
*/
|
|
32
|
+
var MultipartReception = class {
|
|
33
|
+
fail;
|
|
34
|
+
constructor(fail) {
|
|
35
|
+
this.fail = fail;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
26
38
|
const CHARSET_ALIASES = {
|
|
27
39
|
"utf-8": "utf8",
|
|
28
40
|
utf8: "utf8",
|
|
@@ -128,6 +140,9 @@ var HttpRequest = class {
|
|
|
128
140
|
* temporaire — lus par `@UploadedFile()` / `@UploadedFiles()`. Les champs
|
|
129
141
|
* texte du même corps sont dans {@link body}.
|
|
130
142
|
*
|
|
143
|
+
* Ces temporaires sont EFFACÉS à la fin de la requête : pour garder un
|
|
144
|
+
* fichier, l'action le déplace (`moveAsync`) avant de répondre.
|
|
145
|
+
*
|
|
131
146
|
* Lecture seule : une requête sans upload rend un vide partagé et gelé,
|
|
132
147
|
* aucune allocation.
|
|
133
148
|
*/
|
|
@@ -271,6 +286,25 @@ var HttpRequest = class {
|
|
|
271
286
|
}
|
|
272
287
|
}
|
|
273
288
|
/**
|
|
289
|
+
* Lit le plafond du corps et les limites d'envoi tels que les voit CETTE
|
|
290
|
+
* requête : la configuration http, surchargée par le calque que la requête a
|
|
291
|
+
* pu poser avant la lecture du corps (`overlayConfig`, #494), puis par les
|
|
292
|
+
* bornes que la route déclare pour elle-même (option de route `upload`). La
|
|
293
|
+
* route est déjà résolue à ce moment : une route sans bornes propres
|
|
294
|
+
* n'alloue rien. Hors pipeline (aucun scope ouvert), la configuration du
|
|
295
|
+
* module telle quelle.
|
|
296
|
+
*/
|
|
297
|
+
readBodyLimits() {
|
|
298
|
+
const options = RequestContext.getScope() !== void 0 ? useConfig("@nodefony/http") : this.context.httpKernel?.module.options;
|
|
299
|
+
const base = options?.upload ?? {};
|
|
300
|
+
const route = this.context.resolver?.route?.upload;
|
|
301
|
+
this.uploadOption = route ? {
|
|
302
|
+
...base,
|
|
303
|
+
...route
|
|
304
|
+
} : base;
|
|
305
|
+
this.maxBodySize = options?.maxBodySize ?? 0;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
274
308
|
* B1 — Pré-contrôle de taille du corps via l'en-tête `Content-Length` :
|
|
275
309
|
* rejette en 413 (RFC 9110 §15.5.14 « Content Too Large ») AVANT toute lecture
|
|
276
310
|
* quand le client annonce une taille supérieure à `maxBodySize`. Rideau de
|
|
@@ -279,17 +313,6 @@ var HttpRequest = class {
|
|
|
279
313
|
*
|
|
280
314
|
* @throws {HttpError} 413 si `Content-Length` dépasse `maxBodySize`.
|
|
281
315
|
*/
|
|
282
|
-
/**
|
|
283
|
-
* Lit le plafond du corps et les limites d'envoi tels que les voit CETTE
|
|
284
|
-
* requête : la configuration http, surchargée par le calque que la requête a
|
|
285
|
-
* pu poser avant la lecture du corps (`overlayConfig`, #494). Hors pipeline
|
|
286
|
-
* (aucun scope ouvert), la configuration du module telle quelle.
|
|
287
|
-
*/
|
|
288
|
-
readBodyLimits() {
|
|
289
|
-
const options = RequestContext.getScope() !== void 0 ? useConfig("@nodefony/http") : this.context.httpKernel?.module.options;
|
|
290
|
-
this.uploadOption = options?.upload ?? {};
|
|
291
|
-
this.maxBodySize = options?.maxBodySize ?? 0;
|
|
292
|
-
}
|
|
293
316
|
enforceBodyLimit() {
|
|
294
317
|
const max = this.maxBodySize;
|
|
295
318
|
if (max <= 0) return;
|
|
@@ -366,6 +389,7 @@ var HttpRequest = class {
|
|
|
366
389
|
return this.parser;
|
|
367
390
|
}
|
|
368
391
|
const { fields, files } = await this.streamMultipart(bb);
|
|
392
|
+
this.parser = null;
|
|
369
393
|
this.body = fields;
|
|
370
394
|
for (const pf of files) await this.createFileUpload(pf.field, pf.file);
|
|
371
395
|
this.context.requestEnded = true;
|
|
@@ -385,18 +409,33 @@ var HttpRequest = class {
|
|
|
385
409
|
return new Promise((resolve, reject) => {
|
|
386
410
|
const fields = {};
|
|
387
411
|
const files = [];
|
|
412
|
+
let order = 0;
|
|
388
413
|
const pending = [];
|
|
389
414
|
const tempPaths = [];
|
|
390
415
|
const openStreams = /* @__PURE__ */ new Set();
|
|
391
416
|
let totalBytes = 0;
|
|
392
417
|
let aborted = false;
|
|
418
|
+
let received = false;
|
|
393
419
|
const abort = (err) => {
|
|
394
420
|
if (aborted) return;
|
|
395
421
|
aborted = true;
|
|
396
422
|
this.request.unpipe(bb);
|
|
397
423
|
this.request.resume();
|
|
398
|
-
|
|
399
|
-
|
|
424
|
+
const purge = () => {
|
|
425
|
+
Promise.all(tempPaths.map(unlinkQuiet)).finally(() => reject(err));
|
|
426
|
+
};
|
|
427
|
+
let closing = openStreams.size;
|
|
428
|
+
if (closing === 0) {
|
|
429
|
+
purge();
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
for (const ws of openStreams) {
|
|
433
|
+
ws.once("close", () => {
|
|
434
|
+
closing -= 1;
|
|
435
|
+
if (closing === 0) purge();
|
|
436
|
+
});
|
|
437
|
+
ws.destroy();
|
|
438
|
+
}
|
|
400
439
|
};
|
|
401
440
|
bb.on("field", (name, value) => {
|
|
402
441
|
if (aborted) return;
|
|
@@ -407,6 +446,8 @@ var HttpRequest = class {
|
|
|
407
446
|
stream.resume();
|
|
408
447
|
return;
|
|
409
448
|
}
|
|
449
|
+
const slot = order;
|
|
450
|
+
order += 1;
|
|
410
451
|
const field = reg.exec(fieldname)?.[1] ?? fieldname;
|
|
411
452
|
const ext = filename ? path.extname(filename) : "";
|
|
412
453
|
const newFilename = `${randomUUID()}${ext}`;
|
|
@@ -431,7 +472,7 @@ var HttpRequest = class {
|
|
|
431
472
|
ws.on("close", () => {
|
|
432
473
|
openStreams.delete(ws);
|
|
433
474
|
if (aborted) return res();
|
|
434
|
-
files
|
|
475
|
+
files[slot] = {
|
|
435
476
|
field,
|
|
436
477
|
file: {
|
|
437
478
|
filepath,
|
|
@@ -443,7 +484,7 @@ var HttpRequest = class {
|
|
|
443
484
|
hashAlgorithm: algo,
|
|
444
485
|
hash: hasher ? hasher.digest("hex") : null
|
|
445
486
|
}
|
|
446
|
-
}
|
|
487
|
+
};
|
|
447
488
|
res();
|
|
448
489
|
});
|
|
449
490
|
});
|
|
@@ -455,6 +496,7 @@ var HttpRequest = class {
|
|
|
455
496
|
bb.on("partsLimit", () => abort(new HttpError("too many parts", 413, this.context)));
|
|
456
497
|
bb.on("error", (e) => abort(e instanceof Error ? e : new Error(String(e))));
|
|
457
498
|
bb.on("finish", () => {
|
|
499
|
+
received = true;
|
|
458
500
|
if (aborted) return;
|
|
459
501
|
Promise.all(pending).then(() => {
|
|
460
502
|
if (!aborted) resolve({
|
|
@@ -463,10 +505,32 @@ var HttpRequest = class {
|
|
|
463
505
|
});
|
|
464
506
|
}).catch(abort);
|
|
465
507
|
});
|
|
508
|
+
this.parser = new MultipartReception((error) => {
|
|
509
|
+
if (aborted || received) return false;
|
|
510
|
+
abort(error);
|
|
511
|
+
return true;
|
|
512
|
+
});
|
|
466
513
|
this.request.pipe(bb);
|
|
467
514
|
});
|
|
468
515
|
}
|
|
469
516
|
/**
|
|
517
|
+
* Interrompt la réception du corps en cours : la promesse de `initialize()`
|
|
518
|
+
* rejette avec `error`, rendue par le chemin d'erreur habituel — comme un
|
|
519
|
+
* corps qui dépasse sa limite (413).
|
|
520
|
+
*
|
|
521
|
+
* Sert le délai de réception HTTP/2 (`requestTimeout`), que `node:http2` ne
|
|
522
|
+
* borne pas. Sans effet hors réception : corps déjà reçu, lu en flux par
|
|
523
|
+
* l'action (`bodyStream`), ou méthode sans corps.
|
|
524
|
+
*
|
|
525
|
+
* @param error - la cause rendue au client (408 au délai dépassé)
|
|
526
|
+
* @returns vrai si une réception en cours a été interrompue
|
|
527
|
+
*/
|
|
528
|
+
abortBody(error) {
|
|
529
|
+
const parser = this.parser;
|
|
530
|
+
if (parser instanceof Parser || parser instanceof MultipartReception) return parser.fail(error);
|
|
531
|
+
return false;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
470
534
|
* Accumule un champ texte multipart. `foo[]` (ou répétition de `foo`) →
|
|
471
535
|
* tableau ; sinon valeur scalaire. (Anciennement délégué à formidable.)
|
|
472
536
|
*/
|
|
@@ -499,9 +563,25 @@ var HttpRequest = class {
|
|
|
499
563
|
}
|
|
500
564
|
async createFileUpload(name, file) {
|
|
501
565
|
const fileUpload = await this.context.uploadService?.createUploadFile(file, name);
|
|
502
|
-
if (fileUpload)
|
|
566
|
+
if (fileUpload) {
|
|
567
|
+
if (this.#uploads === null) {
|
|
568
|
+
this.#uploads = [];
|
|
569
|
+
this.context.onAfterResponse(() => this.#purgeUploads());
|
|
570
|
+
}
|
|
571
|
+
this.#uploads.push(fileUpload);
|
|
572
|
+
}
|
|
503
573
|
return fileUpload;
|
|
504
574
|
}
|
|
575
|
+
/**
|
|
576
|
+
* Efface, une fois la requête terminée (réponse envoyée ou client parti),
|
|
577
|
+
* les temporaires que l'action n'a pas déplacés — la règle de PHP. Un
|
|
578
|
+
* fichier déplacé (`move`/`moveAsync`) n'est plus à son chemin temporaire :
|
|
579
|
+
* l'effacement n'y trouve rien, et l'erreur est ignorée.
|
|
580
|
+
*/
|
|
581
|
+
#purgeUploads() {
|
|
582
|
+
const uploads = this.#uploads ?? NO_FILES;
|
|
583
|
+
return Promise.all(uploads.map((upload) => unlinkQuiet(upload.parsedFile.filepath))).then(() => void 0);
|
|
584
|
+
}
|
|
505
585
|
getMethod() {
|
|
506
586
|
return this.request.method;
|
|
507
587
|
}
|
|
@@ -546,8 +626,14 @@ var HttpRequest = class {
|
|
|
546
626
|
host = this.getHost();
|
|
547
627
|
return host === this.#rawHostSource ? this.#rawHostname : hostnameOf(host);
|
|
548
628
|
}
|
|
629
|
+
/**
|
|
630
|
+
* L'autorité de la requête : celle de la cible en forme absolue, sinon
|
|
631
|
+
* l'en-tête `Host` (RFC 9112 §3.2.2 — le serveur DOIT alors ignorer `Host`).
|
|
632
|
+
* HTTP/2 lit `:authority` (override).
|
|
633
|
+
*/
|
|
549
634
|
getHost() {
|
|
550
|
-
|
|
635
|
+
const absolute = splitAbsoluteForm(this.request.url);
|
|
636
|
+
return absolute === null ? this.request.headers.host : absolute.authority;
|
|
551
637
|
}
|
|
552
638
|
getRemoteAddress() {
|
|
553
639
|
if (this.forwarded) return this.forwarded.clientIp;
|
|
@@ -556,10 +642,13 @@ var HttpRequest = class {
|
|
|
556
642
|
/**
|
|
557
643
|
* Request-target brut (origin-form) tel que reçu du transport — SOURCE
|
|
558
644
|
* UNIQUE partagée par la concaténation de {@link getFullUrl} et la découpe
|
|
559
|
-
* fast-path du ctor.
|
|
645
|
+
* fast-path du ctor. Une cible en forme absolue est ramenée à sa forme
|
|
646
|
+
* origine, son autorité passant par {@link getHost}. HTTP/2 lit le
|
|
647
|
+
* pseudo-header `:path` (override).
|
|
560
648
|
*/
|
|
561
649
|
getRawTarget() {
|
|
562
|
-
|
|
650
|
+
const target = this.request.url;
|
|
651
|
+
return splitAbsoluteForm(target)?.target ?? target;
|
|
563
652
|
}
|
|
564
653
|
/**
|
|
565
654
|
* Scheme effectif côté client : `Forwarded`/`X-Forwarded-*` résolu de façon
|