package routers import ( "net/http" "net/http/httptest" "os" "path/filepath" "testing" "server/pkg/verifyfiles" beego "github.com/beego/beego/v2/server/web" ) // TestVerifyFilesEndToEnd 走真实 HTTP 链路验证: // 根路径下的验证文件能被吐出来,且不带白名单的路径仍然 404。 func TestVerifyFilesEndToEnd(t *testing.T) { dir := t.TempDir() if err := os.WriteFile(filepath.Join(dir, "1XXl8fPHr9.txt"), []byte("1XXl8fPHr9"), 0o644); err != nil { t.Fatalf("准备测试文件失败: %v", err) } // 注册到全局 beego(与线上 router.go 的注册方式一致) RegisterVerifyFiles(dir, "") beego.BeeApp.Handlers.Init() // 1) 验证文件正常返回 req := httptest.NewRequest(http.MethodGet, "/1XXl8fPHr9.txt", nil) req.Host = "api.yunzer.cn" rec := httptest.NewRecorder() beego.BeeApp.Handlers.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Fatalf("验证文件应返回 200,实际 %d", rec.Code) } if got := rec.Body.String(); got != "1XXl8fPHr9" { t.Fatalf("验证文件内容不对,实际 %q", got) } if ct := rec.Header().Get("Content-Type"); ct == "" || ct[:len("text/plain")] != "text/plain" { t.Logf("Content-Type: %s", ct) } // 2) 不存在的验证文件仍走正常路由(404),行为不变 req2 := httptest.NewRequest(http.MethodGet, "/not-exist-verify.txt", nil) req2.Host = "api.yunzer.cn" rec2 := httptest.NewRecorder() beego.BeeApp.Handlers.ServeHTTP(rec2, req2) if rec2.Code != http.StatusNotFound { t.Fatalf("不存在的验证文件应返回 404,实际 %d", rec2.Code) } } // TestAppRootFrom 确认服务根目录按「含 conf/app.conf 的目录」定位。 func TestAppRootFrom(t *testing.T) { root := t.TempDir() if err := os.MkdirAll(filepath.Join(root, "conf"), 0o755); err != nil { t.Fatalf("准备测试目录失败: %v", err) } if err := os.WriteFile(filepath.Join(root, "conf", "app.conf"), []byte("appname = server"), 0o644); err != nil { t.Fatalf("准备测试文件失败: %v", err) } other := t.TempDir() if got := appRootFrom([]string{other, root}); got != root { t.Fatalf("应定位到 %s,实际 %s", root, got) } if got := appRootFrom([]string{other, ""}); got != "" { t.Fatalf("没有 conf/app.conf 时应返回空串,实际 %s", got) } if got := appRootFrom([]string{""}); got != "" { t.Fatalf("空候选应返回空串,实际 %s", got) } } // TestDefaultDirResolvesToRepoVerifyDir 确认默认目录落在「服务根目录/verify」下, // 且仓库里的验证文件能被解析出来、内容正确。 // 线上等价:服务根目录 /www/wwwroot/api.yunzer.cn → verify/1XXl8fPHr9.txt。 func TestDefaultDirResolvesToRepoVerifyDir(t *testing.T) { orig, err := os.Getwd() if err != nil { t.Fatalf("取当前工作目录失败: %v", err) } defer os.Chdir(orig) // 切到 go/ 目录:这里有 conf/app.conf,等价于线上服务根目录 goRoot := filepath.Dir(orig) if err := os.Chdir(goRoot); err != nil { t.Fatalf("切换工作目录失败: %v", err) } root := appRoot() if root == "" { t.Fatalf("应能从 conf/app.conf 定位服务根目录(工作目录 %s)", goRoot) } dir := filepath.Join(root, verifyfiles.DefaultDir) resolver, err := verifyfiles.New(verifyfiles.Config{Dir: dir}) if err != nil || resolver == nil { t.Fatalf("创建 Resolver 失败: %v", err) } full, ok := resolver.Resolve("/1XXl8fPHr9.txt") if !ok { t.Fatalf("默认目录 %s 下应能解析出验证文件", dir) } b, err := os.ReadFile(full) if err != nil { t.Fatalf("读取验证文件失败: %v", err) } if string(b) != "1XXl8fPHr9" { t.Fatalf("验证文件内容不对,实际 %q", string(b)) } }