Documentation
¶
Index ¶
- Constants
- Variables
- func AdminMiddleware(jwtManager *jwt.Manager, adminEmail string, ...) gin.HandlerFunc
- func AuthMiddleware(jwtManager *jwt.Manager, publicPaths []string) gin.HandlerFunc
- func LoggerMiddleware() gin.HandlerFunc
- func MaxBodyBytesMiddleware(defaultLimit int64, overrides map[string]int64) gin.HandlerFunc
- func MetricsMiddleware() gin.HandlerFunc
- func NewRateLimitMiddleware(rate int64, period time.Duration) gin.HandlerFunc
- func NewUserRateLimitMiddleware(rate int64, period time.Duration) gin.HandlerFunc
- func RateLimitByPath(rl gin.HandlerFunc, paths ...string) gin.HandlerFunc
- func RateLimitByPathPrefix(rl gin.HandlerFunc, prefixes ...string) gin.HandlerFunc
- func RateLimitByPathWithQueryParam(rl gin.HandlerFunc, path, queryParam string) gin.HandlerFunc
- func RecoveryWithMetrics() gin.HandlerFunc
- func RegisterAppMetrics(version string, startedAt time.Time)
- func RequestTimeoutMiddleware(timeout time.Duration) gin.HandlerFunc
- func SecurityHeadersMiddleware() gin.HandlerFunc
- type DBStatsCollector
Constants ¶
const ( // RequestIDKey is the context key for request ID RequestIDKey = "request_id" // RequestIDHeader is the header key for request ID RequestIDHeader = "X-Request-ID" )
Variables ¶
var ( // AppInfo is a constant gauge (value 1) with version and go_version labels. AppInfo = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "app_info", Help: "Application build information.", }, []string{"version", "go_version"}, ) // AppUptimeSeconds reports seconds since server start. AppUptimeSeconds = prometheus.NewGaugeFunc( prometheus.GaugeOpts{ Name: "app_uptime_seconds", Help: "Seconds since server start.", }, func() float64 { return 0 }, ) // HealthCheckStatus is 1 when the service is healthy, 0 when unhealthy. HealthCheckStatus = prometheus.NewGauge( prometheus.GaugeOpts{ Name: "health_check_status", Help: "Health check status: 1 = healthy, 0 = unhealthy.", }, ) )
var ( // HTTPRequestsTotal counts total HTTP requests by method, path, and status. HTTPRequestsTotal = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests.", }, []string{"method", "path", "status"}, ) // HTTPRequestDurationSeconds tracks HTTP request latency. HTTPRequestDurationSeconds = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "HTTP request latency in seconds.", Buckets: prometheus.DefBuckets, }, []string{"method", "path"}, ) // HTTPResponseSizeBytes tracks HTTP response sizes. HTTPResponseSizeBytes = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "http_response_size_bytes", Help: "HTTP response size in bytes.", Buckets: prometheus.ExponentialBuckets(100, 10, 7), }, []string{"method", "path"}, ) // HTTPRequestsInFlight tracks the number of in-flight HTTP requests. HTTPRequestsInFlight = prometheus.NewGauge( prometheus.GaugeOpts{ Name: "http_requests_in_flight", Help: "Number of HTTP requests currently being processed.", }, ) // APIPanicsRecoveredTotal counts panics recovered by the recovery middleware. APIPanicsRecoveredTotal = prometheus.NewCounter( prometheus.CounterOpts{ Name: "api_panics_recovered_total", Help: "Total number of panics recovered.", }, ) )
var ( // RateLimitHitsTotal counts requests that were rate-limited. RateLimitHitsTotal = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "rate_limit_hits_total", Help: "Total number of requests that were rate-limited.", }, []string{"path"}, ) )
Functions ¶
func AdminMiddleware ¶
func AdminMiddleware(jwtManager *jwt.Manager, adminEmail string, getUserEmail func(userID uuid.UUID) (string, error)) gin.HandlerFunc
AdminMiddleware creates a middleware that restricts access to admin users only. It requires the auth middleware to have already set "userID" in the context. The admin user is determined by matching the user's email against the ADMIN_EMAIL env var.
func AuthMiddleware ¶
func AuthMiddleware(jwtManager *jwt.Manager, publicPaths []string) gin.HandlerFunc
AuthMiddleware enforces JWT authentication on all routes except explicitly allowed public paths. It extracts the user ID from the token and sets it in the Gin context as "userID".
func LoggerMiddleware ¶
func LoggerMiddleware() gin.HandlerFunc
LoggerMiddleware creates a middleware for request logging
func MaxBodyBytesMiddleware ¶ added in v1.3.0
func MaxBodyBytesMiddleware(defaultLimit int64, overrides map[string]int64) gin.HandlerFunc
MaxBodyBytesMiddleware caps the request body size for non-multipart requests. ShouldBindJSON (and json.NewDecoder) read the body in full before any application-level validation runs, so without a cap a large JSON payload is buffered entirely in memory regardless of what the handler goes on to check.
Multipart (file upload) requests are exempt — they already have their own size guards (router.MaxMultipartMemory plus an explicit per-file check in the CSV upload handler) sized for actual file uploads, which defaultLimit is not.
overrides maps a path suffix (matched the same way as RateLimitByPath/RateLimitByPathPrefix) to a larger limit, for the rare JSON endpoint that legitimately carries a bigger payload (e.g. restoring a full logbook backup via POST /imports/json). The first matching suffix wins; unmatched paths get defaultLimit.
func MetricsMiddleware ¶
func MetricsMiddleware() gin.HandlerFunc
MetricsMiddleware returns a Gin middleware that records Prometheus metrics for every HTTP request: counter, duration histogram, response size histogram, and in-flight gauge.
func NewRateLimitMiddleware ¶
func NewRateLimitMiddleware(rate int64, period time.Duration) gin.HandlerFunc
NewRateLimitMiddleware creates a Gin middleware that rate-limits requests. rate is the number of requests allowed per period (e.g., 10 requests per 1 minute). It uses Gin's c.ClientIP() to key rate limits by the real client IP (respecting X-Real-IP / X-Forwarded-For headers set by nginx) instead of the proxy's address.
func NewUserRateLimitMiddleware ¶ added in v1.3.0
func NewUserRateLimitMiddleware(rate int64, period time.Duration) gin.HandlerFunc
NewUserRateLimitMiddleware is like NewRateLimitMiddleware, but keys by the authenticated user's ID (set by AuthMiddleware as "userID") when present, falling back to client IP otherwise (e.g. the request never reached AuthMiddleware's authenticated branch). Per-user keying is more precise for logged-in traffic than per-IP: it isn't inflated by users sharing a NAT/office IP, and isn't defeated by one user rotating source IPs.
func RateLimitByPath ¶
func RateLimitByPath(rl gin.HandlerFunc, paths ...string) gin.HandlerFunc
RateLimitByPath applies a rate-limit middleware only to requests whose path (relative to the router group) matches one of the given suffixes.
func RateLimitByPathPrefix ¶ added in v1.2.9
func RateLimitByPathPrefix(rl gin.HandlerFunc, prefixes ...string) gin.HandlerFunc
RateLimitByPathPrefix applies a rate-limit middleware only to requests whose path starts with one of the given prefixes. Unlike RateLimitByPath's suffix matching, this is needed for routes ending in an opaque token (e.g. "/sign/{token}"), which never share a fixed suffix.
func RateLimitByPathWithQueryParam ¶ added in v1.3.0
func RateLimitByPathWithQueryParam(rl gin.HandlerFunc, path, queryParam string) gin.HandlerFunc
RateLimitByPathWithQueryParam applies a rate-limit middleware only to requests whose path (relative to the router group) ends with the given suffix AND which carry a non-empty queryParam. This targets expensive query variants of an otherwise-cheap route (e.g. GET /flights only becomes costly once a free-text search "q" is present) without limiting plain, cheap requests to the same path.
func RecoveryWithMetrics ¶
func RecoveryWithMetrics() gin.HandlerFunc
RecoveryWithMetrics returns a Gin middleware that recovers from panics, increments the api_panics_recovered_total counter, and returns a 500 response.
func RegisterAppMetrics ¶
RegisterAppMetrics registers app_info and app_uptime_seconds gauges. version is the application version string (e.g. "1.0.0" or a git SHA).
func RequestTimeoutMiddleware ¶ added in v1.3.0
func RequestTimeoutMiddleware(timeout time.Duration) gin.HandlerFunc
RequestTimeoutMiddleware bounds every request's context to the given duration. Handlers pass c.Request.Context() down to database calls (QueryContext/ExecContext), so without this a slow or unbounded query has no deadline and holds its pool connection until it finishes on its own. This is defense in depth alongside the database's own statement_timeout: whichever fires first cancels the query and frees the connection.
func SecurityHeadersMiddleware ¶
func SecurityHeadersMiddleware() gin.HandlerFunc
SecurityHeadersMiddleware adds standard security headers to all API responses.
Types ¶
type DBStatsCollector ¶
type DBStatsCollector struct {
// contains filtered or unexported fields
}
DBStatsCollector implements prometheus.Collector and exposes sql.DBStats as Prometheus gauges on every scrape.
func NewDBStatsCollector ¶
func NewDBStatsCollector(db *sql.DB) *DBStatsCollector
NewDBStatsCollector creates a collector that reads stats from db on every scrape.
func (*DBStatsCollector) Collect ¶
func (c *DBStatsCollector) Collect(ch chan<- prometheus.Metric)
Collect reads the current sql.DBStats and sends each metric value.
func (*DBStatsCollector) Describe ¶
func (c *DBStatsCollector) Describe(ch chan<- *prometheus.Desc)
Describe sends the descriptors of each metric to the channel.