@downcity/city 0.2.129 → 0.2.130

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 CHANGED
@@ -65,32 +65,33 @@ serve({ fetch: (request) => base.fetch(request), port: 43127, hostname: "127.0.0
65
65
 
66
66
  ## HTTP Middleware
67
67
 
68
- Federation 级 middleware 会在内部路由和 Action body 读取之前执行,适合统一放 CORS、安全响应头、body 大小限制、限流和超时:
68
+ Federation 级 middleware 会在内部路由和 Action body 读取之前执行。`@downcity/city` 只提供 middleware 接口,不内置 CORS、安全响应头、body 大小限制、限流、超时等策略实现;这些策略应由具体调用方按自己的 HTTP 运行环境提供。
69
69
 
70
70
  ```ts
71
- import {
72
- bodyLimit,
73
- clientIp,
74
- cors,
75
- memoryRateLimitStore,
76
- rateLimit,
77
- requestTimeout,
78
- securityHeaders,
79
- } from "@downcity/city";
80
-
81
- base.middle(securityHeaders());
82
- base.middle(cors({
83
- origins: ["https://app.example.com"],
84
- max_age: 86400,
85
- }));
86
- base.middle(bodyLimit({ max_bytes: 1_000_000 }));
87
- base.middle(rateLimit({
88
- window_ms: 60_000,
89
- max: 120,
90
- key: (ctx) => clientIp(ctx.request),
91
- store: memoryRateLimitStore(),
92
- }));
93
- base.middle(requestTimeout({ ms: 30_000 }));
71
+ base.middle(async (ctx, next) => {
72
+ const origin = ctx.request.headers.get("origin");
73
+ if (ctx.request.method === "OPTIONS" && origin === "https://app.example.com") {
74
+ return new Response(null, {
75
+ status: 204,
76
+ headers: {
77
+ "Access-Control-Allow-Origin": origin,
78
+ "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
79
+ "Access-Control-Allow-Headers": "Content-Type, Authorization",
80
+ },
81
+ });
82
+ }
83
+
84
+ const response = await next();
85
+ if (!origin) return response;
86
+
87
+ const headers = new Headers(response.headers);
88
+ headers.set("Access-Control-Allow-Origin", origin);
89
+ return new Response(response.body, {
90
+ status: response.status,
91
+ statusText: response.statusText,
92
+ headers,
93
+ });
94
+ });
94
95
  ```
95
96
 
96
97
  ## City 说明文档
package/bin/index.d.ts CHANGED
@@ -12,8 +12,7 @@ export type { Runtime, EnvProvider, BuiltinTables, TableDef } from "./federation
12
12
  export type { CityQueueAdapter, CityQueueMessage } from "./federation/queue.js";
13
13
  export { R2Storage } from "./federation/storage.js";
14
14
  export type { FederationStorage, FederationStorageStoreInput, FederationStorageStoreResult, R2BucketLike, R2StorageOptions, } from "./federation/storage.js";
15
- export { bodyLimit, clientIp, cors, memoryRateLimitStore, rateLimit, requestTimeout, securityHeaders, } from "./federation/middlewares.js";
16
- export type { BodyLimitOptions, CorsOptions, FederationMiddleware, FederationMiddlewareContext, FederationMiddlewareFederationRef, FederationMiddlewareNext, RateLimitOptions, RateLimitStore, RateLimitStoreIncrementResult, RequestTimeoutOptions, SecurityHeadersOptions, } from "./types/FederationMiddleware.js";
15
+ export type { FederationMiddleware, FederationMiddlewareContext, FederationMiddlewareFederationRef, FederationMiddlewareNext, } from "./types/FederationMiddleware.js";
17
16
  export { Service } from "./service/service.js";
18
17
  export { InstallableService } from "./service/installable-service.js";
19
18
  export { Action } from "./service/action.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/bin/index.js CHANGED
@@ -10,7 +10,6 @@
10
10
  // ===========================================================================
11
11
  export { Federation } from "./federation/federation.js";
12
12
  export { R2Storage } from "./federation/storage.js";
13
- export { bodyLimit, clientIp, cors, memoryRateLimitStore, rateLimit, requestTimeout, securityHeaders, } from "./federation/middlewares.js";
14
13
  // ===========================================================================
15
14
  // 场景 2:注册 Service / InstallableService / AI 模型
16
15
  // ===========================================================================
package/bin/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAKxD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAQpD,OAAO,EACL,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAerC,8EAA8E;AAC9E,+CAA+C;AAC/C,8EAA8E;AAE9E,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAmC7C,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAcpD,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAChB,6BAA6B,EAC7B,qCAAqC,EACrC,gBAAgB,EAChB,gBAAgB,EAChB,4BAA4B,EAC5B,eAAe,EACf,UAAU,EACV,oBAAoB,EACpB,cAAc,EACd,QAAQ,EACR,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAiBjC,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAShE,8EAA8E;AAC9E,0BAA0B;AAC1B,8EAA8E;AAE9E,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAQ1D,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAOtD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAqB3C,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAUxC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAyCxE,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AA8BzD,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAE7E,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,OAAO,EACL,YAAY,EACZ,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,SAAS,EACT,eAAe,EACf,WAAW,EACX,kBAAkB,GACnB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAKxD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAepD,8EAA8E;AAC9E,+CAA+C;AAC/C,8EAA8E;AAE9E,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAmC7C,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAcpD,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAChB,6BAA6B,EAC7B,qCAAqC,EACrC,gBAAgB,EAChB,gBAAgB,EAChB,4BAA4B,EAC5B,eAAe,EACf,UAAU,EACV,oBAAoB,EACpB,cAAc,EACd,QAAQ,EACR,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAiBjC,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAShE,8EAA8E;AAC9E,0BAA0B;AAC1B,8EAA8E;AAE9E,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAQ1D,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAOtD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAqB3C,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAUxC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAyCxE,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AA8BzD,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAE7E,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,OAAO,EACL,YAAY,EACZ,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,SAAS,EACT,eAAe,EACf,WAAW,EACX,kBAAkB,GACnB,MAAM,oBAAoB,CAAC"}
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Federation HTTP Middleware 类型模块。
3
3
  *
4
- * 定义 `fed.middle()` 使用的中间件上下文、next 函数以及内置
5
- * middleware helper 的公开配置类型。该层只处理 HTTP 入站横切策略,
6
- * 不承载 Service / Action 的业务生命周期逻辑。
4
+ * 定义 `fed.middle()` 使用的中间件上下文与 next 函数。该层只约束
5
+ * Federation HTTP middleware 的接入接口,具体 CORS、安全响应头、
6
+ * 限流、超时等策略实现由调用方按自己的运行环境提供。
7
7
  */
8
8
  import type { Service } from "../service/service.js";
9
9
  import type { Runtime } from "../federation/runtime.js";
@@ -47,92 +47,4 @@ export interface FederationMiddlewareContext {
47
47
  /** middleware 之间共享的轻量临时上下文。 */
48
48
  locals: Record<string, unknown>;
49
49
  }
50
- /**
51
- * 请求体大小限制配置。
52
- */
53
- export interface BodyLimitOptions {
54
- /** 允许的最大请求体字节数。 */
55
- max_bytes: number;
56
- /** 需要检查的 HTTP 方法;默认检查 POST、PUT、PATCH。 */
57
- methods?: readonly string[];
58
- /** 需要检查的路径模式;支持精确路径和 `*` 后缀前缀匹配。 */
59
- paths?: readonly string[];
60
- }
61
- /**
62
- * CORS middleware 配置。
63
- */
64
- export interface CorsOptions {
65
- /** 允许的 Origin 列表;传 `"*"` 表示允许所有 Origin。 */
66
- origins: readonly string[] | "*";
67
- /** 允许的 HTTP 方法列表。 */
68
- methods?: readonly string[];
69
- /** 允许的请求头列表。 */
70
- headers?: readonly string[];
71
- /** preflight 响应的缓存秒数。 */
72
- max_age?: number;
73
- /** Origin 不允许时是否直接返回 403。 */
74
- strict?: boolean;
75
- }
76
- /**
77
- * 安全响应头配置。
78
- */
79
- export interface SecurityHeadersOptions {
80
- /** 是否设置 X-Content-Type-Options,默认 true。 */
81
- content_type_options?: boolean;
82
- /** Referrer-Policy 响应头值,默认 no-referrer。 */
83
- referrer_policy?: string;
84
- /** X-Frame-Options 响应头值,默认 DENY。 */
85
- frame_options?: string;
86
- /** Permissions-Policy 响应头值。 */
87
- permissions_policy?: string;
88
- /** Strict-Transport-Security 响应头值;未传入时不设置。 */
89
- strict_transport_security?: string;
90
- /** Content-Security-Policy 响应头值;未传入时不设置。 */
91
- content_security_policy?: string;
92
- }
93
- /**
94
- * 请求超时配置。
95
- */
96
- export interface RequestTimeoutOptions {
97
- /** 请求超时时间,单位毫秒。 */
98
- ms: number;
99
- /** 不启用超时保护的路径模式;支持精确路径和 `*` 后缀前缀匹配。 */
100
- exclude_paths?: readonly string[];
101
- }
102
- /**
103
- * 限流存储接口。
104
- */
105
- export interface RateLimitStore {
106
- /**
107
- * 增加当前 key 在窗口内的请求次数。
108
- *
109
- * @param key - 限流维度 key。
110
- * @param window_ms - 限流窗口长度,单位毫秒。
111
- */
112
- increment(key: string, window_ms: number): Promise<RateLimitStoreIncrementResult>;
113
- }
114
- /**
115
- * 限流存储增加计数后的结果。
116
- */
117
- export interface RateLimitStoreIncrementResult {
118
- /** 当前窗口内已经累计的请求次数。 */
119
- count: number;
120
- /** 当前窗口重置的 Unix 时间戳,单位毫秒。 */
121
- reset_at: number;
122
- }
123
- /**
124
- * 限流 middleware 配置。
125
- */
126
- export interface RateLimitOptions {
127
- /** 限流窗口长度,单位毫秒。 */
128
- window_ms: number;
129
- /** 单个窗口允许的最大请求数。 */
130
- max: number;
131
- /** 生成限流 key 的函数。 */
132
- key(ctx: FederationMiddlewareContext): string | Promise<string>;
133
- /** 判断当前请求是否需要限流的函数。 */
134
- match?: (ctx: FederationMiddlewareContext) => boolean | Promise<boolean>;
135
- /** 限流计数存储。 */
136
- store: RateLimitStore;
137
- }
138
50
  //# sourceMappingURL=FederationMiddleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FederationMiddleware.d.ts","sourceRoot":"","sources":["../../src/types/FederationMiddleware.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FederationMiddleware.d.ts","sourceRoot":"","sources":["../../src/types/FederationMiddleware.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,wBAAwB,CAAC;AAEhF;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE/D;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,GAAG,EAAE,2BAA2B,EAChC,IAAI,EAAE,wBAAwB,KAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,iCAAiC;IAChD,uCAAuC;IACvC,QAAQ,IAAI,SAAS,OAAO,EAAE,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,oBAAoB;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,uBAAuB;IACvB,SAAS,CAAC,EAAE,iCAAiC,CAAC;IAC9C,8BAA8B;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,6BAA6B;IAC7B,UAAU,EAAE,iCAAiC,CAAC;IAC9C,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC"}
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Federation HTTP Middleware 类型模块。
3
3
  *
4
- * 定义 `fed.middle()` 使用的中间件上下文、next 函数以及内置
5
- * middleware helper 的公开配置类型。该层只处理 HTTP 入站横切策略,
6
- * 不承载 Service / Action 的业务生命周期逻辑。
4
+ * 定义 `fed.middle()` 使用的中间件上下文与 next 函数。该层只约束
5
+ * Federation HTTP middleware 的接入接口,具体 CORS、安全响应头、
6
+ * 限流、超时等策略实现由调用方按自己的运行环境提供。
7
7
  */
8
8
  export {};
9
9
  //# sourceMappingURL=FederationMiddleware.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@downcity/city",
3
- "version": "0.2.129",
3
+ "version": "0.2.130",
4
4
  "description": "Downcity City runtime and City access SDK for services, actions, auth, env, and cities.",
5
5
  "type": "module",
6
6
  "main": "./bin/index.js",
@@ -1,44 +0,0 @@
1
- /**
2
- * Federation 内置 HTTP middleware。
3
- *
4
- * 提供生产入口常用的横切安全策略:请求体大小限制、CORS、安全响应头、
5
- * 请求超时和粗粒度限流。所有 helper 都运行在内部 router 之前。
6
- */
7
- import type { BodyLimitOptions, CorsOptions, FederationMiddleware, RateLimitOptions, RateLimitStore, RequestTimeoutOptions, SecurityHeadersOptions } from "../types/FederationMiddleware.js";
8
- /**
9
- * 在业务路由读取 body 前基于 Content-Length 拒绝过大请求。
10
- */
11
- export declare function bodyLimit(options: BodyLimitOptions): FederationMiddleware;
12
- /**
13
- * 处理 CORS preflight,并为允许的 Origin 回填 CORS 响应头。
14
- */
15
- export declare function cors(options: CorsOptions): FederationMiddleware;
16
- /**
17
- * 为响应增加基础安全头。
18
- */
19
- export declare function securityHeaders(options?: SecurityHeadersOptions): FederationMiddleware;
20
- /**
21
- * 为普通请求增加总耗时保护。
22
- *
23
- * 关键说明(中文)
24
- * - 这里只能让 HTTP 层返回 504,不能保证取消下游 provider 外呼。
25
- * - 流式接口建议通过 `exclude_paths` 排除。
26
- */
27
- export declare function requestTimeout(options: RequestTimeoutOptions): FederationMiddleware;
28
- /**
29
- * 基于可插拔 store 的粗粒度限流。
30
- */
31
- export declare function rateLimit(options: RateLimitOptions): FederationMiddleware;
32
- /**
33
- * 创建进程内限流 store。
34
- *
35
- * 关键说明(中文)
36
- * - 适合本地开发、Node 单进程或单 isolate 兜底。
37
- * - 多实例 / 多区域生产限流应使用共享存储或平台能力。
38
- */
39
- export declare function memoryRateLimitStore(): RateLimitStore;
40
- /**
41
- * 从常见代理头读取客户端 IP。
42
- */
43
- export declare function clientIp(request: Request): string;
44
- //# sourceMappingURL=middlewares.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"middlewares.d.ts","sourceRoot":"","sources":["../../src/federation/middlewares.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,WAAW,EACX,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EAEd,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,kCAAkC,CAAC;AAO1C;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,oBAAoB,CAsBzE;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,oBAAoB,CA0B/D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,oBAAoB,CAqB1F;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,oBAAoB,CAoBnF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,oBAAoB,CAqBzE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAiBrD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAUjD"}
@@ -1,219 +0,0 @@
1
- /**
2
- * Federation 内置 HTTP middleware。
3
- *
4
- * 提供生产入口常用的横切安全策略:请求体大小限制、CORS、安全响应头、
5
- * 请求超时和粗粒度限流。所有 helper 都运行在内部 router 之前。
6
- */
7
- const DEFAULT_BODY_LIMIT_METHODS = ["POST", "PUT", "PATCH"];
8
- const DEFAULT_CORS_METHODS = ["GET", "POST", "OPTIONS"];
9
- const DEFAULT_CORS_HEADERS = ["Content-Type", "Authorization"];
10
- const DEFAULT_PERMISSIONS_POLICY = "camera=(), microphone=(), geolocation=()";
11
- /**
12
- * 在业务路由读取 body 前基于 Content-Length 拒绝过大请求。
13
- */
14
- export function bodyLimit(options) {
15
- const methods = new Set((options.methods ?? DEFAULT_BODY_LIMIT_METHODS).map((method) => method.toUpperCase()));
16
- return (ctx, next) => {
17
- if (!methods.has(ctx.request.method.toUpperCase())) {
18
- return next();
19
- }
20
- if (!match_path(ctx.request, options.paths)) {
21
- return next();
22
- }
23
- const content_length = ctx.request.headers.get("content-length");
24
- if (!content_length) {
25
- return next();
26
- }
27
- const size = Number.parseInt(content_length, 10);
28
- if (Number.isFinite(size) && size > options.max_bytes) {
29
- return json_error("Request body too large", "request_too_large", 413);
30
- }
31
- return next();
32
- };
33
- }
34
- /**
35
- * 处理 CORS preflight,并为允许的 Origin 回填 CORS 响应头。
36
- */
37
- export function cors(options) {
38
- const methods = options.methods ?? DEFAULT_CORS_METHODS;
39
- const headers = options.headers ?? DEFAULT_CORS_HEADERS;
40
- return async (ctx, next) => {
41
- const origin = ctx.request.headers.get("origin");
42
- const allowed_origin = resolve_allowed_origin(origin, options.origins);
43
- if (origin && !allowed_origin && options.strict) {
44
- return json_error("Origin is not allowed", "origin_forbidden", 403);
45
- }
46
- if (ctx.request.method.toUpperCase() === "OPTIONS") {
47
- const response_headers = new Headers();
48
- append_cors_headers(response_headers, allowed_origin, methods, headers, options.max_age);
49
- return new Response(null, { status: 204, headers: response_headers });
50
- }
51
- const response = await next();
52
- if (!allowed_origin) {
53
- return response;
54
- }
55
- const response_headers = new Headers(response.headers);
56
- append_cors_headers(response_headers, allowed_origin, methods, headers, options.max_age);
57
- return clone_response_with_headers(response, response_headers);
58
- };
59
- }
60
- /**
61
- * 为响应增加基础安全头。
62
- */
63
- export function securityHeaders(options = {}) {
64
- return async (_ctx, next) => {
65
- const response = await next();
66
- const headers = new Headers(response.headers);
67
- if (options.content_type_options !== false) {
68
- headers.set("X-Content-Type-Options", "nosniff");
69
- }
70
- headers.set("Referrer-Policy", options.referrer_policy ?? "no-referrer");
71
- headers.set("X-Frame-Options", options.frame_options ?? "DENY");
72
- headers.set("Permissions-Policy", options.permissions_policy ?? DEFAULT_PERMISSIONS_POLICY);
73
- if (options.strict_transport_security) {
74
- headers.set("Strict-Transport-Security", options.strict_transport_security);
75
- }
76
- if (options.content_security_policy) {
77
- headers.set("Content-Security-Policy", options.content_security_policy);
78
- }
79
- return clone_response_with_headers(response, headers);
80
- };
81
- }
82
- /**
83
- * 为普通请求增加总耗时保护。
84
- *
85
- * 关键说明(中文)
86
- * - 这里只能让 HTTP 层返回 504,不能保证取消下游 provider 外呼。
87
- * - 流式接口建议通过 `exclude_paths` 排除。
88
- */
89
- export function requestTimeout(options) {
90
- return async (ctx, next) => {
91
- if (options.exclude_paths && match_path(ctx.request, options.exclude_paths)) {
92
- return next();
93
- }
94
- let timer;
95
- try {
96
- return await Promise.race([
97
- next(),
98
- new Promise((resolve) => {
99
- timer = setTimeout(() => {
100
- resolve(json_error("Request timed out", "request_timeout", 504));
101
- }, options.ms);
102
- }),
103
- ]);
104
- }
105
- finally {
106
- if (timer)
107
- clearTimeout(timer);
108
- }
109
- };
110
- }
111
- /**
112
- * 基于可插拔 store 的粗粒度限流。
113
- */
114
- export function rateLimit(options) {
115
- return async (ctx, next) => {
116
- if (options.match && !await options.match(ctx)) {
117
- return next();
118
- }
119
- const key = await options.key(ctx);
120
- const result = await options.store.increment(key, options.window_ms);
121
- const remaining = Math.max(options.max - result.count, 0);
122
- if (result.count > options.max) {
123
- const response = json_error("Too many requests", "rate_limited", 429);
124
- set_rate_limit_headers(response.headers, options.max, remaining, result.reset_at);
125
- return response;
126
- }
127
- const response = await next();
128
- const headers = new Headers(response.headers);
129
- set_rate_limit_headers(headers, options.max, remaining, result.reset_at);
130
- return clone_response_with_headers(response, headers);
131
- };
132
- }
133
- /**
134
- * 创建进程内限流 store。
135
- *
136
- * 关键说明(中文)
137
- * - 适合本地开发、Node 单进程或单 isolate 兜底。
138
- * - 多实例 / 多区域生产限流应使用共享存储或平台能力。
139
- */
140
- export function memoryRateLimitStore() {
141
- const windows = new Map();
142
- return {
143
- async increment(key, window_ms) {
144
- const now = Date.now();
145
- const current = windows.get(key);
146
- if (!current || current.reset_at <= now) {
147
- const next_window = { count: 1, reset_at: now + window_ms };
148
- windows.set(key, next_window);
149
- return next_window;
150
- }
151
- current.count += 1;
152
- return current;
153
- },
154
- };
155
- }
156
- /**
157
- * 从常见代理头读取客户端 IP。
158
- */
159
- export function clientIp(request) {
160
- const cf_ip = request.headers.get("cf-connecting-ip");
161
- if (cf_ip)
162
- return cf_ip;
163
- const forwarded_for = request.headers.get("x-forwarded-for");
164
- if (forwarded_for) {
165
- return forwarded_for.split(",")[0]?.trim() || "unknown";
166
- }
167
- return request.headers.get("x-real-ip") ?? "unknown";
168
- }
169
- function json_error(message, type, status) {
170
- return Response.json({ error: { message, type } }, { status });
171
- }
172
- function resolve_allowed_origin(origin, origins) {
173
- if (!origin)
174
- return undefined;
175
- if (origins === "*")
176
- return "*";
177
- return origins.includes(origin) ? origin : undefined;
178
- }
179
- function append_cors_headers(headers, allowed_origin, methods, request_headers, max_age) {
180
- if (allowed_origin) {
181
- headers.set("Access-Control-Allow-Origin", allowed_origin);
182
- if (allowed_origin !== "*") {
183
- headers.append("Vary", "Origin");
184
- }
185
- }
186
- headers.set("Access-Control-Allow-Methods", methods.join(", "));
187
- headers.set("Access-Control-Allow-Headers", request_headers.join(", "));
188
- if (max_age !== undefined) {
189
- headers.set("Access-Control-Max-Age", String(max_age));
190
- }
191
- }
192
- function set_rate_limit_headers(headers, limit, remaining, reset_at) {
193
- const reset_seconds = Math.ceil(reset_at / 1000);
194
- const retry_after = Math.max(Math.ceil((reset_at - Date.now()) / 1000), 0);
195
- headers.set("Retry-After", String(retry_after));
196
- headers.set("X-RateLimit-Limit", String(limit));
197
- headers.set("X-RateLimit-Remaining", String(remaining));
198
- headers.set("X-RateLimit-Reset", String(reset_seconds));
199
- }
200
- function clone_response_with_headers(response, headers) {
201
- return new Response(response.body, {
202
- status: response.status,
203
- statusText: response.statusText,
204
- headers,
205
- });
206
- }
207
- function match_path(request, patterns) {
208
- if (!patterns || patterns.length === 0) {
209
- return true;
210
- }
211
- const pathname = new URL(request.url).pathname;
212
- return patterns.some((pattern) => {
213
- if (pattern.endsWith("*")) {
214
- return pathname.startsWith(pattern.slice(0, -1));
215
- }
216
- return pathname === pattern;
217
- });
218
- }
219
- //# sourceMappingURL=middlewares.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../../src/federation/middlewares.ts"],"names":[],"mappings":"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"}