Co-authored-by: dev_agent <dev_agent@cubecraftlabs.com> Co-committed-by: dev_agent <dev_agent@cubecraftlabs.com>
35 lines
1.3 KiB
Go
35 lines
1.3 KiB
Go
package server
|
|
|
|
import (
|
|
"errors"
|
|
"log/slog"
|
|
"net/http"
|
|
|
|
"code.cubecraftlabs.com/Maniacs_Mansion/Meal-Quest/internal/forwarded"
|
|
)
|
|
|
|
// resolveOrigin resolves every request's client address and scheme with
|
|
// forwarded.Resolve and puts them in the context (read them with
|
|
// forwarded.ClientIP and forwarded.Scheme). Forwarded headers are honoured
|
|
// only from a peer in trusted. A malformed forwarded header from a trusted
|
|
// peer gets 400 bad_request.
|
|
func resolveOrigin(logger *slog.Logger, trusted forwarded.Trusted) func(http.Handler) http.Handler {
|
|
badRequest := apiErrorHandler(logger, http.StatusBadRequest, "bad_request", "invalid forwarded headers")
|
|
internal := apiErrorHandler(logger, http.StatusInternalServerError, "internal", "internal error")
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
o, err := forwarded.Resolve(r, trusted)
|
|
switch {
|
|
case errors.Is(err, forwarded.ErrInvalidHeader):
|
|
logger.WarnContext(r.Context(), "rejected forwarded headers", "peer", r.RemoteAddr, "error", err)
|
|
badRequest(w, r)
|
|
case err != nil:
|
|
logger.ErrorContext(r.Context(), "resolve request origin", "error", err)
|
|
internal(w, r)
|
|
default:
|
|
next.ServeHTTP(w, r.WithContext(forwarded.NewContext(r.Context(), o)))
|
|
}
|
|
})
|
|
}
|
|
}
|