diff --git a/docs/guides/overrides.md b/docs/guides/overrides.md index 0c7d78df13..c022a5415d 100644 --- a/docs/guides/overrides.md +++ b/docs/guides/overrides.md @@ -197,7 +197,7 @@ Result: } ``` -**Response (200 OK):** +**Response (202 Accepted):** Returns success with no body. **Response (400 Bad Request):** diff --git a/pkg/overrides/api.go b/pkg/overrides/api.go index bbbea84dd5..2ff3eba890 100644 --- a/pkg/overrides/api.go +++ b/pkg/overrides/api.go @@ -71,12 +71,18 @@ func (a *API) GetOverrides(w http.ResponseWriter, r *http.Request) { http.Error(w, "not found", http.StatusNotFound) return } - w.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(w).Encode(overrides); err != nil { + + // Buffer the response before writing headers so http.Error works if encoding fails + var buf bytes.Buffer + if err := json.NewEncoder(&buf).Encode(overrides); err != nil { level.Error(a.logger).Log("msg", "failed to encode overrides response", "err", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } + w.Header().Set("Content-Type", "application/json") + if _, err := w.Write(buf.Bytes()); err != nil { + level.Error(a.logger).Log("msg", "failed to write overrides response", "err", err) + } } // SetOverrides updates overrides for a specific tenant @@ -122,7 +128,7 @@ func (a *API) SetOverrides(w http.ResponseWriter, r *http.Request) { return } - w.WriteHeader(http.StatusOK) + w.WriteHeader(http.StatusAccepted) } // DeleteOverrides removes tenant-specific overrides diff --git a/pkg/overrides/overrides_test.go b/pkg/overrides/overrides_test.go index 3cc505855c..50421f6a05 100644 --- a/pkg/overrides/overrides_test.go +++ b/pkg/overrides/overrides_test.go @@ -234,7 +234,7 @@ func TestAPIEndpoints(t *testing.T) { path: "/api/v1/user-overrides", tenantID: "user789", requestBody: map[string]any{"ingestion_rate": 5000, "ruler_max_rules_per_rule_group": 10}, - expectedStatus: http.StatusOK, + expectedStatus: http.StatusAccepted, setupMock: func(mock *bucket.ClientMock) { // Mock runtime config with allowed limits runtimeConfig := `overrides: @@ -288,7 +288,7 @@ api_allowed_limits: path: "/api/v1/user-overrides", tenantID: "user888", requestBody: map[string]any{"ingestion_rate": 8000}, // Only update ingestion_rate - expectedStatus: http.StatusOK, + expectedStatus: http.StatusAccepted, setupMock: func(m *bucket.ClientMock) { // Mock runtime config with existing overrides for user888 initialConfig := `overrides: