feat: funciones impuras HTTP — response, parse, logger, router, serve

Seis funciones de servidor HTTP con tests usando httptest:
- HTTPJSONResponse: escribe JSON con Content-Type y status code
- HTTPErrorResponse: escribe HTTPError como JSON estructurado
- HTTPParseBody: decode JSON con limite de bytes y campos estrictos
- HTTPLoggerMiddleware: loguea method/path/status/duration a io.Writer
- HTTPRouter: crea ServeMux con rutas Go 1.22+ (METHOD /path)
- HTTPServe: ListenAndServe con graceful shutdown por contexto

23 tests pasando, solo stdlib net/http.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-13 01:57:47 +02:00
parent c43322ecc0
commit b074313c01
13 changed files with 729 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
package infra
import (
"fmt"
"io"
"net/http"
"time"
)
// responseWriter captura el status code escrito al ResponseWriter.
type responseWriter struct {
http.ResponseWriter
status int
}
func (rw *responseWriter) WriteHeader(status int) {
rw.status = status
rw.ResponseWriter.WriteHeader(status)
}
// HTTPLoggerMiddleware retorna un Middleware que loguea metodo, path, status y duracion de cada request.
// El formato de cada linea es: METHOD /path STATUS DURACIONms
func HTTPLoggerMiddleware(logger io.Writer) Middleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
rw := &responseWriter{ResponseWriter: w, status: http.StatusOK}
next.ServeHTTP(rw, r)
duration := time.Since(start)
fmt.Fprintf(logger, "%s %s %d %dms\n",
r.Method, r.URL.Path, rw.status, duration.Milliseconds())
})
}
}