-
Notifications
You must be signed in to change notification settings - Fork 20
[duplicate-code] Duplicate Code Pattern: HTTP Error Response Format Inconsistency #2828
Description
Part of duplicate code analysis: #2825
Summary
The server package sends HTTP error responses in two incompatible formats depending on the code path. internal/server/auth.go uses http.Error() which emits a text/plain body, while internal/server/handlers.go uses writeJSONResponse() which emits application/json. Clients (including MCP SDK clients) that parse error bodies as JSON will receive an unparseable plain-text body when an auth error occurs.
Duplication Details
Pattern: Mixed HTTP error response formats
- Severity: Medium
- Occurrences: 4+ response-writing call-sites across 2 files
- Locations:
internal/server/auth.go~line 51 —http.Error(w, "Unauthorized: missing Authorization header", http.StatusUnauthorized)internal/server/auth.go~line 59 —http.Error(w, "Unauthorized: invalid API key", http.StatusUnauthorized)internal/server/handlers.go~line 51 —writeJSONResponse(w, http.StatusGone, map[string]interface{}{...})internal/server/handlers.go~line 63 —writeJSONResponse(w, http.StatusOK, map[string]interface{}{...})
Variant 1 — plain text (auth.go):
http.Error(w, "Unauthorized: missing Authorization header", http.StatusUnauthorized)
// Content-Type: text/plain; charset=utf-8
// Body: Unauthorized: missing Authorization header\nVariant 2 — JSON (handlers.go):
writeJSONResponse(w, http.StatusGone, map[string]interface{}{
"error": "server_not_found",
"message": "...",
})
// Content-Type: application/json
// Body: {"error":"server_not_found","message":"..."}Impact Analysis
- Maintainability: Developers adding new error paths must know which format to use — there's no enforced convention.
- Bug Risk: Medium — JSON-parsing clients that inspect 401 responses will fail to parse the body and may produce confusing error messages.
- API Consistency: The MCP Gateway spec implies a JSON API; mixing
text/plainfor auth errors is inconsistent with the rest of the API surface.
Refactoring Recommendations
-
Standardise on
writeJSONResponsefor all HTTP error paths in theserverpackage:// Replace in auth.go: // Before: http.Error(w, "Unauthorized: missing Authorization header", http.StatusUnauthorized) // After: writeJSONResponse(w, http.StatusUnauthorized, map[string]string{ "error": "unauthorized", "message": "missing Authorization header", })
-
Consider a dedicated
writeErrorResponsehelper to enforce the structure across all error paths:// writeErrorResponse writes a JSON error response with a consistent shape. func writeErrorResponse(w http.ResponseWriter, statusCode int, code, message string) { writeJSONResponse(w, statusCode, map[string]string{ "error": code, "message": message, }) }
-
Estimated effort: < 30 minutes; risk: very low (format change only, existing tests may need body-assertion updates).
Implementation Checklist
- Replace
http.Errorcalls inauth.gowithwriteJSONResponse(orwriteErrorResponse) - Add
writeErrorResponsehelper tohttp_helpers.goif adopting it - Update any tests that assert on plain-text
401bodies - Verify no other files in
internal/server/usehttp.Error - Confirm
Content-Type: application/jsonon all non-2xx responses
Parent Issue
See parent analysis report: #2825
Related to #2825
Generated by Duplicate Code Detector · ◷
- expires on Apr 6, 2026, 6:10 AM UTC