Documentation
¶
Overview ¶
Package httpx contains HTTP middleware and helpers shared by every API surface: client IP resolution, request logging, panic recovery, metrics and JSON error responses.
Index ¶
- func AllowIPs(allowed []netip.Prefix) func(http.Handler) http.Handler
- func ClientIP(r *http.Request) netip.Addr
- func ClientIPString(r *http.Request) string
- func Logger(log *slog.Logger) func(http.Handler) http.Handler
- func MethodNotAllowed(w http.ResponseWriter, _ *http.Request)
- func NotFound(w http.ResponseWriter, _ *http.Request)
- func RateLimit(l *RateLimiter, retryAfter string, reject http.HandlerFunc) func(http.Handler) http.Handler
- func RealIP(trusted []netip.Prefix, header string) func(http.Handler) http.Handler
- func Recoverer(log *slog.Logger) func(http.Handler) http.Handler
- func RedactPath(p string) string
- func WriteError(w http.ResponseWriter, status int, code, message string)
- func WriteJSON(w http.ResponseWriter, status int, v any)
- type ErrorBody
- type ErrorDetail
- type Metrics
- type RateLimiter
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AllowIPs ¶
AllowIPs returns middleware rejecting (403) clients whose resolved IP is outside allowed. Used for /metrics. Defence in depth for deployments behind a loopback reverse proxy: every address in any forwarding header (X-Forwarded-For, X-Real-IP, CF-Connecting-IP, True-Client-IP, Forwarded) must also be allowed, so a proxied request is never mistaken for a local scraper even when the proxy uses a different header than real_ip_header.
func ClientIP ¶
ClientIP returns the client IP resolved by RealIP (invalid if the middleware did not run and RemoteAddr is unparsable).
func ClientIPString ¶
ClientIPString is ClientIP formatted for logs/DB ("" when unknown).
func Logger ¶
Logger logs one line per request. Query strings are deliberately omitted: they can carry bearer material (OIDC codes, share tokens); so is the token segment of public share link paths (see RedactPath).
func MethodNotAllowed ¶
func MethodNotAllowed(w http.ResponseWriter, _ *http.Request)
MethodNotAllowed is a JSON 405 handler for API sub-routers.
func NotFound ¶
func NotFound(w http.ResponseWriter, _ *http.Request)
NotFound is a JSON 404 handler for API sub-routers.
func RateLimit ¶ added in v0.14.0
func RateLimit(l *RateLimiter, retryAfter string, reject http.HandlerFunc) func(http.Handler) http.Handler
RateLimit returns middleware answering 429 (Retry-After: retryAfter seconds, body from reject) to clients over l's limit, keyed by ClientIP.
func RealIP ¶
RealIP resolves the client IP and stores it in the request context (retrieve with ClientIP). Forwarding headers are honoured ONLY when the direct peer is inside trusted; otherwise the TCP peer address is used.
header selects the source when the peer is trusted:
- "X-Forwarded-For": walk the list right-to-left, skipping trusted hops, and take the first untrusted address (spoof-resistant);
- "X-Real-Ip" / "Cf-Connecting-Ip": take the single address.
func Recoverer ¶
Recoverer turns panics into a 500 JSON error and logs the stack. http.ErrAbortHandler is re-panicked so net/http can abort the connection.
func RedactPath ¶ added in v0.14.0
RedactPath hides bearer material carried in a request path for logs: the token of public share links (/s/<token>/... becomes /s/[token]/...). Their static files (/s/assets/..., /s/favicon.svg) are kept.
func WriteError ¶
func WriteError(w http.ResponseWriter, status int, code, message string)
WriteError writes the standard error envelope.
Types ¶
type ErrorBody ¶
type ErrorBody struct {
Error ErrorDetail `json:"error"`
}
ErrorBody is the panel API error envelope: {"error":{"code":"...","message":"..."}}. (The RustDesk client API under /api uses its own legacy shapes.)
type ErrorDetail ¶
ErrorDetail carries a stable machine-readable code and a human message.
type Metrics ¶
type Metrics struct {
// contains filtered or unexported fields
}
Metrics records request counts and latencies by chi route pattern (never by raw path, to keep label cardinality bounded).
func NewMetrics ¶
func NewMetrics(reg prometheus.Registerer) *Metrics
NewMetrics registers HTTP metrics on reg.
type RateLimiter ¶ added in v0.14.0
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter is an in-memory token bucket per key (usually the client IP): Rate requests per second with bursts of Burst. Idle keys are dropped after ten minutes. A Rate <= 0 allows everything.
func NewRateLimiter ¶ added in v0.14.0
func NewRateLimiter(rate float64, burst int, now func() time.Time) *RateLimiter
NewRateLimiter returns a limiter of rate requests per second with bursts of burst (at least 1); now nil means time.Now.
func (*RateLimiter) Allow ¶ added in v0.14.0
func (l *RateLimiter) Allow(key string) bool
Allow takes a token for key and reports whether one was available.