@wooksjs/event-http 0.6.4 → 0.6.6
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 +60 -49
- package/dist/index.d.ts +6 -5
- package/dist/index.mjs +60 -49
- package/package.json +6 -7
package/dist/index.cjs
CHANGED
|
@@ -697,7 +697,7 @@ function error_tl_default(ctx) {
|
|
|
697
697
|
//#endregion
|
|
698
698
|
//#region packages/event-http/src/errors/error-renderer.ts
|
|
699
699
|
let framework = {
|
|
700
|
-
version: "0.6.
|
|
700
|
+
version: "0.6.5",
|
|
701
701
|
poweredBy: `wooksjs`,
|
|
702
702
|
link: `https://wooks.moost.org/`,
|
|
703
703
|
image: `https://wooks.moost.org/wooks-full-logo.png`
|
|
@@ -750,14 +750,8 @@ var HttpErrorRenderer = class extends BaseHttpResponseRenderer {
|
|
|
750
750
|
}, null, " ")}` : ""}`;
|
|
751
751
|
}
|
|
752
752
|
renderJson(response) {
|
|
753
|
-
const data = response.body || {};
|
|
754
753
|
response.setContentType("application/json");
|
|
755
|
-
|
|
756
|
-
"statusCode",
|
|
757
|
-
"error",
|
|
758
|
-
"message"
|
|
759
|
-
].includes(key));
|
|
760
|
-
return `{"statusCode":${escapeQuotes(data.statusCode)},"error":"${escapeQuotes(data.error)}","message":"${escapeQuotes(data.message)}"${keys.length > 0 ? `,${keys.map((k) => `"${escapeQuotes(k)}":${JSON.stringify(data[k])}`).join(",")}` : ""}}`;
|
|
754
|
+
return JSON.stringify(response.body || {});
|
|
761
755
|
}
|
|
762
756
|
render(response) {
|
|
763
757
|
const { acceptsJson, acceptsText, acceptsHtml } = useAccept();
|
|
@@ -768,9 +762,6 @@ var HttpErrorRenderer = class extends BaseHttpResponseRenderer {
|
|
|
768
762
|
else return this.renderJson(response);
|
|
769
763
|
}
|
|
770
764
|
};
|
|
771
|
-
function escapeQuotes(s) {
|
|
772
|
-
return (typeof s === "number" ? s : s || "").toString().replace(/"/gu, "\\\"");
|
|
773
|
-
}
|
|
774
765
|
|
|
775
766
|
//#endregion
|
|
776
767
|
//#region packages/event-http/src/errors/http-error.ts
|
|
@@ -1009,6 +1000,15 @@ function useSetHeader(name) {
|
|
|
1009
1000
|
|
|
1010
1001
|
//#endregion
|
|
1011
1002
|
//#region packages/event-http/src/composables/cookies.ts
|
|
1003
|
+
const cookieRegExpCache = /* @__PURE__ */ new Map();
|
|
1004
|
+
function getCookieRegExp(name) {
|
|
1005
|
+
let re = cookieRegExpCache.get(name);
|
|
1006
|
+
if (!re) {
|
|
1007
|
+
re = new RegExp(`(?:^|; )${escapeRegex(name)}=(.*?)(?:;?$|; )`, "i");
|
|
1008
|
+
cookieRegExpCache.set(name, re);
|
|
1009
|
+
}
|
|
1010
|
+
return re;
|
|
1011
|
+
}
|
|
1012
1012
|
/**
|
|
1013
1013
|
* Provides access to parsed request cookies.
|
|
1014
1014
|
* @example
|
|
@@ -1023,7 +1023,7 @@ function useCookies() {
|
|
|
1023
1023
|
const { init } = store("cookies");
|
|
1024
1024
|
const getCookie = (name) => init(name, () => {
|
|
1025
1025
|
if (cookie) {
|
|
1026
|
-
const result =
|
|
1026
|
+
const result = getCookieRegExp(name).exec(cookie);
|
|
1027
1027
|
return result?.[1] ? safeDecodeURIComponent(result[1]) : null;
|
|
1028
1028
|
} else return null;
|
|
1029
1029
|
});
|
|
@@ -1043,7 +1043,9 @@ function useSetCookies() {
|
|
|
1043
1043
|
});
|
|
1044
1044
|
}
|
|
1045
1045
|
function cookies() {
|
|
1046
|
-
|
|
1046
|
+
const entries = cookiesStore.entries();
|
|
1047
|
+
if (entries.length === 0) return [];
|
|
1048
|
+
return entries.filter((a) => !!a[1]).map(([key, value]) => renderCookie(key, value));
|
|
1047
1049
|
}
|
|
1048
1050
|
return {
|
|
1049
1051
|
setCookie,
|
|
@@ -1367,12 +1369,10 @@ var BaseHttpResponse = class {
|
|
|
1367
1369
|
const { cookies, removeCookie } = useSetCookies();
|
|
1368
1370
|
const newCookies = this._headers["set-cookie"] || [];
|
|
1369
1371
|
for (const cookie of newCookies) removeCookie(cookie.slice(0, cookie.indexOf("=")));
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
const setCookie = [...newCookies, ...cookies()];
|
|
1375
|
-
if (setCookie.length > 0) this._headers["set-cookie"] = setCookie;
|
|
1372
|
+
const composableHeaders = headers();
|
|
1373
|
+
for (const key in composableHeaders) if (!(key in this._headers)) this._headers[key] = composableHeaders[key];
|
|
1374
|
+
const renderedCookies = cookies();
|
|
1375
|
+
if (newCookies.length > 0 || renderedCookies.length > 0) this._headers["set-cookie"] = newCookies.length > 0 && renderedCookies.length > 0 ? [...newCookies, ...renderedCookies] : newCookies.length > 0 ? newCookies : renderedCookies;
|
|
1376
1376
|
return this;
|
|
1377
1377
|
}
|
|
1378
1378
|
mergeStatus(renderedBody) {
|
|
@@ -1400,7 +1400,7 @@ var BaseHttpResponse = class {
|
|
|
1400
1400
|
const res = rawResponse();
|
|
1401
1401
|
if (this.body instanceof stream.Readable) {
|
|
1402
1402
|
const stream$1 = this.body;
|
|
1403
|
-
this.mergeStatus(
|
|
1403
|
+
this.mergeStatus(true);
|
|
1404
1404
|
res.writeHead(this.status, { ...this._headers });
|
|
1405
1405
|
rawRequest.once("close", () => {
|
|
1406
1406
|
stream$1.destroy();
|
|
@@ -1422,32 +1422,37 @@ var BaseHttpResponse = class {
|
|
|
1422
1422
|
});
|
|
1423
1423
|
} else if (globalThis.Response && this.body instanceof Response) {
|
|
1424
1424
|
this.mergeFetchStatus(this.body.status);
|
|
1425
|
+
const additionalHeaders = {};
|
|
1426
|
+
const fetchContentLength = this.body.headers.get("content-length");
|
|
1427
|
+
if (fetchContentLength) additionalHeaders["content-length"] = fetchContentLength;
|
|
1428
|
+
const fetchContentType = this.body.headers.get("content-type");
|
|
1429
|
+
if (fetchContentType) additionalHeaders["content-type"] = fetchContentType;
|
|
1430
|
+
res.writeHead(this.status, {
|
|
1431
|
+
...this._headers,
|
|
1432
|
+
...additionalHeaders
|
|
1433
|
+
});
|
|
1425
1434
|
if (method === "HEAD") res.end();
|
|
1426
|
-
else
|
|
1427
|
-
const additionalHeaders = {};
|
|
1428
|
-
if (this.body.headers.get("content-length")) additionalHeaders["content-length"] = this.body.headers.get("content-length");
|
|
1429
|
-
if (this.body.headers.get("content-type")) additionalHeaders["content-type"] = this.body.headers.get("content-type");
|
|
1430
|
-
res.writeHead(this.status, {
|
|
1431
|
-
...additionalHeaders,
|
|
1432
|
-
...this._headers
|
|
1433
|
-
});
|
|
1434
|
-
await respondWithFetch(this.body.body, res);
|
|
1435
|
-
}
|
|
1435
|
+
else await respondWithFetch(this.body.body, res, logger);
|
|
1436
1436
|
} else {
|
|
1437
1437
|
const renderedBody = this.renderer.render(this);
|
|
1438
1438
|
this.mergeStatus(renderedBody);
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1439
|
+
const contentLength = typeof renderedBody === "string" ? Buffer.byteLength(renderedBody) : renderedBody.byteLength;
|
|
1440
|
+
return new Promise((resolve) => {
|
|
1441
|
+
res.writeHead(this.status, {
|
|
1442
|
+
"content-length": contentLength,
|
|
1443
|
+
...this._headers
|
|
1444
|
+
}).end(method === "HEAD" ? "" : renderedBody, resolve);
|
|
1445
|
+
});
|
|
1443
1446
|
}
|
|
1444
1447
|
}
|
|
1445
1448
|
};
|
|
1446
|
-
async function respondWithFetch(fetchBody, res) {
|
|
1449
|
+
async function respondWithFetch(fetchBody, res, logger) {
|
|
1447
1450
|
if (fetchBody) try {
|
|
1448
1451
|
for await (const chunk of fetchBody) res.write(chunk);
|
|
1449
|
-
} catch {
|
|
1450
|
-
|
|
1452
|
+
} catch (error) {
|
|
1453
|
+
logger.error("Error streaming fetch response body", error);
|
|
1454
|
+
}
|
|
1455
|
+
if (!res.writableEnded) res.end();
|
|
1451
1456
|
}
|
|
1452
1457
|
|
|
1453
1458
|
//#endregion
|
|
@@ -1477,10 +1482,12 @@ function createWooksResponder(renderer = new BaseHttpResponseRenderer(), errorRe
|
|
|
1477
1482
|
/** HTTP adapter for Wooks that provides route registration, server lifecycle, and request handling. */
|
|
1478
1483
|
var WooksHttp = class extends wooks.WooksAdapterBase {
|
|
1479
1484
|
logger;
|
|
1485
|
+
_cachedEventOptions;
|
|
1480
1486
|
constructor(opts, wooks$1) {
|
|
1481
1487
|
super(wooks$1, opts?.logger, opts?.router);
|
|
1482
1488
|
this.opts = opts;
|
|
1483
1489
|
this.logger = opts?.logger || this.getLogger(`[96m[wooks-http]`);
|
|
1490
|
+
this._cachedEventOptions = this.mergeEventOptions(opts?.eventOptions);
|
|
1484
1491
|
}
|
|
1485
1492
|
/** Registers a handler for all HTTP methods on the given path. */
|
|
1486
1493
|
all(path, handler) {
|
|
@@ -1568,7 +1575,7 @@ var WooksHttp = class extends wooks.WooksAdapterBase {
|
|
|
1568
1575
|
}
|
|
1569
1576
|
responder = createWooksResponder();
|
|
1570
1577
|
respond(data) {
|
|
1571
|
-
this.responder.respond(data)?.catch((error) => {
|
|
1578
|
+
return this.responder.respond(data)?.catch((error) => {
|
|
1572
1579
|
this.logger.error("Uncaught response exception", error);
|
|
1573
1580
|
});
|
|
1574
1581
|
}
|
|
@@ -1590,20 +1597,23 @@ var WooksHttp = class extends wooks.WooksAdapterBase {
|
|
|
1590
1597
|
req,
|
|
1591
1598
|
res,
|
|
1592
1599
|
requestLimits: this.opts?.requestLimits
|
|
1593
|
-
}, this.
|
|
1600
|
+
}, this._cachedEventOptions);
|
|
1601
|
+
const method = req.method || "";
|
|
1602
|
+
const url$1 = req.url || "";
|
|
1594
1603
|
runInContext(async () => {
|
|
1595
|
-
const
|
|
1596
|
-
|
|
1597
|
-
|
|
1604
|
+
const notFoundHandler = this.opts?.onNotFound;
|
|
1605
|
+
const { handlers } = this.wooks.lookup(method, url$1);
|
|
1606
|
+
if (handlers || notFoundHandler) try {
|
|
1607
|
+
return await this.processHandlers(handlers || [notFoundHandler]);
|
|
1598
1608
|
} catch (error) {
|
|
1599
1609
|
this.logger.error("Internal error, please report", error);
|
|
1600
|
-
this.respond(error);
|
|
1610
|
+
await this.respond(error);
|
|
1601
1611
|
return error;
|
|
1602
1612
|
}
|
|
1603
1613
|
else {
|
|
1604
|
-
this.logger.debug(`404 Not found (${
|
|
1614
|
+
this.logger.debug(`404 Not found (${method})${url$1}`);
|
|
1605
1615
|
const error = new HttpError(404);
|
|
1606
|
-
this.respond(error);
|
|
1616
|
+
await this.respond(error);
|
|
1607
1617
|
return error;
|
|
1608
1618
|
}
|
|
1609
1619
|
});
|
|
@@ -1611,17 +1621,18 @@ var WooksHttp = class extends wooks.WooksAdapterBase {
|
|
|
1611
1621
|
}
|
|
1612
1622
|
async processHandlers(handlers) {
|
|
1613
1623
|
const { store } = useHttpContext();
|
|
1614
|
-
for (
|
|
1615
|
-
const
|
|
1624
|
+
for (let i = 0; i < handlers.length; i++) {
|
|
1625
|
+
const handler = handlers[i];
|
|
1626
|
+
const isLastHandler = i === handlers.length - 1;
|
|
1616
1627
|
try {
|
|
1617
1628
|
const promise = handler();
|
|
1618
1629
|
const result = await promise;
|
|
1619
|
-
this.respond(result);
|
|
1630
|
+
await this.respond(result);
|
|
1620
1631
|
return result;
|
|
1621
1632
|
} catch (error) {
|
|
1622
1633
|
if (error instanceof HttpError) {} else this.logger.error(`Uncaught route handler exception: ${store("event").get("req")?.url || ""}`, error);
|
|
1623
1634
|
if (isLastHandler) {
|
|
1624
|
-
this.respond(error);
|
|
1635
|
+
await this.respond(error);
|
|
1625
1636
|
return error;
|
|
1626
1637
|
}
|
|
1627
1638
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -445,7 +445,7 @@ declare class BaseHttpResponse<BodyType = unknown> {
|
|
|
445
445
|
setHeader(name: string, value: string): this;
|
|
446
446
|
getHeader(name: string): string | string[];
|
|
447
447
|
protected mergeHeaders(): this;
|
|
448
|
-
protected mergeStatus(renderedBody: string | Uint8Array): this;
|
|
448
|
+
protected mergeStatus(renderedBody: string | Uint8Array | boolean): this;
|
|
449
449
|
protected mergeFetchStatus(fetchStatus: number): void;
|
|
450
450
|
protected panic(text: string, logger: TConsoleBase): void;
|
|
451
451
|
respond(): Promise<unknown>;
|
|
@@ -506,7 +506,7 @@ declare class HttpErrorRenderer extends BaseHttpResponseRenderer<TWooksErrorBody
|
|
|
506
506
|
}
|
|
507
507
|
|
|
508
508
|
/** Creates an async event context for an incoming HTTP request/response pair. */
|
|
509
|
-
declare function createHttpContext(data: THttpEventData, options: TEventOptions): <T>(cb: (...a:
|
|
509
|
+
declare function createHttpContext(data: THttpEventData, options: TEventOptions): <T>(cb: (...a: unknown[]) => T) => T;
|
|
510
510
|
/**
|
|
511
511
|
* Wrapper on useEventContext with HTTP event types
|
|
512
512
|
* @returns set of hooks { getCtx, restoreCtx, clearCtx, hookStore, getStore, setStore }
|
|
@@ -531,6 +531,7 @@ interface TWooksHttpOptions {
|
|
|
531
531
|
declare class WooksHttp extends WooksAdapterBase {
|
|
532
532
|
protected opts?: TWooksHttpOptions | undefined;
|
|
533
533
|
protected logger: TConsoleBase;
|
|
534
|
+
protected _cachedEventOptions: TEventOptions;
|
|
534
535
|
constructor(opts?: TWooksHttpOptions | undefined, wooks?: Wooks | WooksAdapterBase);
|
|
535
536
|
/** Registers a handler for all HTTP methods on the given path. */
|
|
536
537
|
all<ResType = unknown, ParamsType = Record<string, string | string[]>>(path: string, handler: TWooksHandler<ResType>): wooks.TProstoRouterPathHandle<ParamsType>;
|
|
@@ -561,8 +562,8 @@ declare class WooksHttp extends WooksAdapterBase {
|
|
|
561
562
|
listen(path: string, backlog?: number, listeningListener?: () => void): Promise<void>;
|
|
562
563
|
listen(path: string, listeningListener?: () => void): Promise<void>;
|
|
563
564
|
listen(options: ListenOptions, listeningListener?: () => void): Promise<void>;
|
|
564
|
-
listen(handle:
|
|
565
|
-
listen(handle:
|
|
565
|
+
listen(handle: unknown, backlog?: number, listeningListener?: () => void): Promise<void>;
|
|
566
|
+
listen(handle: unknown, listeningListener?: () => void): Promise<void>;
|
|
566
567
|
/**
|
|
567
568
|
* Stops the server if it was attached or passed via argument
|
|
568
569
|
* @param server
|
|
@@ -587,7 +588,7 @@ declare class WooksHttp extends WooksAdapterBase {
|
|
|
587
588
|
createResponse: <T = unknown>(data: T) => BaseHttpResponse<T | TWooksErrorBodyExt> | null;
|
|
588
589
|
respond: (data: unknown) => Promise<unknown> | undefined;
|
|
589
590
|
};
|
|
590
|
-
protected respond(data: unknown):
|
|
591
|
+
protected respond(data: unknown): Promise<unknown> | undefined;
|
|
591
592
|
/**
|
|
592
593
|
* Returns server callback function
|
|
593
594
|
* that can be passed to any node server:
|
package/dist/index.mjs
CHANGED
|
@@ -674,7 +674,7 @@ function error_tl_default(ctx) {
|
|
|
674
674
|
//#endregion
|
|
675
675
|
//#region packages/event-http/src/errors/error-renderer.ts
|
|
676
676
|
let framework = {
|
|
677
|
-
version: "0.6.
|
|
677
|
+
version: "0.6.5",
|
|
678
678
|
poweredBy: `wooksjs`,
|
|
679
679
|
link: `https://wooks.moost.org/`,
|
|
680
680
|
image: `https://wooks.moost.org/wooks-full-logo.png`
|
|
@@ -727,14 +727,8 @@ var HttpErrorRenderer = class extends BaseHttpResponseRenderer {
|
|
|
727
727
|
}, null, " ")}` : ""}`;
|
|
728
728
|
}
|
|
729
729
|
renderJson(response) {
|
|
730
|
-
const data = response.body || {};
|
|
731
730
|
response.setContentType("application/json");
|
|
732
|
-
|
|
733
|
-
"statusCode",
|
|
734
|
-
"error",
|
|
735
|
-
"message"
|
|
736
|
-
].includes(key));
|
|
737
|
-
return `{"statusCode":${escapeQuotes(data.statusCode)},"error":"${escapeQuotes(data.error)}","message":"${escapeQuotes(data.message)}"${keys.length > 0 ? `,${keys.map((k) => `"${escapeQuotes(k)}":${JSON.stringify(data[k])}`).join(",")}` : ""}}`;
|
|
731
|
+
return JSON.stringify(response.body || {});
|
|
738
732
|
}
|
|
739
733
|
render(response) {
|
|
740
734
|
const { acceptsJson, acceptsText, acceptsHtml } = useAccept();
|
|
@@ -745,9 +739,6 @@ var HttpErrorRenderer = class extends BaseHttpResponseRenderer {
|
|
|
745
739
|
else return this.renderJson(response);
|
|
746
740
|
}
|
|
747
741
|
};
|
|
748
|
-
function escapeQuotes(s) {
|
|
749
|
-
return (typeof s === "number" ? s : s || "").toString().replace(/"/gu, "\\\"");
|
|
750
|
-
}
|
|
751
742
|
|
|
752
743
|
//#endregion
|
|
753
744
|
//#region packages/event-http/src/errors/http-error.ts
|
|
@@ -986,6 +977,15 @@ function useSetHeader(name) {
|
|
|
986
977
|
|
|
987
978
|
//#endregion
|
|
988
979
|
//#region packages/event-http/src/composables/cookies.ts
|
|
980
|
+
const cookieRegExpCache = /* @__PURE__ */ new Map();
|
|
981
|
+
function getCookieRegExp(name) {
|
|
982
|
+
let re = cookieRegExpCache.get(name);
|
|
983
|
+
if (!re) {
|
|
984
|
+
re = new RegExp(`(?:^|; )${escapeRegex(name)}=(.*?)(?:;?$|; )`, "i");
|
|
985
|
+
cookieRegExpCache.set(name, re);
|
|
986
|
+
}
|
|
987
|
+
return re;
|
|
988
|
+
}
|
|
989
989
|
/**
|
|
990
990
|
* Provides access to parsed request cookies.
|
|
991
991
|
* @example
|
|
@@ -1000,7 +1000,7 @@ function useCookies() {
|
|
|
1000
1000
|
const { init } = store("cookies");
|
|
1001
1001
|
const getCookie = (name) => init(name, () => {
|
|
1002
1002
|
if (cookie) {
|
|
1003
|
-
const result =
|
|
1003
|
+
const result = getCookieRegExp(name).exec(cookie);
|
|
1004
1004
|
return result?.[1] ? safeDecodeURIComponent(result[1]) : null;
|
|
1005
1005
|
} else return null;
|
|
1006
1006
|
});
|
|
@@ -1020,7 +1020,9 @@ function useSetCookies() {
|
|
|
1020
1020
|
});
|
|
1021
1021
|
}
|
|
1022
1022
|
function cookies() {
|
|
1023
|
-
|
|
1023
|
+
const entries = cookiesStore.entries();
|
|
1024
|
+
if (entries.length === 0) return [];
|
|
1025
|
+
return entries.filter((a) => !!a[1]).map(([key, value]) => renderCookie(key, value));
|
|
1024
1026
|
}
|
|
1025
1027
|
return {
|
|
1026
1028
|
setCookie,
|
|
@@ -1344,12 +1346,10 @@ var BaseHttpResponse = class {
|
|
|
1344
1346
|
const { cookies, removeCookie } = useSetCookies();
|
|
1345
1347
|
const newCookies = this._headers["set-cookie"] || [];
|
|
1346
1348
|
for (const cookie of newCookies) removeCookie(cookie.slice(0, cookie.indexOf("=")));
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
const setCookie = [...newCookies, ...cookies()];
|
|
1352
|
-
if (setCookie.length > 0) this._headers["set-cookie"] = setCookie;
|
|
1349
|
+
const composableHeaders = headers();
|
|
1350
|
+
for (const key in composableHeaders) if (!(key in this._headers)) this._headers[key] = composableHeaders[key];
|
|
1351
|
+
const renderedCookies = cookies();
|
|
1352
|
+
if (newCookies.length > 0 || renderedCookies.length > 0) this._headers["set-cookie"] = newCookies.length > 0 && renderedCookies.length > 0 ? [...newCookies, ...renderedCookies] : newCookies.length > 0 ? newCookies : renderedCookies;
|
|
1353
1353
|
return this;
|
|
1354
1354
|
}
|
|
1355
1355
|
mergeStatus(renderedBody) {
|
|
@@ -1377,7 +1377,7 @@ var BaseHttpResponse = class {
|
|
|
1377
1377
|
const res = rawResponse();
|
|
1378
1378
|
if (this.body instanceof Readable$1) {
|
|
1379
1379
|
const stream = this.body;
|
|
1380
|
-
this.mergeStatus(
|
|
1380
|
+
this.mergeStatus(true);
|
|
1381
1381
|
res.writeHead(this.status, { ...this._headers });
|
|
1382
1382
|
rawRequest.once("close", () => {
|
|
1383
1383
|
stream.destroy();
|
|
@@ -1399,32 +1399,37 @@ var BaseHttpResponse = class {
|
|
|
1399
1399
|
});
|
|
1400
1400
|
} else if (globalThis.Response && this.body instanceof Response) {
|
|
1401
1401
|
this.mergeFetchStatus(this.body.status);
|
|
1402
|
+
const additionalHeaders = {};
|
|
1403
|
+
const fetchContentLength = this.body.headers.get("content-length");
|
|
1404
|
+
if (fetchContentLength) additionalHeaders["content-length"] = fetchContentLength;
|
|
1405
|
+
const fetchContentType = this.body.headers.get("content-type");
|
|
1406
|
+
if (fetchContentType) additionalHeaders["content-type"] = fetchContentType;
|
|
1407
|
+
res.writeHead(this.status, {
|
|
1408
|
+
...this._headers,
|
|
1409
|
+
...additionalHeaders
|
|
1410
|
+
});
|
|
1402
1411
|
if (method === "HEAD") res.end();
|
|
1403
|
-
else
|
|
1404
|
-
const additionalHeaders = {};
|
|
1405
|
-
if (this.body.headers.get("content-length")) additionalHeaders["content-length"] = this.body.headers.get("content-length");
|
|
1406
|
-
if (this.body.headers.get("content-type")) additionalHeaders["content-type"] = this.body.headers.get("content-type");
|
|
1407
|
-
res.writeHead(this.status, {
|
|
1408
|
-
...additionalHeaders,
|
|
1409
|
-
...this._headers
|
|
1410
|
-
});
|
|
1411
|
-
await respondWithFetch(this.body.body, res);
|
|
1412
|
-
}
|
|
1412
|
+
else await respondWithFetch(this.body.body, res, logger);
|
|
1413
1413
|
} else {
|
|
1414
1414
|
const renderedBody = this.renderer.render(this);
|
|
1415
1415
|
this.mergeStatus(renderedBody);
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1416
|
+
const contentLength = typeof renderedBody === "string" ? Buffer.byteLength(renderedBody) : renderedBody.byteLength;
|
|
1417
|
+
return new Promise((resolve) => {
|
|
1418
|
+
res.writeHead(this.status, {
|
|
1419
|
+
"content-length": contentLength,
|
|
1420
|
+
...this._headers
|
|
1421
|
+
}).end(method === "HEAD" ? "" : renderedBody, resolve);
|
|
1422
|
+
});
|
|
1420
1423
|
}
|
|
1421
1424
|
}
|
|
1422
1425
|
};
|
|
1423
|
-
async function respondWithFetch(fetchBody, res) {
|
|
1426
|
+
async function respondWithFetch(fetchBody, res, logger) {
|
|
1424
1427
|
if (fetchBody) try {
|
|
1425
1428
|
for await (const chunk of fetchBody) res.write(chunk);
|
|
1426
|
-
} catch {
|
|
1427
|
-
|
|
1429
|
+
} catch (error) {
|
|
1430
|
+
logger.error("Error streaming fetch response body", error);
|
|
1431
|
+
}
|
|
1432
|
+
if (!res.writableEnded) res.end();
|
|
1428
1433
|
}
|
|
1429
1434
|
|
|
1430
1435
|
//#endregion
|
|
@@ -1454,10 +1459,12 @@ function createWooksResponder(renderer = new BaseHttpResponseRenderer(), errorRe
|
|
|
1454
1459
|
/** HTTP adapter for Wooks that provides route registration, server lifecycle, and request handling. */
|
|
1455
1460
|
var WooksHttp = class extends WooksAdapterBase {
|
|
1456
1461
|
logger;
|
|
1462
|
+
_cachedEventOptions;
|
|
1457
1463
|
constructor(opts, wooks) {
|
|
1458
1464
|
super(wooks, opts?.logger, opts?.router);
|
|
1459
1465
|
this.opts = opts;
|
|
1460
1466
|
this.logger = opts?.logger || this.getLogger(`[96m[wooks-http]`);
|
|
1467
|
+
this._cachedEventOptions = this.mergeEventOptions(opts?.eventOptions);
|
|
1461
1468
|
}
|
|
1462
1469
|
/** Registers a handler for all HTTP methods on the given path. */
|
|
1463
1470
|
all(path, handler) {
|
|
@@ -1545,7 +1552,7 @@ var WooksHttp = class extends WooksAdapterBase {
|
|
|
1545
1552
|
}
|
|
1546
1553
|
responder = createWooksResponder();
|
|
1547
1554
|
respond(data) {
|
|
1548
|
-
this.responder.respond(data)?.catch((error) => {
|
|
1555
|
+
return this.responder.respond(data)?.catch((error) => {
|
|
1549
1556
|
this.logger.error("Uncaught response exception", error);
|
|
1550
1557
|
});
|
|
1551
1558
|
}
|
|
@@ -1567,20 +1574,23 @@ var WooksHttp = class extends WooksAdapterBase {
|
|
|
1567
1574
|
req,
|
|
1568
1575
|
res,
|
|
1569
1576
|
requestLimits: this.opts?.requestLimits
|
|
1570
|
-
}, this.
|
|
1577
|
+
}, this._cachedEventOptions);
|
|
1578
|
+
const method = req.method || "";
|
|
1579
|
+
const url = req.url || "";
|
|
1571
1580
|
runInContext(async () => {
|
|
1572
|
-
const
|
|
1573
|
-
|
|
1574
|
-
|
|
1581
|
+
const notFoundHandler = this.opts?.onNotFound;
|
|
1582
|
+
const { handlers } = this.wooks.lookup(method, url);
|
|
1583
|
+
if (handlers || notFoundHandler) try {
|
|
1584
|
+
return await this.processHandlers(handlers || [notFoundHandler]);
|
|
1575
1585
|
} catch (error) {
|
|
1576
1586
|
this.logger.error("Internal error, please report", error);
|
|
1577
|
-
this.respond(error);
|
|
1587
|
+
await this.respond(error);
|
|
1578
1588
|
return error;
|
|
1579
1589
|
}
|
|
1580
1590
|
else {
|
|
1581
|
-
this.logger.debug(`404 Not found (${
|
|
1591
|
+
this.logger.debug(`404 Not found (${method})${url}`);
|
|
1582
1592
|
const error = new HttpError(404);
|
|
1583
|
-
this.respond(error);
|
|
1593
|
+
await this.respond(error);
|
|
1584
1594
|
return error;
|
|
1585
1595
|
}
|
|
1586
1596
|
});
|
|
@@ -1588,17 +1598,18 @@ var WooksHttp = class extends WooksAdapterBase {
|
|
|
1588
1598
|
}
|
|
1589
1599
|
async processHandlers(handlers) {
|
|
1590
1600
|
const { store } = useHttpContext();
|
|
1591
|
-
for (
|
|
1592
|
-
const
|
|
1601
|
+
for (let i = 0; i < handlers.length; i++) {
|
|
1602
|
+
const handler = handlers[i];
|
|
1603
|
+
const isLastHandler = i === handlers.length - 1;
|
|
1593
1604
|
try {
|
|
1594
1605
|
const promise = handler();
|
|
1595
1606
|
const result = await promise;
|
|
1596
|
-
this.respond(result);
|
|
1607
|
+
await this.respond(result);
|
|
1597
1608
|
return result;
|
|
1598
1609
|
} catch (error) {
|
|
1599
1610
|
if (error instanceof HttpError) {} else this.logger.error(`Uncaught route handler exception: ${store("event").get("req")?.url || ""}`, error);
|
|
1600
1611
|
if (isLastHandler) {
|
|
1601
|
-
this.respond(error);
|
|
1612
|
+
await this.respond(error);
|
|
1602
1613
|
return error;
|
|
1603
1614
|
}
|
|
1604
1615
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wooksjs/event-http",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6",
|
|
4
4
|
"description": "@wooksjs/event-http",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -47,18 +47,17 @@
|
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"typescript": "^5.9.3",
|
|
49
49
|
"vitest": "^3.2.4",
|
|
50
|
-
"@wooksjs/event-core": "^0.6.
|
|
51
|
-
"wooks": "^0.6.
|
|
50
|
+
"@wooksjs/event-core": "^0.6.6",
|
|
51
|
+
"wooks": "^0.6.6"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"@prostojs/logger": "^0.4.3",
|
|
55
|
-
"@prostojs/router": "^0.
|
|
56
|
-
"@wooksjs/event-core": "^0.6.
|
|
57
|
-
"wooks": "^0.6.
|
|
55
|
+
"@prostojs/router": "^0.3.1",
|
|
56
|
+
"@wooksjs/event-core": "^0.6.6",
|
|
57
|
+
"wooks": "^0.6.6"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
60
60
|
"build": "rolldown -c ../../rolldown.config.mjs",
|
|
61
|
-
"postinstall": "node scripts/setup-skills.js",
|
|
62
61
|
"setup-skills": "node scripts/setup-skills.js"
|
|
63
62
|
}
|
|
64
63
|
}
|