Wasp 中间件配置指南:全局、API 级与路径级 Middleware 定制

发布时间:2026/9/14 10:17:33
Wasp 中间件配置指南:全局、API 级与路径级 Middleware 定制 Wasp 中间件配置指南全局、API 级与路径级 Middleware 定制【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/waspWasp 为每个应用内置了一套开箱即用的 Express 中间件Helmet、CORS、Morgan、JSON/urlencoded 解析与 cookieParser覆盖绝大多数默认场景。本文基于 version-0.12 文档 展开系统讲解如何通过middlewareConfigFn在全局、单条 API、以及整个 API 路径命名空间三个层面增删改中间件并深入生成器源码验证每一层配置的落地机制。读完本文你将掌握在 Wasp 应用中安全定制 HTTP 中间件的完整套路例如为 Webhook 回调禁用 JSON 解析、为多域名场景扩展 CORS 白名单并能预判修改对既有路由的影响范围。默认全局中间件内置的 Express 安全与解析层Wasp 的 Express 服务端在生成时默认挂载以下中间件它们对所有查询Query、动作Action和 API 路由生效Helmet通过设置各类 HTTP 安全响应头加固 Express 应用。它并非银弹但作为安全基线是很好的起点。CORS提供可配置的跨域资源共享中间件。前端与后端通信依赖 CORS 中间件因此不要随意移除。MorganHTTP 请求日志中间件默认以dev模式输出。express.json基于 body-parser 的 JSON 请求体解析解析结果挂载到req.body。Operations 依赖 JSON 中间件才能正常工作移除前务必三思。express.urlencoded仅解析Content-Type匹配的 urlencoded 请求体默认extended: false。cookieParser解析Cookie请求头并将结果以对象形式挂载到req.cookies。默认中间件的真实定义下面是 Wasp 文档给出的默认全局中间件定义即你可以覆盖的基准 MapJavaScript 与 TypeScript 两种写法等价const defaultGlobalMiddleware new Map([ [helmet, helmet()], [cors, cors({ origin: config.allowedCORSOrigins })], [logger, logger(dev)], [express.json, express.json()], [express.urlencoded, express.urlencoded({ extended: false })], [cookieParser, cookieParser()] ])TypeScript 版本还引入了两个关键类型export type MiddlewareConfig Mapstring, express.RequestHandler // 用于下面所有示例 export type MiddlewareConfigFn (middlewareConfig: MiddlewareConfig) MiddlewareConfig const defaultGlobalMiddleware: MiddlewareConfig new Map([ [helmet, helmet()], [cors, cors({ origin: config.allowedCORSOrigins })], [logger, logger(dev)], [express.json, express.json()], [express.urlencoded, express.urlencoded({ extended: false })], [cookieParser, cookieParser()] ])注意 CORS 的origin默认取自config.allowedCORSOrigins即 Wasp 配置中的 CORS 设置后续示例将演示如何在其基础上扩展额外域名。源码印证默认中间件在生成模板中的落点以上定义并非文档虚构而是直接来自 Wasp 生成器模板 globalMiddleware.ts。该文件真实地构造了defaultGlobalMiddlewareConfig且注释明确写着这是 Wasp 默认提供的中间件集合修改时记得同步更新文档const defaultGlobalMiddlewareConfig: MiddlewareConfig new Map([ [helmet, helmet()], [cors, cors({ origin: config.allowedCORSOrigins })], [logger, logger(dev)], [express.json, express.json()], [express.urlencoded, express.urlencoded()], [cookieParser, cookieParser()] ])同一文件还实现了把MiddlewareConfigMap转换为 Express 中间件数组的核心函数globalMiddlewareConfigForExpressglobalMiddleware.ts。它的关键设计是每次调用都会基于全局配置克隆一份新 Map再把用户的middlewareConfigFn应用到克隆上避免某个具体路由的定制污染全局 Map、影响其它路由。export function globalMiddlewareConfigForExpress(middlewareConfigFn?: MiddlewareConfigFn): express.RequestHandler[] { if (!middlewareConfigFn) { return Array.from(globalMiddlewareConfig.values()) } // 克隆一份防止路由级定制破坏全局 Map const globalMiddlewareConfigClone new Map(globalMiddlewareConfig) const modifiedMiddlewareConfig middlewareConfigFn(globalMiddlewareConfigClone) return Array.from(modifiedMiddlewareConfig.values()) }生成的根路由 routes/index.js 对根路径、/auth、Operations 路由和 CRUD 路由统一调用globalMiddlewareConfigForExpress()挂载全局中间件const middleware globalMiddlewareConfigForExpress() router.use(/{ operationsRouteInRootRouter }, middleware, operations)同时生成器明确把用户自定义 API 路由放在最后routes/index.js并注释不要把中间件加在这里以便后续支持中间件定制——这正是middlewareConfigFn得以在 API 层面独立生效的前提。三个定制层级全局、API 级、路径级Wasp 提供三个互不冲突的中间件定制位置全局Global对所有OperationsQuery/Action和 API 默认生效。适合为 CORS 增加多个域名这类全局诉求。⚠️ 全局改动影响面最大务必极其谨慎不确定时优先使用下面两个局部方案。API 级Per-api覆盖单条 API 路由例如POST /webhook/callback的中间件。适合为某个回调禁用 JSON 解析这类场景。路径级Per-path覆盖某个公共路径下的所有方法。适合复杂 CORS 请求需要同时作用于OPTIONS与GET或给一组API 路由统一加中间件的场景。层级背后的声明模型从源码看三个层级分别对应 Wasp AppSpec 中的三个声明字段App/Server.hsdata Server Server { setupFn :: Maybe ExtImport, middlewareConfigFn :: Maybe ExtImport, -- 全局层 envValidationSchema :: Maybe ExtImport }API 级对应 Api.hs 中的middlewareConfigFn :: Maybe ExtImport路径级对应 ApiNamespace.hs 中必填的middlewareConfigFn :: ExtImport注意它没有Maybe即apiNamespace声明必须提供中间件函数。差异也体现了设计意图全局与 API 级可缺省回退到默认而路径级本身就是为了注入定制而存在的。1. 定制全局中间件若要让某个改动作用于所有Operations 和 API在main.wasp的server配置块中声明middlewareConfigFnapp todoApp { // ... server: { setupFn: import setup from src/serverSetup, middlewareConfigFn: import { serverMiddlewareFn } from src/serverSetup }, }然后在src/serverSetup.ts中实现该函数。下面的例子演示如何为 CORS 增加额外的允许域名import cors from cors import { config, type MiddlewareConfigFn } from wasp/server export const serverMiddlewareFn: MiddlewareConfigFn (middlewareConfig) { // 在默认前端地址基础上追加两个域名 middlewareConfig.set(cors, cors({ origin: [config.frontendUrl, https://example1.com, https://example2.com] })) return middlewareConfig }要点通过middlewareConfig.set(key, handler)覆盖同名键即可替换对应中间件key必须与默认 Map 的键如cors、helmet一致。函数必须返回处理后的middlewareConfig否则改动不会生效。全局层直接修改的是整个应用的中间件基线任何局部未定制的路由都会继承这里的改动。生成器如何接入全局函数ServerGenerator.hs 会把server.middlewareConfigFn注入到 globalMiddleware.ts 模板若未定义则用恒等函数(mc) mc兜底若定义了则生成对应的 import 语句并在第 32 行通过globalMiddlewareConfigFn(defaultGlobalMiddlewareConfig)计算得到最终全局配置。2. 定制单条 API 的中间件当某条 API 需要与全局不同的中间件组合时在其api声明中加middlewareConfigFn// ... api webhookCallback { fn: import { webhookCallback } from src/apis, middlewareConfigFn: import { webhookCallbackMiddlewareFn } from src/apis, httpRoute: (POST, /webhook/callback), auth: false }实现示例Webhook 回调通常需要接收原始字节流这里把默认的 JSON 解析替换为express.rawimport express from express import { type WebhookCallback } from wasp/server/api import { type MiddlewareConfigFn } from wasp/server export const webhookCallback: WebhookCallback (req, res, _context) { res.json({ msg: req.body.length }) } export const webhookCallbackMiddlewareFn: MiddlewareConfigFn (middlewareConfig) { console.log(webhookCallbackMiddlewareFn: Swap express.json for express.raw) middlewareConfig.delete(express.json) middlewareConfig.set(express.raw, express.raw({ type: */* })) return middlewareConfig }解读先用delete(express.json)移除全局默认的 JSON 解析再用set注入express.raw实现仅此路由的行为替换。该中间件按 HTTP 方法method粒度安装。在生成的路由文件 apis/index.ts 中每个 API 都会生成独立的{apiName}Middleware并挂到对应方法的路由上。文档明确说明其背后等价于router.post(/webhook/callback, webhookCallbackMiddleware, ...)若api开启了鉴权auth: true鉴权中间件auth会排在定制中间件之前见 apis/index.ts 中[auth, ...{apiName}Middleware]的组装逻辑。3. 定制路径级apiNamespace中间件当需要把同一组中间件应用到某个公共路径下的所有API 路由覆盖所有 HTTP 方法时使用apiNamespace。它比逐条 API 配置更省事也天然覆盖OPTIONS这类预检请求。// ... apiNamespace fooBar { middlewareConfigFn: import { fooBarNamespaceMiddlewareFn } from src/apis, path: /foo/bar }import express from express import { type MiddlewareConfigFn } from wasp/server export const fooBarNamespaceMiddlewareFn: MiddlewareConfigFn (middlewareConfig) { const customMiddleware: express.RequestHandler (_req, _res, next) { console.log(fooBarNamespaceMiddlewareFn: custom middleware) next() } middlewareConfig.set(custom.middleware, customMiddleware) return middlewareConfig }关键点路径级中间件在路由器router级别安装作用于path前缀下的全部方法与路由。文档说明其背后等价于router.use(/foo/bar, fooBarNamespaceMiddleware)在生成的路由模板 apis/index.ts 中命名空间中间件通过router.use({namespacePath}, globalMiddlewareConfigForExpress(namespaceMiddlewareConfigFn))挂载且位于各 API 路由定义之前因此对命名空间下的每条路由统一生效。apiNamespace的middlewareConfigFn是必填字段见上文 ApiNamespace.hs 源码声明时不要遗漏。中间件解析的完整链路把三层的生成机制串起来可以看到一套统一的执行模型模板 globalMiddleware.ts 构造默认 Map应用全局middlewareConfigFn得到全局基线配置。根路由 routes/index.js 对根路径、auth、Operations、CRUD 路由统一挂载globalMiddlewareConfigForExpress()。自定义 API 路由文件 apis/index.ts 中每个apiNamespace先router.use(path, ...)挂载命名空间级中间件路径级定制每条api再通过globalMiddlewareConfigForExpress(routeMiddlewareConfigFn)生成独立中间件数组并挂载API 级定制。任何层级都通过globalMiddlewareConfigForExpress从全局配置克隆后修改天然隔离互不污染。注意事项与最佳实践全局层改动需极度小心它影响所有 Operations 和 API。若不确定影响面优先选择 API 级或路径级定制。文档原文明确给出了该警告见 middleware-config.md。不要轻易移除 CORS 与 JSON 中间件前者是前后端通信的前提后者是 Operations 正常工作的前提即使要替换也应像 Webhook 示例那样先delete旧键再set新键。Map 键名即契约覆盖默认中间件时键必须与默认 Map 一致helmet、cors、logger、express.json、express.urlencoded、cookieParser新增中间件时建议使用带前缀的键如示例中的custom.middleware避免与内置键冲突。中间件函数必须返回 Map无论是全局、API 级还是路径级middlewareConfigFn的返回值都会作为最终配置漏掉return会导致定制失效。类型提示TypeScript 项目中从wasp/server导入MiddlewareConfigFn类型即可获得完整的 Map 操作类型检查API 处理函数本身可从wasp/server/api导入对应类型如WebhookCallback。优先级顺序路径级命名空间中间件先于 API 级中间件执行鉴权中间件如启用位于 API 级定制中间件之前确保先鉴权、再进入业务定制逻辑。通过合理组合全局、API 级与路径级三个定制入口你可以在不改动 Wasp 框架本身的前提下精确控制每一个路由的中间件行为——无论是扩展 CORS 域名、为 Webhook 换用原始请求体解析还是给整组 API 统一注入自定义处理逻辑。【免费下载链接】waspThe batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex full-stack features like auth, background jobs, RPC, email sending, end-to-end type safety, single-command deployment, and more.项目地址: https://gitcode.com/GitHub_Trending/wa/wasp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考