Skip to content

GET/DELETE /packages/:id 把重复的 ?version= 查询参数(string[])原样交给 PackageService #6307

Description

@qq9340100

观察类发现,来自 #5822(PR #6303)的实现过程,按 Prime Directive #10 单独立单。未认领
今天没有用户会撞到:需要客户端重复传同一个查询参数才会触发。

事实

IHttpRequest.query 的契约是 Record<string, string | string[]>(packages/spec/src/contracts/http-server.ts),
即重复的查询参数会是数组。package-routes.ts 的两个 handler 直接把它当字符串用:

  • GET /api/v1/packages/:idconst version = req.query?.version || 'latest'; … packageService.get(packageId, version)
  • DELETE /api/v1/packages/:idconst version = req.query?.version; … packageService.delete(packageId, version)

PackageService.get/delete 的形参是 version?: string。所以 ?version=a&version=b 会把
['a','b'] 交给服务层,查询按一个不存在的版本走(或按适配器的字符串化行为走),
DELETE 还会因为 version 为真而跳过 protocol.deletePackage 的完整卸载分支
(if (!version && typeof options.protocol?.deletePackage === 'function'),退化成窄语义的版本删除。

为什么没有被门禁抓到

tsc --noEmit -p packages/rest/tsconfig.json 确实报这两条:

src/package-routes.ts(178,55): error TS2345: Argument of type 'string | string[]' is not assignable to parameter of type 'string | undefined'.
src/package-routes.ts(245,61): error TS2345: Argument of type 'string | string[]' is not assignable to parameter of type 'string | undefined'.

(行号为 origin/main@f6609e6ae;PR #6303 之后同两个调用点在 207/279。)

packages/rest 没有 typecheck 脚本 —— 它是 scripts/check-type-check-coverage.mjs
的 DEBT 条目(#4311,457 条冻结原始错误之二),所以 CI 里没有任何 job 编译它,vitest 与 tsup
也都不做类型检查。这两条属于该冻结计数,不是新引入的;本单记的是它们背后具体的运行时行为

处置建议(留给分诊)

窄修:在两个 handler 里按契约取第一个值(或明确拒收数组,400 MISSING_REQUIRED_FIELD 家族),
让类型与运行时一致 —— 注意这属于 consumer 侧的入参规范化,不是给 off-spec 输入加宽容别名:
契约本来就说这里可能是数组,是消费方没有处理声明过的形状。

顺带值得问的:同一形状在 rest 其他读 req.query.* 的地方是否也存在(未逐一排查,本单不扩大范围)。

查重

open issue 搜过 packages/rest + query / version / TS2345,无同题单。
#4311 是类型检查覆盖率的总账(计数已含这两条),本单是其中一条的行为面,非重复。

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions