diff --git a/server/internal/httpapi/cors.go b/server/internal/httpapi/cors.go index 752f046..56f4bac 100644 --- a/server/internal/httpapi/cors.go +++ b/server/internal/httpapi/cors.go @@ -35,7 +35,10 @@ func NewCORS() func(http.Handler) http.Handler { h.Set("Access-Control-Allow-Origin", origin) h.Add("Vary", "Origin") h.Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS") - h.Set("Access-Control-Allow-Headers", "Content-Type, Authorization") + // X-Refresh-Token:静默续期/登出把 refresh token 放在此自定义头里 + // (header token 方案,见 web/usercenter/lib/api/http.ts)。不放行则浏览器 + // 预检拦截 /v1/auth/refresh → 登录后一刷新即掉线(login 不带此头故不受影响)。 + h.Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Refresh-Token") h.Set("Access-Control-Max-Age", "600") } // 预检请求直接 204(不落到业务路由,避免 /v1/... 的 OPTIONS 404)。 diff --git a/server/internal/httpapi/cors_test.go b/server/internal/httpapi/cors_test.go index 78727f0..390f3c0 100644 --- a/server/internal/httpapi/cors_test.go +++ b/server/internal/httpapi/cors_test.go @@ -3,6 +3,7 @@ package httpapi import ( "net/http" "net/http/httptest" + "strings" "testing" ) @@ -35,6 +36,11 @@ func TestCORS(t *testing.T) { if w.Header().Get("Access-Control-Allow-Methods") == "" { t.Fatalf("preflight missing Allow-Methods") } + // 静默续期/登出把 refresh token 放 X-Refresh-Token 头,必须在允许头里, + // 否则浏览器预检拦截 /v1/auth/refresh → 登录后一刷新即掉线。 + if ah := w.Header().Get("Access-Control-Allow-Headers"); !strings.Contains(ah, "X-Refresh-Token") { + t.Fatalf("preflight Allow-Headers must include X-Refresh-Token, got %q", ah) + } // 未白名单 Origin:不补 Allow-Origin。 r = httptest.NewRequest("POST", "/v1/auth/login", nil)