fix: expose plugin support header for CORS

This commit is contained in:
LTbinglingfeng
2026-06-13 05:53:19 +08:00
parent c006e672f8
commit 2659e490a8
2 changed files with 42 additions and 0 deletions

View File

@@ -50,6 +50,17 @@ import (
const oauthCallbackSuccessHTML = `<html><head><meta charset="utf-8"><title>Authentication successful</title><script>setTimeout(function(){window.close();},5000);</script></head><body><h1>Authentication successful!</h1><p>You can close this window.</p><p>This window will close automatically in 5 seconds.</p></body></html>`
var corsExposedResponseHeaders = []string{
"X-CPA-VERSION",
"X-CPA-COMMIT",
"X-CPA-BUILD-DATE",
"X-CPA-SUPPORT-PLUGIN",
"X-CPA-HOME-VERSION",
"X-CPA-HOME-BUILD-DATE",
"X-SERVER-VERSION",
"X-SERVER-BUILD-DATE",
}
type serverOptionConfig struct {
extraMiddleware []gin.HandlerFunc
engineConfigurator func(*gin.Engine)
@@ -1466,6 +1477,7 @@ func corsMiddleware() gin.HandlerFunc {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
c.Header("Access-Control-Allow-Headers", "*")
c.Header("Access-Control-Expose-Headers", strings.Join(corsExposedResponseHeaders, ", "))
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent)

View File

@@ -92,6 +92,36 @@ func TestHealthz(t *testing.T) {
})
}
func TestManagementResponseExposesPluginSupportHeaderForCORS(t *testing.T) {
t.Setenv("MANAGEMENT_PASSWORD", "test-management-key")
server := newTestServer(t)
req := httptest.NewRequest(http.MethodGet, "/v0/management/config", nil)
req.Header.Set("Origin", "http://127.0.0.1:5173")
rr := httptest.NewRecorder()
server.engine.ServeHTTP(rr, req)
if rr.Code != http.StatusUnauthorized {
t.Fatalf("status = %d, want %d body=%s", rr.Code, http.StatusUnauthorized, rr.Body.String())
}
if got := rr.Header().Get("X-CPA-SUPPORT-PLUGIN"); got != pluginhost.SupportPluginHeaderValue() {
t.Fatalf("X-CPA-SUPPORT-PLUGIN = %q, want %q", got, pluginhost.SupportPluginHeaderValue())
}
exposedHeaders := make(map[string]struct{})
for _, headerName := range strings.Split(rr.Header().Get("Access-Control-Expose-Headers"), ",") {
headerName = strings.ToLower(strings.TrimSpace(headerName))
if headerName != "" {
exposedHeaders[headerName] = struct{}{}
}
}
for _, headerName := range corsExposedResponseHeaders {
if _, ok := exposedHeaders[strings.ToLower(headerName)]; !ok {
t.Fatalf("Access-Control-Expose-Headers missing %s: %q", headerName, rr.Header().Get("Access-Control-Expose-Headers"))
}
}
}
func TestNewServerWithPluginHostInjectsHandlerInterceptors(t *testing.T) {
host := pluginhost.New()
server := newTestServerWithOptions(t, WithPluginHost(host))