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
50 50
51const 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>`51const 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>`
52 52
53var 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
53type serverOptionConfig struct {64type serverOptionConfig struct {
54 extraMiddleware []gin.HandlerFunc65 extraMiddleware []gin.HandlerFunc
55 engineConfigurator func(*gin.Engine)66 engineConfigurator func(*gin.Engine)
@@ -1466,6 +1477,7 @@ func corsMiddleware() gin.HandlerFunc { · 1410 unmodified lines
1466 c.Header("Access-Control-Allow-Origin", "*")1477 c.Header("Access-Control-Allow-Origin", "*")
1467 c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")1478 c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS")
1468 c.Header("Access-Control-Allow-Headers", "*")1479 c.Header("Access-Control-Allow-Headers", "*")
1480 c.Header("Access-Control-Expose-Headers", strings.Join(corsExposedResponseHeaders, ", "))
1469 1481
1470 if c.Request.Method == "OPTIONS" {1482 if c.Request.Method == "OPTIONS" {
1471 c.AbortWithStatus(http.StatusNoContent)1483 c.AbortWithStatus(http.StatusNoContent)
internal/api/server_test.go+30−0
@@ -92,6 +92,36 @@ func TestHealthz(t *testing.T) { · 91 unmodified lines
92 })92 })
93}93}
94 94
95func 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
95func TestNewServerWithPluginHostInjectsHandlerInterceptors(t *testing.T) {125func TestNewServerWithPluginHostInjectsHandlerInterceptors(t *testing.T) {
96 host := pluginhost.New()126 host := pluginhost.New()
97 server := newTestServerWithOptions(t, WithPluginHost(host))127 server := newTestServerWithOptions(t, WithPluginHost(host))