Skip to content

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

  1. Inconsistent API responses - Some errors returned plain text, others returned JSON
  2. Developer friction - Each handler reimplemented the same boilerplate
  3. Testing difficulty - No single point to mock or validate response behavior
  4. 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:

{"error": "descriptive message"}

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

  1. Consistent API behavior - All endpoints return the same error structure
  2. Reduced boilerplate - Handlers are cleaner and more focused on business logic
  3. Single point of change - Modifying response behavior requires editing one file
  4. Better testability - Can mock response helpers for unit tests
  5. Future extensibility - Easy to add logging, metrics, or tracing

Negative

  1. Migration effort - Required updating all existing handlers
  2. Learning curve - Developers need to know the helper functions

Exceptions

  • MCP Server JSON-RPC - mcp_server.go retains 2 direct json.NewEncoder calls 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