3d521973ab
Deploy Server / deploy-server (push) Successful in 2m56s
usercenter(app.yanmeiai.com,浏览器)跨域调控制面 API 会被浏览器拦(无 CORS 头)。 加白名单 CORS 中间件(CORS_ORIGINS,缺省 app.yanmeiai.com + pages.dev),应答 OPTIONS 预检。原生端非浏览器不受影响。Bearer 认证故不需 Allow-Credentials。含 3 项测试。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
48 lines
1.4 KiB
Go
48 lines
1.4 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
func TestCORS(t *testing.T) {
|
|
t.Setenv("CORS_ORIGINS", "https://app.yanmeiai.com")
|
|
mw := NewCORS()
|
|
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) })
|
|
h := mw(next)
|
|
|
|
// 允许的 Origin:补 Allow-Origin,普通请求继续。
|
|
r := httptest.NewRequest("POST", "/v1/auth/login", nil)
|
|
r.Header.Set("Origin", "https://app.yanmeiai.com")
|
|
w := httptest.NewRecorder()
|
|
h.ServeHTTP(w, r)
|
|
if got := w.Header().Get("Access-Control-Allow-Origin"); got != "https://app.yanmeiai.com" {
|
|
t.Fatalf("allowed origin: want header, got %q", got)
|
|
}
|
|
if w.Code != 200 {
|
|
t.Fatalf("non-preflight should reach next, got %d", w.Code)
|
|
}
|
|
|
|
// OPTIONS 预检:204,不落到业务。
|
|
r = httptest.NewRequest("OPTIONS", "/v1/auth/login", nil)
|
|
r.Header.Set("Origin", "https://app.yanmeiai.com")
|
|
w = httptest.NewRecorder()
|
|
h.ServeHTTP(w, r)
|
|
if w.Code != http.StatusNoContent {
|
|
t.Fatalf("preflight: want 204, got %d", w.Code)
|
|
}
|
|
if w.Header().Get("Access-Control-Allow-Methods") == "" {
|
|
t.Fatalf("preflight missing Allow-Methods")
|
|
}
|
|
|
|
// 未白名单 Origin:不补 Allow-Origin。
|
|
r = httptest.NewRequest("POST", "/v1/auth/login", nil)
|
|
r.Header.Set("Origin", "https://evil.example.com")
|
|
w = httptest.NewRecorder()
|
|
h.ServeHTTP(w, r)
|
|
if got := w.Header().Get("Access-Control-Allow-Origin"); got != "" {
|
|
t.Fatalf("disallowed origin should get no header, got %q", got)
|
|
}
|
|
}
|