fix(api): resolve :owner/:repo and --var placeholders in single calls #254

Merged
wbtiger merged 1 commits from luwanzhou/gitlink-cli:fix/api-owner-repo-placeholders into master 2026-07-14 20:44:17 +08:00
Contributor

问题描述

gitlink-cli api <METHOD> <PATH>单次调用时,会把 <PATH> 原样发送给服务端,不会替换 REST 风格的 :owner / :repo 占位符

  • 现象:执行 gitlink-cli api GET /:owner/:repo/commits 时,字面量 :owner:repo 被直接拼进请求 URL,服务端返回 404 / 资源不存在。
  • 影响
    1. 该命令自身的帮助 Exampleapi POST /:owner/:repo/issues)就是跑不通的;
    2. 文档与 Skill 中大量使用的 :owner/:repo 写法(如 api GET /:owner/:repo/commits)全部失效;
    3. 占位符替换能力此前只存在于 --batch-file 批处理模式{{var}} 模板)中,单次调用无法复用,体验割裂。

问题复现步骤

  1. 安装并登录:gitlink-cli auth login

  2. 执行单次 api 调用(任意有效仓库):

    gitlink-cli api GET /:owner/:repo/commits --owner Gitlink --repo gitlink-cli
    
  3. 实际请求被发往 .../api/:owner/:repo/commits.json(字面 :owner 未替换),返回 404 / 资源不存在;而非预期的提交列表。

同样地,gitlink-cli api POST /:owner/:repo/issues --body '...'(即命令自带的 Example)也无法工作。

根本原因

cmd/api/api.gorunAPI()(单次调用路径)直接使用原始参数,没有任何占位符解析:

method := strings.ToUpper(args[0])
path := args[1]                 // ← 原样使用,未替换 :owner/:repo,未渲染 {{var}}
if !strings.HasPrefix(path, "/") { path = "/" + path }

占位符替换逻辑只实现在 runAPIBatch()renderTemplate(){{var}} 模板)里,单次调用完全没有走任何解析;而 :owner/:repo 这种 REST 风格占位符在单次/批处理两条路径里都没有被处理。

修复方案

cmd/api/api.go 新增 resolveAPIPath(),让单次调用按以下顺序处理路径,并在 runAPI() 中调用:

  1. {{var}} 模板渲染:若提供 --var key=value,复用与批处理模式相同的 parseBatchVars + renderTemplate 渲染 {{key}},缺失变量时报错(与批处理语义一致)。
  2. :owner / :repo 占位符替换:当路径包含 :owner / :repo 时,使用与所有 shortcut 一致internal/context.ResolveOwnerRepo(--owner/--repo → git remote origin) 解析仓库归属并替换;无法解析时给出明确错误提示。
  3. 保留原有「缺失前导 / 自动补全」。

实现要点:

  • :owner / :repo 用正则 :owner\b / :repo\b\b 词边界避免误伤 :owner_id 等更长 token;
  • ReplaceAllLiteralString 替换,避免 owner/repo 名中的 $ 被当作正则替换引用;
  • 复用既有 parseBatchVars / renderTemplatecmd/api/batch.go)与 internal/context.ResolveOwnerRepo无新增依赖
  • 不含占位符、且未传 --var 的调用(如 api GET /users/me)行为完全不变

合并请求描述

本 PR 修复 gitlink-cli api 单次调用不替换 :owner/:repo 占位符的问题,并顺带让单次调用支持 --var{{var}} 模板渲染,使单次调用与批处理模式在占位符能力上保持一致;同时修正了命令自带的、原本无法运行的帮助示例。

相关Issue

关联Issue编号:#144171

变更内容

