diff --git a/internal/daemon/controller/cors_test.go b/internal/daemon/controller/cors_test.go index 9c98881da5..55f9f364dd 100644 --- a/internal/daemon/controller/cors_test.go +++ b/internal/daemon/controller/cors_test.go @@ -265,6 +265,7 @@ func TestHandler_CORS(t *testing.T) { if req.Method == http.MethodOptions && c.code == http.StatusNoContent { assert.Equal(t, fmt.Sprintf("%s, %s, %s, %s, %s", http.MethodDelete, http.MethodGet, http.MethodOptions, http.MethodPost, http.MethodPatch), resp.HttpResponse().Header.Get("Access-Control-Allow-Methods")) assert.Equal(t, fmt.Sprintf("%s, %s, %s, %s", "Content-Type", "X-Requested-With", "Authorization", "X-Foobar"), resp.HttpResponse().Header.Get("Access-Control-Allow-Headers")) + assert.Equal(t, "Retry-After, RateLimit, RateLimit-Policy", resp.HttpResponse().Header.Get("Access-Control-Expose-Headers")) assert.Equal(t, "300", resp.HttpResponse().Header.Get("Access-Control-Max-Age")) } diff --git a/internal/daemon/controller/handler.go b/internal/daemon/controller/handler.go index 22bcce19bb..f8b1f277fa 100644 --- a/internal/daemon/controller/handler.go +++ b/internal/daemon/controller/handler.go @@ -499,6 +499,12 @@ func wrapHandlerWithCors(h http.Handler, props HandlerProperties) http.Handler { "Authorization", }, props.ListenerConfig.CorsAllowedHeaders...) + allowedResponseHeaders := strings.Join([]string{ + "Retry-After", + "RateLimit", + "RateLimit-Policy", + }, ", ") + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if props.ListenerConfig.CorsEnabled == nil || !*props.ListenerConfig.CorsEnabled { h.ServeHTTP(w, req) @@ -548,6 +554,7 @@ func wrapHandlerWithCors(h http.Handler, props HandlerProperties) http.Handler { w.Header().Set("Access-Control-Allow-Origin", origin) w.Header().Set("Vary", "Origin") + w.Header().Set("Access-Control-Expose-Headers", allowedResponseHeaders) // Apply headers for preflight requests if req.Method == http.MethodOptions {