Documentation
¶
Overview ¶
Package httpserver provides HTTP server helpers for graceful shutdown, JSON responses, strict JSON decoding, pagination, trusted-proxy client IP detection, rate limiting, built-in metrics routes, and embedded UI assets.
Serve records app_http_requests_total and app_http_request_duration_seconds with the route pattern the mux matched as the path label ("unmatched" when none did), so the handler it serves must be, or pass the request unchanged to, an http.ServeMux.
Index ¶
- Constants
- func ClientIP(r *http.Request) string
- func DecodeJSON[T any](r *http.Request) (T, error)
- func Heartbeat(ctx context.Context, w http.ResponseWriter, flusher http.Flusher, ...)
- func IsTrustedPeer(r *http.Request) bool
- func ParsePaginationParams(r *http.Request) (offset int64, perPage int64, page int64)
- func Serve(ctx context.Context, addr string, handler http.Handler) error
- func ServeSveltekitStaticFiles(sub fs.FS, fileServer http.Handler) http.HandlerFunc
- func ServeWithListener(ctx context.Context, ln net.Listener, handler http.Handler) error
- func SetTrustedProxyCIDRs(spec string) error
- func WriteData(w http.ResponseWriter, flusher http.Flusher, payload any) error
- func WriteError(w http.ResponseWriter, r *http.Request, status int, err error)
- func WriteJSON(w http.ResponseWriter, r *http.Request, status int, v any)
- type ErrResponse
- type IPRateLimiter
Constants ¶
const DefaultHeartbeatInterval = 15 * time.Second
Variables ¶
This section is empty.
Functions ¶
func ClientIP ¶
ClientIP returns the best-guess client IP address for the request.
Security model:
- X-Forwarded-For is trusted only when the direct peer is in the configured trusted-proxy CIDRs.
- otherwise we ignore forwarded headers and use RemoteAddr directly.
When X-Forwarded-For is trusted, we strip trusted-proxy hops from the right and return the rightmost remaining (untrusted) address — i.e. the leftmost address not appended by a known proxy. This prevents both spoofed leftmost entries and intermediate-proxy IPs from being mistaken for the real client.
func DecodeJSON ¶
DecodeJSON decodes a JSON request body into the specified type T. It ensures that no unknown fields are present and validates the input.
func IsTrustedPeer ¶
IsTrustedPeer reports whether the direct peer of r is in the configured trusted-proxy set.
func ParsePaginationParams ¶
ParsePaginationParams extracts offset, perPage, and page from query parameters.
func Serve ¶
Serve starts HTTP servers on the given addresses with the provided handler. It listens for context cancellation to initiate a graceful shutdown. It returns an error if any server fails to start or if shutdown is problematic.
func ServeSveltekitStaticFiles ¶
ServeSveltekitStaticFiles serves sveltekit static files from the given fs.FS with SPA fallback logic. Hashed assets under /_app/immutable/ are cached for a year; /service-worker.js, /_app/version.json and *.webmanifest are revalidated on every load, since a stale copy hides a new version of the app.
func ServeWithListener ¶
ServeWithListener starts an HTTP server using a provided net.Listener. Useful for tests: you can create a listener to retrieve the address and control the server's lifecycle from the test.
func SetTrustedProxyCIDRs ¶
SetTrustedProxyCIDRs configures which direct peers are allowed to supply trusted forwarded headers (X-Forwarded-For).
Input format:
- comma-separated CIDRs ("10.0.0.0/8,192.168.1.0/24")
- or comma-separated IPs ("127.0.0.1,::1")
- empty string resets to loopback defaults
- "none" disables forwarded-header trust entirely
func WriteError ¶
WriteError writes an error response with the given status code and error message, and logs it as an error. A request its client canceled gets no response and an info line instead: the client is gone, the server did nothing wrong.
Types ¶
type ErrResponse ¶
type ErrResponse struct {
Error string `json:"error"`
}
ErrResponse is the JSON shape written by WriteError.
type IPRateLimiter ¶
type IPRateLimiter struct {
// contains filtered or unexported fields
}
IPRateLimiter implements a fixed-window rate limiter keyed by client IP.
Design (VictoriaMetrics style):
- No goroutines: cleanup is lazy, triggered inside Allow.
- Single mutex over a plain map: predictable, no lock-free magic.
- Metrics via VictoriaMetrics counters: one label per endpoint.
func NewIPRateLimiter ¶
func NewIPRateLimiter(maxReqs int, window time.Duration) *IPRateLimiter
NewIPRateLimiter returns a limiter that allows maxReqs requests per IP within window.
func (*IPRateLimiter) Allow ¶
func (l *IPRateLimiter) Allow(ip string) bool
Allow reports whether the given IP is within the rate limit. Expired entries are swept lazily every cleanupInterval to keep memory bounded.
func (*IPRateLimiter) Check ¶
func (l *IPRateLimiter) Check(w http.ResponseWriter, r *http.Request) bool
Check reports whether the caller's IP is within the rate limit. On rejection it writes a 429 response with a Retry-After header and returns false; the caller must return immediately (mirrors the CheckSession helper).