mirror of
https://github.com/marcusDenslow/terminalShop.git
synced 2026-10-25 02:52:20 +02:00
Adds Prometheus instrumentation across the checkout funnel, auth flow, Stripe calls, rate limiters, and HTTP middleware (inflight gauge, request and response sizes). Introduces a slog handler that counts log lines by level so the dashboard can show error/warn rates; existing log.Printf calls are routed through slog and counted as info. Backs the new "terminalshop — Service Overview" Grafana dashboard. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
43 lines
1.3 KiB
Go
43 lines
1.3 KiB
Go
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"strconv"
|
|
|
|
"github.com/go-chi/httprate"
|
|
"terminalShop/pkg/utils"
|
|
)
|
|
|
|
// RateLimitByIP returns a per-IP rate limiter for public endpoints.
|
|
func RateLimitByIP(limit int, window time.Duration) func(http.Handler) http.Handler {
|
|
return httprate.Limit(
|
|
limit, window,
|
|
httprate.WithKeyFuncs(httprate.KeyByIP),
|
|
httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) {
|
|
RecordRateLimitRejection("ip")
|
|
utils.RespondError(w, http.StatusTooManyRequests, "RATE_LIMITED", "too many requests", nil)
|
|
}),
|
|
)
|
|
}
|
|
|
|
// RateLimitByUser returns a per-authenticated-user rate limiter for protected endpoints.
|
|
func RateLimitByUser(limit int, window time.Duration) func(http.Handler) http.Handler {
|
|
return httprate.Limit(
|
|
limit, window,
|
|
httprate.WithKeyFuncs(func(r *http.Request) (string, error) {
|
|
userID := UserIDFromContext(r.Context())
|
|
if userID == 0 {
|
|
// Fall back to IP if no user context (shouldn't happen on protected routes).
|
|
return httprate.KeyByIP(r)
|
|
}
|
|
return "user:" + strconv.FormatUint(uint64(userID), 10), nil
|
|
}),
|
|
httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) {
|
|
RecordRateLimitRejection("user")
|
|
utils.RespondError(w, http.StatusTooManyRequests, "RATE_LIMITED", "too many requests", nil)
|
|
}),
|
|
)
|
|
}
|