Files
ghproxy/regex_test.go
T
Geekertao-botandGeekertao-bot d18983e23d feat: 支持代理 GitHub 资源 CDN 直链(release-assets / codeload / objects / media) (#1)
* feat: 支持代理 GitHub 资源 CDN 直链(release-assets / codeload / objects / media)

与 CF 版 hubporg/CF-GitHub-Proxy#3 同一套逻辑:GitHub 域名链接仍在服务端内部
跟随跳转并返回文件内容,新增的 CDN 主机直链则直接代理。

改动要点:
1. exps 拆分为 entryExps(入口链接)与 assetExps(资源 CDN),exps 为二者拼接
2. handler 中 exps[1] 改为显式引用 entryExps[1],避免拼接后索引语义漂移
3. proxy 的 Location 分支改用 isEntryURL:只有入口链接才重写为代理地址,
   CDN 跳转在服务端内部跟随,客户端不会看到真实文件地址
4. 新增 isEntryURL

修复前:资源 CDN 直链(release-assets / codeload 等)返回 404。

* test: 补充 CDN 主机匹配与入口判定的单元测试

覆盖两处关键行为:
- checkURL 命中新增的 CDN 主机(release-assets / objects / github-releases /
  codeload / media),并拒绝非 GitHub 域名与形似域名(如 github.com.evil.com)
- isEntryURL 只命中入口链接,CDN 主机一律不命中——这是避免 302 被重写、
  从而把真实文件地址暴露给客户端的关键约束

(可选提交,如不需要可直接丢弃。)

---------

Co-authored-by: Geekertao-bot <254965144+Geekertao-bot@users.noreply.github.com>
2026-09-12 01:41:54 +08:00

62 lines
2.1 KiB
Go

package main
import "testing"
func TestCheckURL(t *testing.T) {
shouldMatch := []string{
"https://release-assets.githubusercontent.com/github-production-release-asset/1/abc?sig=x",
"https://objects.githubusercontent.com/foo/bar",
"https://github-releases.githubusercontent.com/foo/bar",
"https://codeload.github.com/cli/cli/tar.gz/refs/tags/v1",
"https://media.githubusercontent.com/media/octocat/Hello-World/master/README",
"https://media.githubusercontent.com/octocat/Hello-World/master/README",
"https://github.com/a/b/releases/download/v1/x.zip",
"https://raw.githubusercontent.com/a/b/main/c.txt",
"https://api.github.com/repos/a/b",
}
for _, u := range shouldMatch {
if checkURL(u) == nil {
t.Errorf("checkURL 应命中但未命中: %s", u)
}
}
shouldNotMatch := []string{
"https://evil.example.com/a.zip",
"https://example.com/",
"https://github.com.evil.com/a/b",
"https://notcodeload.github.com/a/b",
}
for _, u := range shouldNotMatch {
if checkURL(u) != nil {
t.Errorf("checkURL 不应命中但命中了: %s", u)
}
}
}
func TestIsEntryURL(t *testing.T) {
// 入口:只有这些才允许重写 Location 返回客户端
entry := []string{
"https://github.com/a/b/releases/download/v1/x.zip",
"https://raw.githubusercontent.com/a/b/main/c.txt",
"https://gist.githubusercontent.com/u/1/raw/x.py",
"https://api.github.com/repos/a/b",
}
for _, u := range entry {
if !isEntryURL(u) {
t.Errorf("isEntryURL 应命中: %s", u)
}
}
// 非入口:资源 CDN 必须在服务端内部跟随,不能重写给客户端
notEntry := []string{
"https://release-assets.githubusercontent.com/github-production-release-asset/1/abc?sig=x",
"https://objects.githubusercontent.com/foo/bar",
"https://github-releases.githubusercontent.com/foo/bar",
"https://codeload.github.com/cli/cli/tar.gz/refs/tags/v1",
"https://media.githubusercontent.com/media/octocat/Hello-World/master/README",
}
for _, u := range notEntry {
if isEntryURL(u) {
t.Errorf("isEntryURL 不应命中(否则会泄露真实文件地址): %s", u)
}
}
}