Sushi SaaS 如何路由请求
了解 middleware 为用户和运营做了什么、为何组织选择保留在 URL 中,以及你可以修改哪些路由决策。
Sushi SaaS middleware 处理请求级上下文,不负责认证或业务授权。它的三项工作——语言路由、请求关联和组织上下文传递——都会产生用户可感知的行为,因此应该由你明确选择。
用户会感受到什么
- 页面通过
next-intl进入正确的本地化路由。 - 两个标签页可停留在两个不同 workspace,因为当前组织由
?org=<slug>表达,而非只存于 session。 - 分享账户链接时,链接本身会显示目标 workspace。
每个响应也包含 x-request-id,运营人员可把客服报告与结构化日志对应起来。API 请求跳过语言协商,但仍获得相同的请求与组织上下文。
实现见 7580470 的 src/middleware.ts。
Middleware 实际信任什么
页面请求的组织上下文来自 URL query parameter,调用者自行提供的组织 header 会被移除。API 请求中,共享 client 可以发送 x-organization-slug;若 URL 也提供值,则 URL 优先。
二者都不能直接授权。src/services/authz.ts 仍会证明登录用户属于目标组织,并拒绝多组织用户发起的模糊 API 请求。Middleware 只校验上下文是否适合传递。
只有符合长度与日志安全格式的外部 request ID 才会被接受,否则应用生成新的 UUID。这个 ID 会同时转发给路由并写入响应。
你可以做出的选择
语言路由
如果产品需要带 locale 的页面和语言检测,应保留 next-intl middleware。单语言产品可以移除这条分支,但应同时调整本地化路由、消息目录和测试;只移除一半契约通常会导致重定向与链接互相矛盾。
Workspace 选择
默认 query-string 模式能按标签页独立工作,也容易加到现有账户 URL。/acme/account 这类 path-based tenancy 层级更清晰,但需要修改链接生成、callback、matcher 与上下文解析。只用 session 虽然看似简单,两个标签页却可能覆盖同一个 active organization;只有接受这一行为时才适合。
请求追踪
几乎所有线上产品都应保留关联 ID。如果代理或可观测平台负责 trace ID,可以把可信值映射到日志契约中,或同时保留两者。不要让无限制的外部文本进入日志。
API 上下文
多 workspace 用户的 API 必须显式指定组织,能避免操作悄悄落入上一次活跃的租户。只有 API 确定是单租户时才应简化。
何时在 middleware 添加逻辑
只有必须在路由前运行、并且快速且 edge-compatible 的关注点才放在这里。成员检查、依赖数据库的授权、计费决策和其他业务规则应留在 service。
修改后测试本地化页面、/api 路由、静态资源、request ID 转发、异常上下文和双标签页切换。然后阅读架构与错误契约与组织与团队。