@wooksjs/event-http 0.7.19 → 0.7.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +77 -14
- package/dist/index.d.ts +53 -2
- package/dist/index.mjs +77 -15
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -876,6 +876,21 @@ var HttpResponse = class {
|
|
|
876
876
|
this._hasCookies = true;
|
|
877
877
|
return this;
|
|
878
878
|
}
|
|
879
|
+
/**
|
|
880
|
+
* Renders all buffered cookies (named via `setCookie()`, then raw via `setCookieRaw()`)
|
|
881
|
+
* as `Set-Cookie` header strings, without responding.
|
|
882
|
+
*
|
|
883
|
+
* Non-destructive: the buffers stay intact, so a later `send()` still emits the same
|
|
884
|
+
* cookies — callers that drain cookies onto the wire themselves should not also send
|
|
885
|
+
* through this wrapper. Cookies placed directly into headers (via `setHeader('set-cookie', …)`
|
|
886
|
+
* or default headers) are not included.
|
|
887
|
+
*/
|
|
888
|
+
getSetCookieStrings() {
|
|
889
|
+
const rendered = [];
|
|
890
|
+
for (const [name, data] of Object.entries(this._cookies)) if (data) rendered.push(renderCookie(name, data));
|
|
891
|
+
rendered.push(...this._rawCookies);
|
|
892
|
+
return rendered;
|
|
893
|
+
}
|
|
879
894
|
/** Sets the `Cache-Control` header from a directive object (chainable). */
|
|
880
895
|
setCacheControl(data) {
|
|
881
896
|
this._headers["cache-control"] = renderCacheControl(data);
|
|
@@ -927,9 +942,7 @@ var HttpResponse = class {
|
|
|
927
942
|
}
|
|
928
943
|
if (hasFetchResponse && body instanceof globalThis.Response) {
|
|
929
944
|
this._status = this._status || body.status;
|
|
930
|
-
|
|
931
|
-
if (!this._headers[k]) this._headers[k] = v;
|
|
932
|
-
});
|
|
945
|
+
this.mergeFetchResponseHeaders(body);
|
|
933
946
|
return new globalThis.Response(method === "HEAD" ? null : body.body, {
|
|
934
947
|
status: this._status,
|
|
935
948
|
headers: this._buildWebHeaders()
|
|
@@ -956,6 +969,21 @@ var HttpResponse = class {
|
|
|
956
969
|
_buildWebHeaders() {
|
|
957
970
|
return recordToWebHeaders(this._headers);
|
|
958
971
|
}
|
|
972
|
+
/**
|
|
973
|
+
* Merges headers from a handler-returned fetch `Response` into the buffered headers.
|
|
974
|
+
* Explicitly buffered headers win. `set-cookie` is appended in array form so multiple
|
|
975
|
+
* cookies survive (`Headers` iteration would otherwise keep only the first).
|
|
976
|
+
*/
|
|
977
|
+
mergeFetchResponseHeaders(fetchResponse) {
|
|
978
|
+
fetchResponse.headers.forEach((value, key) => {
|
|
979
|
+
if (key !== "set-cookie" && !this._headers[key]) this._headers[key] = value;
|
|
980
|
+
});
|
|
981
|
+
const setCookies = typeof fetchResponse.headers.getSetCookie === "function" ? fetchResponse.headers.getSetCookie() : [];
|
|
982
|
+
if (setCookies.length > 0) {
|
|
983
|
+
const existing = this._headers["set-cookie"];
|
|
984
|
+
this._headers["set-cookie"] = existing ? [...Array.isArray(existing) ? existing : [existing], ...setCookies] : setCookies;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
959
987
|
renderBody() {
|
|
960
988
|
const body = this._body;
|
|
961
989
|
if (body === void 0 || body === null) return "";
|
|
@@ -1013,10 +1041,7 @@ var HttpResponse = class {
|
|
|
1013
1041
|
}
|
|
1014
1042
|
finalizeCookies() {
|
|
1015
1043
|
if (!this._hasCookies) return;
|
|
1016
|
-
const
|
|
1017
|
-
const rendered = [];
|
|
1018
|
-
for (const [name, data] of entries) if (data) rendered.push(renderCookie(name, data));
|
|
1019
|
-
if (this._rawCookies.length > 0) rendered.push(...this._rawCookies);
|
|
1044
|
+
const rendered = this.getSetCookieStrings();
|
|
1020
1045
|
if (rendered.length > 0) {
|
|
1021
1046
|
const existing = this._headers["set-cookie"];
|
|
1022
1047
|
if (existing) this._headers["set-cookie"] = [...Array.isArray(existing) ? existing : [existing], ...rendered];
|
|
@@ -1059,10 +1084,7 @@ var HttpResponse = class {
|
|
|
1059
1084
|
}
|
|
1060
1085
|
async sendFetchResponse(fetchResponse, method) {
|
|
1061
1086
|
this._status = this._status || fetchResponse.status;
|
|
1062
|
-
|
|
1063
|
-
if (fetchContentLength) this._headers["content-length"] = fetchContentLength;
|
|
1064
|
-
const fetchContentType = fetchResponse.headers.get("content-type");
|
|
1065
|
-
if (fetchContentType) this._headers["content-type"] = fetchContentType;
|
|
1087
|
+
this.mergeFetchResponseHeaders(fetchResponse);
|
|
1066
1088
|
this._res.writeHead(this._status, this._headers);
|
|
1067
1089
|
if (method === "HEAD") {
|
|
1068
1090
|
this._res.end();
|
|
@@ -1457,7 +1479,7 @@ function escapeHtml(value) {
|
|
|
1457
1479
|
//#endregion
|
|
1458
1480
|
//#region packages/event-http/src/response/wooks-http-response.ts
|
|
1459
1481
|
let framework = {
|
|
1460
|
-
version: "0.7.
|
|
1482
|
+
version: "0.7.20",
|
|
1461
1483
|
poweredBy: "wooksjs",
|
|
1462
1484
|
link: "https://wooks.moost.org/",
|
|
1463
1485
|
image: "https://wooks.moost.org/wooks-full-logo.svg"
|
|
@@ -1528,13 +1550,22 @@ function renderErrorText(data) {
|
|
|
1528
1550
|
|
|
1529
1551
|
//#endregion
|
|
1530
1552
|
//#region packages/event-http/src/http-adapter.ts
|
|
1531
|
-
|
|
1553
|
+
/**
|
|
1554
|
+
* Identity headers forwarded from the calling HTTP context during programmatic `fetch()`
|
|
1555
|
+
* when no `forwardHeaders` option is configured.
|
|
1556
|
+
*
|
|
1557
|
+
* The `forwardHeaders` option REPLACES this list. To extend it instead, spread the constant:
|
|
1558
|
+
* ```ts
|
|
1559
|
+
* createHttpApp({ forwardHeaders: [...DEFAULT_FORWARD_HEADERS, 'cloudfront-viewer-address'] })
|
|
1560
|
+
* ```
|
|
1561
|
+
*/
|
|
1562
|
+
const DEFAULT_FORWARD_HEADERS = Object.freeze([
|
|
1532
1563
|
"authorization",
|
|
1533
1564
|
"cookie",
|
|
1534
1565
|
"accept-language",
|
|
1535
1566
|
"x-forwarded-for",
|
|
1536
1567
|
"x-request-id"
|
|
1537
|
-
];
|
|
1568
|
+
]);
|
|
1538
1569
|
/** HTTP adapter for Wooks that provides route registration, server lifecycle, and request handling. */
|
|
1539
1570
|
var WooksHttp = class extends wooks.WooksAdapterBase {
|
|
1540
1571
|
constructor(opts, wooks$1) {
|
|
@@ -1902,6 +1933,37 @@ var WooksHttp = class extends wooks.WooksAdapterBase {
|
|
|
1902
1933
|
const req = input instanceof Request ? input : new Request(input, init);
|
|
1903
1934
|
return this.fetch(req);
|
|
1904
1935
|
}
|
|
1936
|
+
/**
|
|
1937
|
+
* Runs `fn` inside an HTTP event context seeded from a real `(req, res)` pair,
|
|
1938
|
+
* WITHOUT route dispatch. Composables that read request state (`useRequest`,
|
|
1939
|
+
* `useHeaders`, `useCookies`, `useAuthorization`) work; route-scoped state is empty.
|
|
1940
|
+
* Nested `fetch()` calls made during `fn` see this context as their caller,
|
|
1941
|
+
* so `forwardHeaders` and parent `Set-Cookie` propagation apply.
|
|
1942
|
+
*
|
|
1943
|
+
* Never writes to `res` — the caller owns the wire. The response wrapper is
|
|
1944
|
+
* created in capture mode, so even a stray `response.send()` inside `fn` only
|
|
1945
|
+
* finalizes state without touching the socket. Buffered response state
|
|
1946
|
+
* (e.g. `Set-Cookie` collected from nested fetches) can be applied by the
|
|
1947
|
+
* caller via the returned wrapper:
|
|
1948
|
+
* ```ts
|
|
1949
|
+
* const { result: html, response } = await http.withHttpContext(req, res, () => render(url))
|
|
1950
|
+
* for (const cookie of response.getSetCookieStrings()) {
|
|
1951
|
+
* res.appendHeader('Set-Cookie', cookie)
|
|
1952
|
+
* }
|
|
1953
|
+
* ```
|
|
1954
|
+
*/
|
|
1955
|
+
async withHttpContext(req, res, fn) {
|
|
1956
|
+
const ctxOptions = this.eventContextOptions;
|
|
1957
|
+
const response = new this.ResponseClass(res, req, ctxOptions.logger, this.opts?.defaultHeaders, true);
|
|
1958
|
+
return {
|
|
1959
|
+
result: await createHttpContext(ctxOptions, {
|
|
1960
|
+
req,
|
|
1961
|
+
response,
|
|
1962
|
+
requestLimits: this.opts?.requestLimits
|
|
1963
|
+
}, fn),
|
|
1964
|
+
response
|
|
1965
|
+
};
|
|
1966
|
+
}
|
|
1905
1967
|
};
|
|
1906
1968
|
var NoopSocket = class extends stream.Duplex {
|
|
1907
1969
|
constructor(..._args) {
|
|
@@ -2039,6 +2101,7 @@ function prepareTestHttpContext(options) {
|
|
|
2039
2101
|
}
|
|
2040
2102
|
|
|
2041
2103
|
//#endregion
|
|
2104
|
+
exports.DEFAULT_FORWARD_HEADERS = DEFAULT_FORWARD_HEADERS;
|
|
2042
2105
|
exports.DEFAULT_LIMITS = DEFAULT_LIMITS;
|
|
2043
2106
|
exports.EHttpStatusCode = EHttpStatusCode;
|
|
2044
2107
|
exports.HttpError = HttpError;
|
package/dist/index.d.ts
CHANGED
|
@@ -395,6 +395,16 @@ declare class HttpResponse {
|
|
|
395
395
|
clearCookies(): this;
|
|
396
396
|
/** Appends a raw `Set-Cookie` header string (chainable). Use when you need full control over the cookie format. */
|
|
397
397
|
setCookieRaw(rawValue: string): this;
|
|
398
|
+
/**
|
|
399
|
+
* Renders all buffered cookies (named via `setCookie()`, then raw via `setCookieRaw()`)
|
|
400
|
+
* as `Set-Cookie` header strings, without responding.
|
|
401
|
+
*
|
|
402
|
+
* Non-destructive: the buffers stay intact, so a later `send()` still emits the same
|
|
403
|
+
* cookies — callers that drain cookies onto the wire themselves should not also send
|
|
404
|
+
* through this wrapper. Cookies placed directly into headers (via `setHeader('set-cookie', …)`
|
|
405
|
+
* or default headers) are not included.
|
|
406
|
+
*/
|
|
407
|
+
getSetCookieStrings(): string[];
|
|
398
408
|
/** Sets the `Cache-Control` header from a directive object (chainable). */
|
|
399
409
|
setCacheControl(data: TCacheControl): this;
|
|
400
410
|
/** Sets the `Age` header in seconds (chainable). Accepts a number or time string (e.g. `'2h 15m'`). */
|
|
@@ -418,6 +428,12 @@ declare class HttpResponse {
|
|
|
418
428
|
*/
|
|
419
429
|
toWebResponse(): Response;
|
|
420
430
|
private _buildWebHeaders;
|
|
431
|
+
/**
|
|
432
|
+
* Merges headers from a handler-returned fetch `Response` into the buffered headers.
|
|
433
|
+
* Explicitly buffered headers win. `set-cookie` is appended in array form so multiple
|
|
434
|
+
* cookies survive (`Headers` iteration would otherwise keep only the first).
|
|
435
|
+
*/
|
|
436
|
+
protected mergeFetchResponseHeaders(fetchResponse: Response): void;
|
|
421
437
|
protected renderBody(): string | Uint8Array;
|
|
422
438
|
protected renderError(data: TWooksErrorBodyExt, _ctx: EventContext): void;
|
|
423
439
|
/** Renders and sends an HTTP error response. Called automatically by the framework when a handler throws an `HttpError`. */
|
|
@@ -509,6 +525,16 @@ declare class WooksHttpResponse extends HttpResponse {
|
|
|
509
525
|
protected renderError(data: TWooksErrorBodyExt, ctx: EventContext): void;
|
|
510
526
|
}
|
|
511
527
|
|
|
528
|
+
/**
|
|
529
|
+
* Identity headers forwarded from the calling HTTP context during programmatic `fetch()`
|
|
530
|
+
* when no `forwardHeaders` option is configured.
|
|
531
|
+
*
|
|
532
|
+
* The `forwardHeaders` option REPLACES this list. To extend it instead, spread the constant:
|
|
533
|
+
* ```ts
|
|
534
|
+
* createHttpApp({ forwardHeaders: [...DEFAULT_FORWARD_HEADERS, 'cloudfront-viewer-address'] })
|
|
535
|
+
* ```
|
|
536
|
+
*/
|
|
537
|
+
declare const DEFAULT_FORWARD_HEADERS: readonly string[];
|
|
512
538
|
/** Configuration options for the WooksHttp adapter. */
|
|
513
539
|
interface TWooksHttpOptions {
|
|
514
540
|
logger?: TConsoleBase;
|
|
@@ -522,8 +548,10 @@ interface TWooksHttpOptions {
|
|
|
522
548
|
defaultHeaders?: Record<string, string | string[]>;
|
|
523
549
|
/**
|
|
524
550
|
* Headers forwarded from the calling HTTP context during programmatic `fetch()`.
|
|
551
|
+
* REPLACES the default list entirely — to add headers while keeping the defaults,
|
|
552
|
+
* spread the exported constant: `[...DEFAULT_FORWARD_HEADERS, 'my-header']`.
|
|
525
553
|
* Set to `false` to disable forwarding entirely.
|
|
526
|
-
* @default ['authorization', 'cookie', 'accept-language', 'x-forwarded-for', 'x-request-id']
|
|
554
|
+
* @default DEFAULT_FORWARD_HEADERS — ['authorization', 'cookie', 'accept-language', 'x-forwarded-for', 'x-request-id']
|
|
527
555
|
*/
|
|
528
556
|
forwardHeaders?: string[] | false;
|
|
529
557
|
}
|
|
@@ -637,6 +665,29 @@ declare class WooksHttp extends WooksAdapterBase {
|
|
|
637
665
|
* @returns A Web Standard Response.
|
|
638
666
|
*/
|
|
639
667
|
request(input: string | URL | Request, init?: RequestInit): Promise<Response | null>;
|
|
668
|
+
/**
|
|
669
|
+
* Runs `fn` inside an HTTP event context seeded from a real `(req, res)` pair,
|
|
670
|
+
* WITHOUT route dispatch. Composables that read request state (`useRequest`,
|
|
671
|
+
* `useHeaders`, `useCookies`, `useAuthorization`) work; route-scoped state is empty.
|
|
672
|
+
* Nested `fetch()` calls made during `fn` see this context as their caller,
|
|
673
|
+
* so `forwardHeaders` and parent `Set-Cookie` propagation apply.
|
|
674
|
+
*
|
|
675
|
+
* Never writes to `res` — the caller owns the wire. The response wrapper is
|
|
676
|
+
* created in capture mode, so even a stray `response.send()` inside `fn` only
|
|
677
|
+
* finalizes state without touching the socket. Buffered response state
|
|
678
|
+
* (e.g. `Set-Cookie` collected from nested fetches) can be applied by the
|
|
679
|
+
* caller via the returned wrapper:
|
|
680
|
+
* ```ts
|
|
681
|
+
* const { result: html, response } = await http.withHttpContext(req, res, () => render(url))
|
|
682
|
+
* for (const cookie of response.getSetCookieStrings()) {
|
|
683
|
+
* res.appendHeader('Set-Cookie', cookie)
|
|
684
|
+
* }
|
|
685
|
+
* ```
|
|
686
|
+
*/
|
|
687
|
+
withHttpContext<T>(req: IncomingMessage, res: ServerResponse, fn: () => T): Promise<{
|
|
688
|
+
result: Awaited<T>;
|
|
689
|
+
response: HttpResponse;
|
|
690
|
+
}>;
|
|
640
691
|
}
|
|
641
692
|
/**
|
|
642
693
|
* Creates a new WooksHttp application instance.
|
|
@@ -713,5 +764,5 @@ interface TTestHttpContext {
|
|
|
713
764
|
*/
|
|
714
765
|
declare function prepareTestHttpContext(options: TTestHttpContext): <T>(cb: (...a: any[]) => T) => T;
|
|
715
766
|
|
|
716
|
-
export { DEFAULT_LIMITS, EHttpStatusCode, HttpError, HttpResponse, WooksHttp, WooksHttpResponse, WooksURLSearchParams, createHttpApp, createHttpContext, httpKind, httpStatusCodes, prepareTestHttpContext, rawBodySlot, recordToWebHeaders, renderCacheControl, securityHeaders, useAccept, useAuthorization, useCookies, useHeaders, useHttpContext, useRequest, useResponse, useUrlParams };
|
|
767
|
+
export { DEFAULT_FORWARD_HEADERS, DEFAULT_LIMITS, EHttpStatusCode, HttpError, HttpResponse, WooksHttp, WooksHttpResponse, WooksURLSearchParams, createHttpApp, createHttpContext, httpKind, httpStatusCodes, prepareTestHttpContext, rawBodySlot, recordToWebHeaders, renderCacheControl, securityHeaders, useAccept, useAuthorization, useCookies, useHeaders, useHttpContext, useRequest, useResponse, useUrlParams };
|
|
717
768
|
export type { KnownAcceptType, KnownAuthType, SecurityHeadersOptions, TCacheControl, TCookieAttributes, TCookieAttributesInput, THttpEventData, TRequestLimits, TSetCookieData, TTestHttpContext, TWooksErrorBody, TWooksErrorBodyExt, TWooksHttpOptions };
|
package/dist/index.mjs
CHANGED
|
@@ -847,6 +847,21 @@ var HttpResponse = class {
|
|
|
847
847
|
this._hasCookies = true;
|
|
848
848
|
return this;
|
|
849
849
|
}
|
|
850
|
+
/**
|
|
851
|
+
* Renders all buffered cookies (named via `setCookie()`, then raw via `setCookieRaw()`)
|
|
852
|
+
* as `Set-Cookie` header strings, without responding.
|
|
853
|
+
*
|
|
854
|
+
* Non-destructive: the buffers stay intact, so a later `send()` still emits the same
|
|
855
|
+
* cookies — callers that drain cookies onto the wire themselves should not also send
|
|
856
|
+
* through this wrapper. Cookies placed directly into headers (via `setHeader('set-cookie', …)`
|
|
857
|
+
* or default headers) are not included.
|
|
858
|
+
*/
|
|
859
|
+
getSetCookieStrings() {
|
|
860
|
+
const rendered = [];
|
|
861
|
+
for (const [name, data] of Object.entries(this._cookies)) if (data) rendered.push(renderCookie(name, data));
|
|
862
|
+
rendered.push(...this._rawCookies);
|
|
863
|
+
return rendered;
|
|
864
|
+
}
|
|
850
865
|
/** Sets the `Cache-Control` header from a directive object (chainable). */
|
|
851
866
|
setCacheControl(data) {
|
|
852
867
|
this._headers["cache-control"] = renderCacheControl(data);
|
|
@@ -898,9 +913,7 @@ var HttpResponse = class {
|
|
|
898
913
|
}
|
|
899
914
|
if (hasFetchResponse && body instanceof globalThis.Response) {
|
|
900
915
|
this._status = this._status || body.status;
|
|
901
|
-
|
|
902
|
-
if (!this._headers[k]) this._headers[k] = v;
|
|
903
|
-
});
|
|
916
|
+
this.mergeFetchResponseHeaders(body);
|
|
904
917
|
return new globalThis.Response(method === "HEAD" ? null : body.body, {
|
|
905
918
|
status: this._status,
|
|
906
919
|
headers: this._buildWebHeaders()
|
|
@@ -927,6 +940,21 @@ var HttpResponse = class {
|
|
|
927
940
|
_buildWebHeaders() {
|
|
928
941
|
return recordToWebHeaders(this._headers);
|
|
929
942
|
}
|
|
943
|
+
/**
|
|
944
|
+
* Merges headers from a handler-returned fetch `Response` into the buffered headers.
|
|
945
|
+
* Explicitly buffered headers win. `set-cookie` is appended in array form so multiple
|
|
946
|
+
* cookies survive (`Headers` iteration would otherwise keep only the first).
|
|
947
|
+
*/
|
|
948
|
+
mergeFetchResponseHeaders(fetchResponse) {
|
|
949
|
+
fetchResponse.headers.forEach((value, key) => {
|
|
950
|
+
if (key !== "set-cookie" && !this._headers[key]) this._headers[key] = value;
|
|
951
|
+
});
|
|
952
|
+
const setCookies = typeof fetchResponse.headers.getSetCookie === "function" ? fetchResponse.headers.getSetCookie() : [];
|
|
953
|
+
if (setCookies.length > 0) {
|
|
954
|
+
const existing = this._headers["set-cookie"];
|
|
955
|
+
this._headers["set-cookie"] = existing ? [...Array.isArray(existing) ? existing : [existing], ...setCookies] : setCookies;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
930
958
|
renderBody() {
|
|
931
959
|
const body = this._body;
|
|
932
960
|
if (body === void 0 || body === null) return "";
|
|
@@ -984,10 +1012,7 @@ var HttpResponse = class {
|
|
|
984
1012
|
}
|
|
985
1013
|
finalizeCookies() {
|
|
986
1014
|
if (!this._hasCookies) return;
|
|
987
|
-
const
|
|
988
|
-
const rendered = [];
|
|
989
|
-
for (const [name, data] of entries) if (data) rendered.push(renderCookie(name, data));
|
|
990
|
-
if (this._rawCookies.length > 0) rendered.push(...this._rawCookies);
|
|
1015
|
+
const rendered = this.getSetCookieStrings();
|
|
991
1016
|
if (rendered.length > 0) {
|
|
992
1017
|
const existing = this._headers["set-cookie"];
|
|
993
1018
|
if (existing) this._headers["set-cookie"] = [...Array.isArray(existing) ? existing : [existing], ...rendered];
|
|
@@ -1030,10 +1055,7 @@ var HttpResponse = class {
|
|
|
1030
1055
|
}
|
|
1031
1056
|
async sendFetchResponse(fetchResponse, method) {
|
|
1032
1057
|
this._status = this._status || fetchResponse.status;
|
|
1033
|
-
|
|
1034
|
-
if (fetchContentLength) this._headers["content-length"] = fetchContentLength;
|
|
1035
|
-
const fetchContentType = fetchResponse.headers.get("content-type");
|
|
1036
|
-
if (fetchContentType) this._headers["content-type"] = fetchContentType;
|
|
1058
|
+
this.mergeFetchResponseHeaders(fetchResponse);
|
|
1037
1059
|
this._res.writeHead(this._status, this._headers);
|
|
1038
1060
|
if (method === "HEAD") {
|
|
1039
1061
|
this._res.end();
|
|
@@ -1428,7 +1450,7 @@ function escapeHtml(value) {
|
|
|
1428
1450
|
//#endregion
|
|
1429
1451
|
//#region packages/event-http/src/response/wooks-http-response.ts
|
|
1430
1452
|
let framework = {
|
|
1431
|
-
version: "0.7.
|
|
1453
|
+
version: "0.7.20",
|
|
1432
1454
|
poweredBy: "wooksjs",
|
|
1433
1455
|
link: "https://wooks.moost.org/",
|
|
1434
1456
|
image: "https://wooks.moost.org/wooks-full-logo.svg"
|
|
@@ -1499,13 +1521,22 @@ function renderErrorText(data) {
|
|
|
1499
1521
|
|
|
1500
1522
|
//#endregion
|
|
1501
1523
|
//#region packages/event-http/src/http-adapter.ts
|
|
1502
|
-
|
|
1524
|
+
/**
|
|
1525
|
+
* Identity headers forwarded from the calling HTTP context during programmatic `fetch()`
|
|
1526
|
+
* when no `forwardHeaders` option is configured.
|
|
1527
|
+
*
|
|
1528
|
+
* The `forwardHeaders` option REPLACES this list. To extend it instead, spread the constant:
|
|
1529
|
+
* ```ts
|
|
1530
|
+
* createHttpApp({ forwardHeaders: [...DEFAULT_FORWARD_HEADERS, 'cloudfront-viewer-address'] })
|
|
1531
|
+
* ```
|
|
1532
|
+
*/
|
|
1533
|
+
const DEFAULT_FORWARD_HEADERS = Object.freeze([
|
|
1503
1534
|
"authorization",
|
|
1504
1535
|
"cookie",
|
|
1505
1536
|
"accept-language",
|
|
1506
1537
|
"x-forwarded-for",
|
|
1507
1538
|
"x-request-id"
|
|
1508
|
-
];
|
|
1539
|
+
]);
|
|
1509
1540
|
/** HTTP adapter for Wooks that provides route registration, server lifecycle, and request handling. */
|
|
1510
1541
|
var WooksHttp = class extends WooksAdapterBase {
|
|
1511
1542
|
constructor(opts, wooks) {
|
|
@@ -1873,6 +1904,37 @@ var WooksHttp = class extends WooksAdapterBase {
|
|
|
1873
1904
|
const req = input instanceof Request ? input : new Request(input, init);
|
|
1874
1905
|
return this.fetch(req);
|
|
1875
1906
|
}
|
|
1907
|
+
/**
|
|
1908
|
+
* Runs `fn` inside an HTTP event context seeded from a real `(req, res)` pair,
|
|
1909
|
+
* WITHOUT route dispatch. Composables that read request state (`useRequest`,
|
|
1910
|
+
* `useHeaders`, `useCookies`, `useAuthorization`) work; route-scoped state is empty.
|
|
1911
|
+
* Nested `fetch()` calls made during `fn` see this context as their caller,
|
|
1912
|
+
* so `forwardHeaders` and parent `Set-Cookie` propagation apply.
|
|
1913
|
+
*
|
|
1914
|
+
* Never writes to `res` — the caller owns the wire. The response wrapper is
|
|
1915
|
+
* created in capture mode, so even a stray `response.send()` inside `fn` only
|
|
1916
|
+
* finalizes state without touching the socket. Buffered response state
|
|
1917
|
+
* (e.g. `Set-Cookie` collected from nested fetches) can be applied by the
|
|
1918
|
+
* caller via the returned wrapper:
|
|
1919
|
+
* ```ts
|
|
1920
|
+
* const { result: html, response } = await http.withHttpContext(req, res, () => render(url))
|
|
1921
|
+
* for (const cookie of response.getSetCookieStrings()) {
|
|
1922
|
+
* res.appendHeader('Set-Cookie', cookie)
|
|
1923
|
+
* }
|
|
1924
|
+
* ```
|
|
1925
|
+
*/
|
|
1926
|
+
async withHttpContext(req, res, fn) {
|
|
1927
|
+
const ctxOptions = this.eventContextOptions;
|
|
1928
|
+
const response = new this.ResponseClass(res, req, ctxOptions.logger, this.opts?.defaultHeaders, true);
|
|
1929
|
+
return {
|
|
1930
|
+
result: await createHttpContext(ctxOptions, {
|
|
1931
|
+
req,
|
|
1932
|
+
response,
|
|
1933
|
+
requestLimits: this.opts?.requestLimits
|
|
1934
|
+
}, fn),
|
|
1935
|
+
response
|
|
1936
|
+
};
|
|
1937
|
+
}
|
|
1876
1938
|
};
|
|
1877
1939
|
var NoopSocket = class extends Duplex {
|
|
1878
1940
|
constructor(..._args) {
|
|
@@ -2010,4 +2072,4 @@ function prepareTestHttpContext(options) {
|
|
|
2010
2072
|
}
|
|
2011
2073
|
|
|
2012
2074
|
//#endregion
|
|
2013
|
-
export { DEFAULT_LIMITS, EHttpStatusCode, HttpError, HttpResponse, WooksHttp, WooksHttpResponse, WooksURLSearchParams, createHttpApp, createHttpContext, httpKind, httpStatusCodes, prepareTestHttpContext, rawBodySlot, recordToWebHeaders, renderCacheControl, securityHeaders, useAccept, useAuthorization, useCookies, useHeaders, useHttpContext, useLogger, useRequest, useResponse, useRouteParams, useUrlParams };
|
|
2075
|
+
export { DEFAULT_FORWARD_HEADERS, DEFAULT_LIMITS, EHttpStatusCode, HttpError, HttpResponse, WooksHttp, WooksHttpResponse, WooksURLSearchParams, createHttpApp, createHttpContext, httpKind, httpStatusCodes, prepareTestHttpContext, rawBodySlot, recordToWebHeaders, renderCacheControl, securityHeaders, useAccept, useAuthorization, useCookies, useHeaders, useHttpContext, useLogger, useRequest, useResponse, useRouteParams, useUrlParams };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wooksjs/event-http",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.21",
|
|
4
4
|
"description": "@wooksjs/event-http",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -42,14 +42,14 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"typescript": "^5.9.3",
|
|
44
44
|
"vitest": "^3.2.4",
|
|
45
|
-
"@wooksjs/event-core": "^0.7.
|
|
46
|
-
"wooks": "^0.7.
|
|
45
|
+
"@wooksjs/event-core": "^0.7.21",
|
|
46
|
+
"wooks": "^0.7.21"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@prostojs/logger": "^0.4.3",
|
|
50
50
|
"@prostojs/router": "^0.3.4",
|
|
51
|
-
"@wooksjs/event-core": "^0.7.
|
|
52
|
-
"wooks": "^0.7.
|
|
51
|
+
"@wooksjs/event-core": "^0.7.21",
|
|
52
|
+
"wooks": "^0.7.21"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "rolldown -c ../../rolldown.config.mjs"
|