check / check (push) Successful in 45s
A buffer failure on POST /api/v1/reports now returns 500 instead of a false `ok`, so clients can retry. Decode errors split: an over-limit body returns 413 (via errors.As on `*http.MaxBytesError`), malformed JSON stays 400. A new MaxBodyBytes middleware (1 MiB default) caps every route — rejecting an oversized Content-Length up front and capping the read otherwise — so the health check and future routes are bounded too. The raw attacker-controlled geo blob is no longer logged, only its length; client_id and timestamp are length-bounded before logging. A decodeJSON handler helper is added. Panic recovery is now a local middleware routing the stack through slog as structured JSON. Storage failure uses 500: a full buffer or write error is server-side and retryable. Model: opus-4-8
41 lines
938 B
Go
41 lines
938 B
Go
package server
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/chi/v5/middleware"
|
|
)
|
|
|
|
const (
|
|
requestTimeout = 60 * time.Second
|
|
|
|
// maxRequestBodyBytes caps every request body. A route that
|
|
// needs a different bound mounts s.mw.MaxBodyBytes with its
|
|
// own value on its group.
|
|
maxRequestBodyBytes int64 = 1 << 20 // 1 MiB
|
|
)
|
|
|
|
// SetupRoutes configures the chi router with middleware and
|
|
// all application routes.
|
|
func (s *Server) SetupRoutes() {
|
|
s.router = chi.NewRouter()
|
|
|
|
s.router.Use(s.mw.Recoverer())
|
|
s.router.Use(middleware.RequestID)
|
|
s.router.Use(s.mw.Logging())
|
|
s.router.Use(s.mw.SecurityHeaders())
|
|
s.router.Use(s.mw.CORS())
|
|
s.router.Use(s.mw.MaxBodyBytes(maxRequestBodyBytes))
|
|
s.router.Use(middleware.Timeout(requestTimeout))
|
|
|
|
s.router.Get(
|
|
"/.well-known/healthcheck",
|
|
s.h.HandleHealthCheck(),
|
|
)
|
|
|
|
s.router.Route("/api/v1", func(r chi.Router) {
|
|
r.Post("/reports", s.h.HandleReport())
|
|
})
|
|
}
|