@faapi/faapi 4.0.0 → 4.1.0
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 +5 -0
- package/dist/cli/index.js +21 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +21 -6
- package/dist/index.js.map +1 -1
- package/dist/testing.js +21 -6
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,6 +48,11 @@ node dist/main # 启动生产服务器
|
|
|
48
48
|
- 洋葱模型中间件:`(ctx, next) => {}`
|
|
49
49
|
- 依赖注入:注入器按参数名匹配 handler 参数
|
|
50
50
|
- WebSocket 路由:导出 `WS` 函数声明
|
|
51
|
+
- SSE 流式响应:`ctx.sse()` 流式推送(LLM 输出、通知推送)
|
|
52
|
+
- 响应压缩:`compression: true`,gzip/deflate/br 协商,SSE 自动跳过
|
|
53
|
+
- ETag/304 协商:`etag: true`,GET/HEAD 弱 ETag 自动生成与协商
|
|
54
|
+
- 优雅停机:SIGTERM/SIGINT 默认注册,drain 在途请求(`FAAPI_SHUTDOWN_TIMEOUT_MS` 可调)
|
|
55
|
+
- app 级注册表:tool/agent/skill 注册表随 app 实例创建与销毁,多 app 同进程隔离
|
|
51
56
|
- SSE 流式响应:`ctx.sse()` 推送
|
|
52
57
|
- 动态路由:`[id]` / `[...slug]` / `(group)`
|
|
53
58
|
- MCP 集成:LLM 可查询路由 schema
|
package/dist/cli/index.js
CHANGED
|
@@ -7519,7 +7519,7 @@ import { createSecureServer as createHttp2SecureServer } from "http2";
|
|
|
7519
7519
|
import { readFileSync } from "fs";
|
|
7520
7520
|
import { Readable as Readable3 } from "stream";
|
|
7521
7521
|
import path22 from "path";
|
|
7522
|
-
function toWebRequest(req, bodyLimit = DEFAULT_BODY_LIMIT) {
|
|
7522
|
+
function toWebRequest(req, bodyLimit = DEFAULT_BODY_LIMIT, requestSignal) {
|
|
7523
7523
|
const forwardedProto = req.headers["x-forwarded-proto"];
|
|
7524
7524
|
const protocol = Array.isArray(forwardedProto) ? forwardedProto[0]?.split(",")[0]?.trim() ?? "http" : forwardedProto?.split(",")[0]?.trim() ?? "http";
|
|
7525
7525
|
const host = req.headers.host ?? "localhost";
|
|
@@ -7527,7 +7527,10 @@ function toWebRequest(req, bodyLimit = DEFAULT_BODY_LIMIT) {
|
|
|
7527
7527
|
const headers = nodeHttpToWebHeaders(req);
|
|
7528
7528
|
const method = req.method ?? "GET";
|
|
7529
7529
|
if (method === "GET" || method === "HEAD") {
|
|
7530
|
-
return {
|
|
7530
|
+
return {
|
|
7531
|
+
request: new Request(url.toString(), { method, headers, signal: requestSignal }),
|
|
7532
|
+
url
|
|
7533
|
+
};
|
|
7531
7534
|
}
|
|
7532
7535
|
const contentLength = req.headers["content-length"];
|
|
7533
7536
|
if (contentLength !== void 0) {
|
|
@@ -7543,7 +7546,8 @@ function toWebRequest(req, bodyLimit = DEFAULT_BODY_LIMIT) {
|
|
|
7543
7546
|
method,
|
|
7544
7547
|
headers,
|
|
7545
7548
|
body: limitedStream,
|
|
7546
|
-
duplex: "half"
|
|
7549
|
+
duplex: "half",
|
|
7550
|
+
signal: requestSignal
|
|
7547
7551
|
}),
|
|
7548
7552
|
url
|
|
7549
7553
|
};
|
|
@@ -7682,8 +7686,8 @@ function createServer(options) {
|
|
|
7682
7686
|
});
|
|
7683
7687
|
return { server, routesRef };
|
|
7684
7688
|
}
|
|
7685
|
-
function prepareRequest(req, config, bodyLimit, trustedProxy, registries) {
|
|
7686
|
-
const { request, url } = toWebRequest(req, bodyLimit);
|
|
7689
|
+
function prepareRequest(req, config, bodyLimit, trustedProxy, registries, requestSignal) {
|
|
7690
|
+
const { request, url } = toWebRequest(req, bodyLimit, requestSignal);
|
|
7687
7691
|
const method = request.method.toUpperCase();
|
|
7688
7692
|
const urlPath = url.pathname;
|
|
7689
7693
|
const ctx = createContextFromUrl(
|
|
@@ -7768,8 +7772,19 @@ async function sendErrorResponse(err, meta, res, onError, ctx) {
|
|
|
7768
7772
|
async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares, onError, config, globalInjectors, bodyLimit, trustedProxy, registries) {
|
|
7769
7773
|
let meta = { headers: {}, setCookies: [] };
|
|
7770
7774
|
let ctx;
|
|
7775
|
+
const abortController = new AbortController();
|
|
7776
|
+
res.on("close", () => {
|
|
7777
|
+
if (!res.writableEnded) abortController.abort();
|
|
7778
|
+
});
|
|
7771
7779
|
try {
|
|
7772
|
-
const prepared = prepareRequest(
|
|
7780
|
+
const prepared = prepareRequest(
|
|
7781
|
+
req,
|
|
7782
|
+
config,
|
|
7783
|
+
bodyLimit,
|
|
7784
|
+
trustedProxy,
|
|
7785
|
+
registries,
|
|
7786
|
+
abortController.signal
|
|
7787
|
+
);
|
|
7773
7788
|
ctx = prepared.ctx;
|
|
7774
7789
|
meta = prepared.meta;
|
|
7775
7790
|
const { request, url, method, urlPath } = prepared;
|