ADR-008: Standardized HTTP Response Handlers¶
Last Updated: 2026-03-07
Status: Accepted
Overview¶
This ADR documents the decision to standardize all HTTP response handling in cortex-api using centralized helper functions, replacing scattered http.Error and json.NewEncoder calls throughout the codebase.
Context¶
Problem Statement¶
The cortex-api codebase had accumulated significant technical debt:
- 105+ json.NewEncoder(w).Encode() calls scattered across 66 handlers
- 50+ http.Error() calls with inconsistent error formatting
- No standard error response structure
- Duplicate code for setting Content-Type headers
- Difficult to maintain consistent API behavior
Impact¶
- Inconsistent API responses - Some errors returned plain text, others returned JSON
- Developer friction - Each handler reimplemented the same boilerplate
- Testing difficulty - No single point to mock or validate response behavior
- Observability gaps - No centralized logging for response errors
Decision¶
Create Centralized Response Helpers¶
Implemented in cortex-api/http_helpers.go:
// Success responses
func respondJSON(w http.ResponseWriter, status int, data interface{})
func respondOK(w http.ResponseWriter, data interface{})
func respondCreated(w http.ResponseWriter, data interface{})
// Error responses (consistent JSON structure)
func respondError(w http.ResponseWriter, status int, message string)
func respondBadRequest(w http.ResponseWriter, message string)
func respondUnauthorized(w http.ResponseWriter, message string)
func respondForbidden(w http.ResponseWriter, message string)
func respondNotFound(w http.ResponseWriter, message string)
func respondInternalError(w http.ResponseWriter, message string)
func respondServiceUnavailable(w http.ResponseWriter, message string)
// Request helpers
func decodeJSON(w http.ResponseWriter, r *http.Request, dst interface{}) bool
func requireField(w http.ResponseWriter, value, fieldName string) bool
Standard Error Format¶
All error responses now return:
Migration Scope¶
Migrated 18 files in cortex-api:
- ab_testing.go, agent.go, auth_middleware.go, cloud_llm.go
- conversation.go, cost_tracking.go, doc_uri_resolver.go
- eval_suite.go, evaluation.go, experiment_outcomes.go
- experiment_proposals.go, feedback.go, fim_completions.go
- flywheel.go, main.go, mcp_server.go, portal_auth.go
- runner_loop.go
Consequences¶
Positive¶
- Consistent API behavior - All endpoints return the same error structure
- Reduced boilerplate - Handlers are cleaner and more focused on business logic
- Single point of change - Modifying response behavior requires editing one file
- Better testability - Can mock response helpers for unit tests
- Future extensibility - Easy to add logging, metrics, or tracing
Negative¶
- Migration effort - Required updating all existing handlers
- Learning curve - Developers need to know the helper functions
Exceptions¶
- MCP Server JSON-RPC -
mcp_server.goretains 2 directjson.NewEncodercalls for JSON-RPC protocol compliance (different response structure required)
Metrics¶
| Metric | Before | After |
|---|---|---|
http.Error calls |
50+ | 0 |
json.NewEncoder(w).Encode calls |
105+ | 2 (MCP only) |
| Helper functions | 0 | 12 |
| Files with response helpers | 0 | 18 |