History

fix: expose plugin support header for CORS

LTbinglingfeng committed 5 months ago

Commit 2659e491 parent c006e672 files · +42 −0Browse files

Unified · Split

2 files
  1. internal/api/server.go +12 −0
  2. internal/api/server_test.go +30 −0
internal/api/server.go+12−0
@@ -50,6 +50,17 @@ import ( · 49 unmodified lines
5050
5151 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>`
5252
53+var corsExposedResponseHeaders = []string{
54+ "X-CPA-VERSION",
55+ "X-CPA-COMMIT",
56+ "X-CPA-BUILD-DATE",
57+ "X-CPA-SUPPORT-PLUGIN",
58+ "X-CPA-HOME-VERSION",
59+ "X-CPA-HOME-BUILD-DATE",
60+ "X-SERVER-VERSION",
61+ "X-SERVER-BUILD-DATE",
62+}
63+
5364 type serverOptionConfig struct {
5465 extraMiddleware []gin.HandlerFunc
5566 engineConfigurator func(*gin.Engine)
@@ -1466,6 +1477,7 @@ func corsMiddleware() gin.HandlerFunc { · 1410 unmodified lines
14661477 c.Header("Access-Control-Allow-Origin", "*")
14671478 c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
14681479 c.Header("Access-Control-Allow-Headers", "*")
1480+ c.Header("Access-Control-Expose-Headers", strings.Join(corsExposedResponseHeaders, ", "))
14691481
14701482 if c.Request.Method == "OPTIONS" {
14711483 c.AbortWithStatus(http.StatusNoContent)
internal/api/server_test.go+30−0
@@ -92,6 +92,36 @@ func TestHealthz(t *testing.T) { · 91 unmodified lines
9292 })
9393 }
9494
95+func TestManagementResponseExposesPluginSupportHeaderForCORS(t *testing.T) {
96+ t.Setenv("MANAGEMENT_PASSWORD", "test-management-key")
97+
98+ server := newTestServer(t)
99+ req := httptest.NewRequest(http.MethodGet, "/v0/management/config", nil)
100+ req.Header.Set("Origin", "http://127.0.0.1:5173")
101+ rr := httptest.NewRecorder()
102+ server.engine.ServeHTTP(rr, req)
103+
104+ if rr.Code != http.StatusUnauthorized {
105+ t.Fatalf("status = %d, want %d body=%s", rr.Code, http.StatusUnauthorized, rr.Body.String())
106+ }
107+ if got := rr.Header().Get("X-CPA-SUPPORT-PLUGIN"); got != pluginhost.SupportPluginHeaderValue() {
108+ t.Fatalf("X-CPA-SUPPORT-PLUGIN = %q, want %q", got, pluginhost.SupportPluginHeaderValue())
109+ }
110+
111+ exposedHeaders := make(map[string]struct{})
112+ for _, headerName := range strings.Split(rr.Header().Get("Access-Control-Expose-Headers"), ",") {
113+ headerName = strings.ToLower(strings.TrimSpace(headerName))
114+ if headerName != "" {
115+ exposedHeaders[headerName] = struct{}{}
116+ }
117+ }
118+ for _, headerName := range corsExposedResponseHeaders {
119+ if _, ok := exposedHeaders[strings.ToLower(headerName)]; !ok {
120+ t.Fatalf("Access-Control-Expose-Headers missing %s: %q", headerName, rr.Header().Get("Access-Control-Expose-Headers"))
121+ }
122+ }
123+}
124+
95125 func TestNewServerWithPluginHostInjectsHandlerInterceptors(t *testing.T) {
96126 host := pluginhost.New()
97127 server := newTestServerWithOptions(t, WithPluginHost(host))