1. 修复 :owner/:repo 占位符未替换(cmd/api/api.go

  • 新增 resolveAPIPath(){{var}} 渲染 → :owner/:repo 解析替换 → 前导 / 补全。
  • 新增 apiOwnerPlaceholder / apiRepoPlaceholder 正则(\b 边界)。
  • runAPI() 改为调用 resolveAPIPath()

2. 增强:单次调用支持 --var 模板

  • 单次调用现在也能用 --var key=value 渲染路径中的 {{key}},与批处理模式语义统一。

3. 文档:更新命令 Example

  • 新增 api GET /:owner/:repo/commits --owner Gitlink --repo gitlink-cli
  • 新增 api GET /v1/{{owner}}/gitlink-cli/issues --var owner=Gitlink

4. 测试(cmd/api/api_test.go

  • 新增::owner/:repo 解析替换、单次调用 {{var}} 渲染、缺失模板变量报错。
  • 既有 api 测试全部通过。

5. 变更说明(doc/changes/api-path-placeholders.md

测试与验证

  • go build ./...go vet ./...go test ./...gofmt -s 全部通过。
  • 真实 API 端到端验证(源码 build 后):
    • api GET /:owner/:repo/commits --owner Gitlink --repo gitlink-cli → 正常返回提交列表(不再发送字面 :owner)。
    • api GET /v1/{{owner}}/gitlink-cli --var owner=Gitlink → 正常返回仓库详情。
## 问题描述 `gitlink-cli api <METHOD> <PATH>` 在**单次调用**时,会把 `<PATH>` 原样发送给服务端,**不会替换 REST 风格的 `:owner` / `:repo` 占位符**。 - **现象**:执行 `gitlink-cli api GET /:owner/:repo/commits` 时,字面量 `:owner`、`:repo` 被直接拼进请求 URL,服务端返回 404 / 资源不存在。 - **影响**: 1. 该命令**自身的帮助 `Example`**(`api POST /:owner/:repo/issues`)就是跑不通的; 2. 文档与 Skill 中大量使用的 `:owner/:repo` 写法(如 `api GET /:owner/:repo/commits`)全部失效; 3. 占位符替换能力此前**只存在于 `--batch-file` 批处理模式**(`{{var}}` 模板)中,单次调用无法复用,体验割裂。 ## 问题复现步骤 1. 安装并登录:`gitlink-cli auth login` 2. 执行单次 api 调用(任意有效仓库): ```bash gitlink-cli api GET /:owner/:repo/commits --owner Gitlink --repo gitlink-cli ``` 3. 实际请求被发往 `.../api/:owner/:repo/commits.json`(字面 `:owner` 未替换),返回 404 / 资源不存在;而非预期的提交列表。 > 同样地,`gitlink-cli api POST /:owner/:repo/issues --body '...'`(即命令自带的 Example)也无法工作。 ## 根本原因 `cmd/api/api.go` 的 `runAPI()`(单次调用路径)直接使用原始参数,没有任何占位符解析: ```go method := strings.ToUpper(args[0]) path := args[1] // ← 原样使用,未替换 :owner/:repo,未渲染 {{var}} if !strings.HasPrefix(path, "/") { path = "/" + path } ``` 占位符替换逻辑只实现在 `runAPIBatch()` 的 `renderTemplate()`(`{{var}}` 模板)里,单次调用完全没有走任何解析;而 `:owner/:repo` 这种 REST 风格占位符在单次/批处理两条路径里都没有被处理。 ## 修复方案 在 `cmd/api/api.go` 新增 `resolveAPIPath()`,让单次调用按以下顺序处理路径,并在 `runAPI()` 中调用: 1. **`{{var}}` 模板渲染**:若提供 `--var key=value`,复用与批处理模式相同的 `parseBatchVars` + `renderTemplate` 渲染 `{{key}}`,缺失变量时报错(与批处理语义一致)。 2. **`:owner` / `:repo` 占位符替换**:当路径包含 `:owner` / `:repo` 时,使用与**所有 shortcut 一致**的 `internal/context.ResolveOwnerRepo(--owner/--repo → git remote origin)` 解析仓库归属并替换;无法解析时给出明确错误提示。 3. 保留原有「缺失前导 `/` 自动补全」。 实现要点: - `:owner` / `:repo` 用正则 `:owner\b` / `:repo\b`,`\b` 词边界避免误伤 `:owner_id` 等更长 token; - 用 `ReplaceAllLiteralString` 替换,避免 owner/repo 名中的 `$` 被当作正则替换引用; - 复用既有 `parseBatchVars` / `renderTemplate`(`cmd/api/batch.go`)与 `internal/context.ResolveOwnerRepo`,**无新增依赖**; - 不含占位符、且未传 `--var` 的调用(如 `api GET /users/me`)行为**完全不变**。 ## 合并请求描述 本 PR 修复 `gitlink-cli api` 单次调用不替换 `:owner/:repo` 占位符的问题,并顺带让单次调用支持 `--var` 的 `{{var}}` 模板渲染,使单次调用与批处理模式在占位符能力上保持一致;同时修正了命令自带的、原本无法运行的帮助示例。 ## 相关Issue 关联Issue编号:#144171 ## 变更内容 ### 1. 修复 `:owner/:repo` 占位符未替换(`cmd/api/api.go`) - 新增 `resolveAPIPath()`:`{{var}}` 渲染 → `:owner/:repo` 解析替换 → 前导 `/` 补全。 - 新增 `apiOwnerPlaceholder` / `apiRepoPlaceholder` 正则(`\b` 边界)。 - `runAPI()` 改为调用 `resolveAPIPath()`。 ### 2. 增强:单次调用支持 `--var` 模板 - 单次调用现在也能用 `--var key=value` 渲染路径中的 `{{key}}`,与批处理模式语义统一。 ### 3. 文档:更新命令 `Example` - 新增 `api GET /:owner/:repo/commits --owner Gitlink --repo gitlink-cli` - 新增 `api GET /v1/{{owner}}/gitlink-cli/issues --var owner=Gitlink` ### 4. 测试(`cmd/api/api_test.go`) - 新增:`:owner/:repo` 解析替换、单次调用 `{{var}}` 渲染、缺失模板变量报错。 - 既有 api 测试全部通过。 ### 5. 变更说明(`doc/changes/api-path-placeholders.md`) ## 测试与验证 - `go build ./...`、`go vet ./...`、`go test ./...`、`gofmt -s` 全部通过。 - **真实 API 端到端验证**(源码 build 后): - `api GET /:owner/:repo/commits --owner Gitlink --repo gitlink-cli` → 正常返回提交列表(不再发送字面 `:owner`)。 - `api GET /v1/{{owner}}/gitlink-cli --var owner=Gitlink` → 正常返回仓库详情。
luwanzhou added 1 commit 2026-06-15 12:45:46 +08:00
81d30d6741 fix(api): resolve :owner/:repo and --var placeholders in single calls
gitlink-cli api <METHOD> <PATH> 单次调用此前直接发送原始路径,不替换
REST 风格的 :owner/:repo 占位符——导致该命令自身的 Example
(api POST /:owner/:repo/issues)以及依赖该写法的 Skill/文档无法使用。

- 新增 resolveAPIPath:先按 --var 渲染 {{var}} 模板(复用批处理模板引擎),
  再用 context.ResolveOwnerRepo(--owner/--repo → git remote,与所有 shortcut
  一致)替换 :owner/:repo,最后补全前导 /。
- :owner/:repo 正则用 \b 边界避免误伤 :owner_id;ReplaceAllLiteralString
  避免 owner/repo 中的 $ 被当作正则替换引用。
- 不含占位符且无 --var 的调用行为不变。
- 更新命令 Example;新增单元测试(占位符解析、单次 --var 渲染、缺失变量报错)。

修复 Issue: api 命令单次调用不替换 :owner/:repo 占位符。
wbtiger merged commit e5cf341d26 into master 2026-07-14 20:43:56 +08:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: Gitlink/gitlink-cli#254
No description provided.