Skip to content

fix(rest): register static data-action routes before greedy :object/:id#2315

Merged
os-zhuang merged 2 commits into
mainfrom
claude/suspicious-ptolemy-649160
Jun 25, 2026
Merged

fix(rest): register static data-action routes before greedy :object/:id#2315
os-zhuang merged 2 commits into
mainfrom
claude/suspicious-ptolemy-649160

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

问题

REST 路由器(RouteManagerIHttpServer/Express 适配器)按先注册先匹配(first-match-wins)工作,没有任何按具体性排序的逻辑(见 packages/rest/src/route-manager.ts:88,196)。

registerDataActionEndpoints(含 GET /data/:object/export)在 registerCrudEndpoints(含贪婪的 GET /data/:object/:id)之后注册,于是请求 GET /api/v1/data/<object>/export?format=csv 会先撞上 :object/:id,"export" 被当成一条记录的 id → 返回 404 RECORD_NOT_FOUND,根本到不了导出处理器。已对 rest@10.0.0 实证复现。

修复

registerDataActionEndpoints(bp) 调到 registerCrudEndpoints(bp) 之前注册,让静态字面量动作路由(/export/import/:id/clone 等)排在贪婪的 :object/:id 之前。沿用代码库已有惯例(/meta/:type/:name/references 先于 /meta/:type/:name,见 rest-server.ts:2140)。

为什么安全(两个方向都核对过)

按 HTTP 方法 + 段数穷举,first-match 下只有"同方法 + 同段数 + 字面量 vs :param"才会互相遮蔽:

方法 数据命名空间里的贪婪 :param 调换影响
GET :object/:id export 抢到 :id 前 = 修复目标;export 只精确匹配 /export 段,不会反向遮蔽真实 id
POST (克隆是更深的 :object/:id/clone) import/query/batch 等全是字面量,任何顺序都精确命中
PATCH / DELETE :object/:id ✅ DataAction 里没有同方法路由,不受影响
  • registerDataActionEndpoints没有任何贪婪 2 段 :object/:id 路由(只有字面量动作和更深的 :id/clone:id/shares),所以它先注册也吃不掉任何 CRUD 字面量路由。
  • enableCrud=false 时行为不变:export 的注册条件没动。

测试

  • 新增回归测试:断言 GET /export 的注册下标必须小于 GET /:object/:id。在修复前的顺序下该测试失败(export idx 61 不小于 :id idx 54),修复后通过。
  • packages/rest 全量 136 个测试通过

🤖 Generated with Claude Code

The REST router (RouteManager → IHttpServer/Express adapter) matches
first-registered-wins with no specificity sorting. registerDataActionEndpoints
(which holds GET /data/:object/export) ran AFTER registerCrudEndpoints (which
holds the greedy GET /data/:object/:id), so a request to
`GET /data/<object>/export` was captured by `:object/:id` — "export" treated as
a record id — returning 404 RECORD_NOT_FOUND instead of streaming the export.

Reorder so the static-literal action routes register before the greedy
:object/:id matcher, mirroring the existing /meta/:type/:name/references-before
-/meta/:type/:name convention. The reorder is safe in both directions:
registerDataActionEndpoints has no greedy 2-segment :object/:id routes, and the
only per-method collision in the data namespace is GET export vs GET :id.

Add a regression test asserting the export route's registration index precedes
the get-by-id route's.
@vercel

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 25, 2026 3:55am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/rest.

5 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/implementation-status.mdx (via @objectstack/rest)
  • content/docs/concepts/packages.mdx (via @objectstack/rest)
  • content/docs/guides/api-reference.mdx (via @objectstack/rest)
  • content/docs/guides/packages.mdx (via @objectstack/rest)
  • content/docs/guides/plugins.mdx (via @objectstack/rest)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tooling labels Jun 25, 2026
@os-zhuang
os-zhuang merged commit 9a810f8 into main Jun 25, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/suspicious-ptolemy-649160 branch June 25, 2026 05:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants