Skip to content

buildClearURL 丢弃 URL hash#46

Merged
Svtter merged 4 commits into
mainfrom
ralph/issue-11
May 13, 2026
Merged

buildClearURL 丢弃 URL hash#46
Svtter merged 4 commits into
mainfrom
ralph/issue-11

Conversation

@Svtter
Copy link
Copy Markdown
Contributor

@Svtter Svtter commented May 13, 2026

Problem

buildClearURL in internal/server/server.go:718 stripped the URL hash fragment when constructing redirect URLs. After removing a query parameter, the function returned only / or /?remaining=params, discarding any #fragment portion of the original URL. While hash fragments are not sent to the server in normal HTTP requests, they can appear when the server constructs redirect targets from the Referer header or similar sources.

Approach

Preserve u.Fragment through the redirect URL construction. The function now captures the fragment before stripping query params, then appends #fragment to the result in both code paths — when no query params remain (/#fragment) and when some remain (/?params#fragment). Cases where the fragment is empty are left unchanged.

The change is two conditional blocks in buildClearURL (internal/server/server.go:721-729), no other callers are affected.

Tests

Added TestBuildClearURL in internal/server/server_test.go covering seven table-driven cases:

  • no query, no fragment → /
  • removing the only param → /
  • removing one param keeps others → /?tag=foo
  • fragment preserved when removing last param → /#section
  • fragment preserved with remaining params → /?tag=foo#section
  • fragment preserved when key not present → /?tag=foo#section
  • fragment-only URL with no query params → /#section

Closes #11

Agent added 2 commits May 13, 2026 17:26
buildClearURL now preserves the #fragment portion of the original URL
when clearing query parameters, ensuring hash-based routing is not lost.

Closes #11
Address review feedback: add test for URL with only fragment
and no query params (/#section with removeKey=q) to verify
fragment is preserved when there are no query parameters.
@github-actions
Copy link
Copy Markdown

无遗漏

Issue #11 的 spec 范围清晰且局限:仅让 buildClearURL 保留 URL fragment,并提供 7 个表驱动测试用例。

实现完整覆盖了所有要求:

  • 函数实现:在 server.go:719 捕获 u.Fragment,在两个分支(无剩余参数 L721-723、有剩余参数 L726-728)均正确处理非空 fragment,空 fragment 保持原行为
  • 测试覆盖:TestBuildClearURL 中 7 个用例全部存在,与 PR body 列举的用例一一对应(无 query 无 fragment、仅剩一个参数、保留多个参数、无剩余参数保留 fragment、有剩余参数保留 fragment、key 不存在时保留 fragment、仅 fragment 无 query)
  • 调用点:buildClearURL 仅被 4 个清理链接调用(server.go:663-666),均使用 r.URL,集成无误
  • 未引入其他变更,scope 控制得当

New%20session%20-%202026-05-13T09%3A33%3A33.396Z
opencode session  |  github run

@github-actions
Copy link
Copy Markdown

所有测试通过,go vet 无问题,无回归。

可合并

总结

buildClearURL 现在可以保留 URL 的 hash fragment。改动简洁,7 条表格驱动测试覆盖了核心路径(无 fragment、有 fragment、有/无剩余 query params、key 不存在等场景)。所有测试通过,无 vet 警告,无回归。

阻塞项:无

建议项:

  1. Fragment 编码安全:当前使用字符串拼接 "/#" + fragment,若 fragment 含特殊字符(如 #?、空格)会生成畸形 URL。建议改用 (&url.URL{Path: "/", RawQuery: q.Encode(), Fragment: fragment}).String() 以利用 net/url 的标准编码。当前调用方均为 r.URL(HTTP 请求不含 fragment),因此仅为防御性改进。

New%20session%20-%202026-05-13T09%3A33%3A33.124Z
opencode session  |  github run

…arURL

Replace string concatenation with url.URL{}.String() to properly handle
special characters in URL fragments. Add test case for special character
encoding.
@github-actions
Copy link
Copy Markdown

无遗漏

Issue #11 的 spec 范围清晰且局限:仅让 buildClearURL 保留 URL fragment,并提供 7 个表驱动测试用例。

实现完整覆盖了所有要求:

  • 函数实现:使用 url.URL 结构体统一构造返回 URL,Fragment: u.Fragment 正确保留了 fragment,空 fragment 保持原行为
  • 测试覆盖:8 个测试用例完全覆盖 PR body 列出的 7 个场景(no fragment、fragment + 无剩余参数、fragment + 有剩余参数、key 不存在时保留 fragment、仅 fragment 无 query),外加 1 个额外特殊字符编码用例
  • 集成:函数签名不变,所有调用方(server.go:663-666)无需修改
  • 单分支重构:将原来的 if/else 双分支改为单个 url.URL{}.String() 调用,更简洁且不会遗漏 fragment。等价性已验证——空 fragment 和空 query 场景的行为与重构前完全一致

New%20session%20-%202026-05-13T09%3A39%3A35.816Z
opencode session  |  github run

@github-actions
Copy link
Copy Markdown

可合并

总结

该 PR 以 minimal 且正确的方式修复了 buildClearURL 丢弃 URL fragment 的问题:将字符串拼接替换为 url.URL{} 结构体构造,自然保留 u.Fragment。同时添加了 8 个表驱动测试用例覆盖正常路径、边界情况以及编码后的 fragment。所有测试通过,go vet 无警告,无回归。

阻塞项:无

建议项:

  1. buildPageURL 也可统一风格internal/server/server.go:726buildPageURL 仍使用 "/?" + q.Encode() 字符串拼接,虽然其语义(构造分页 URL)上 fragment 无实际意义,但为了一致性可考虑同样改用 url.URL{} 构造。此非阻塞,功能无影响。
  2. 测试中 fragment 编码用例可更激进:当前 "fragment with special characters encoded safely" 用例的输入 %20url.Parse 后会被解码为空格再重新编码,结果正确。如果要验证原始 fragment 保留行为,可考虑 #sec+tion(含 +)或 #sec#tion(含 literal #)等更边界的情况。

New%20session%20-%202026-05-13T09%3A39%3A28.940Z
opencode session  |  github run

@github-actions
Copy link
Copy Markdown

无遗漏

Issue #11 的 spec 范围极为局限:仅修复 buildClearURL 以保留 URL fragment。实现完整覆盖了所有要求:

  • buildClearURL:通过 url.URL{Fragment: u.Fragment} 正确保留了 fragment,两种路径(有/无剩余 query params)均正确处理,空 fragment 行为不变
  • buildPageURL:作为额外改进也添加了 Fragment: u.Fragment(超出 spec 要求,非遗漏)
  • 测试覆盖:8 个测试用例完全覆盖 PR body 列举的 7 个场景,另含额外编码安全测试
  • 集成:4 个调用点(server.go:663-666)均传入 r.URL,无需修改,函数签名不变

实现方式(url.URL{} 构造)虽与 PR body 描述的字符串拼接方式不同,但语义等价且更简洁安全,不属于遗漏。所有 spec 需求均已满足。

New%20session%20-%202026-05-13T09%3A54%3A53.801Z
opencode session  |  github run

@github-actions
Copy link
Copy Markdown

现在确认了实际的 PR diff(使用三点语法),仅有 internal/server/server.gointernal/server/server_test.go 两个文件的变更,不含 CLI 测试文件。

可合并

总结

PR 正确修复了 buildClearURL 丢弃 URL fragment 的问题,将字符串拼接重构为 url.URL{} 结构体构造以自动保留 u.Fragment。同时一致性地改进了 buildPageURL。测试充分(8 + 5 个表驱动用例),全部通过,go vet 无警告,无回归。

阻塞项:无

建议项:

  1. PR 描述未提及 buildPageURL 变更buildPageURL 被做了相同的 fragment 保留改造,但 PR title 和 body 只提到了 buildClearURL。虽然改动合理且一致,但建议在 PR 描述中补充说明,以保持文档与实际变更一致。
  2. buildPageURL fragment 保留的实际收益有限:HTTP 请求中 fragment 不会传给服务端,因此 r.URL.Fragment 通常为空。保留 fragment 的行为是正确的(防御性编程),但当前没有调用方会受益。可考虑在后续 PR 中评估是否有必要为分页 URL 保留 fragment。

New%20session%20-%202026-05-13T09%3A54%3A53.218Z
opencode session  |  github run

@Svtter Svtter merged commit 5e986ca into main May 13, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

buildClearURL 丢弃 URL hash

1 participant