Documentation
¶
Overview ¶
Package middleware is the HTTP middleware a project mounts: Register adds middleware to every API route, RegisterAuth to the routes of the authenticated group, and the constructors here build the middleware the framework ships for either. IAMSession and Authz are the middleware of the iam and authz modules, whose source files gg module copy copies into a project.
The chain the framework mounts ahead of every route itself, and the machinery that mounts registered middleware onto the routes, are the framework's own.
Index ¶
- func Authz() gin.HandlerFunc
- func CircuitBreaker() gin.HandlerFunc
- func Delay(duration time.Duration) gin.HandlerFunc
- func DelayRandom(minDuration, maxDuration time.Duration) gin.HandlerFunc
- func DelayWithConfig(delayFunc func(*gin.Context) time.Duration) gin.HandlerFunc
- func IAMSession() gin.HandlerFunc
- func IPBlacklist(blacklist []string) gin.HandlerFunc
- func IPFilter(config *IPFilterConfig) gin.HandlerFunc
- func IPWhitelist(whitelist []string) gin.HandlerFunc
- func JwtAuth() gin.HandlerFunc
- func Register(middlewares ...gin.HandlerFunc)
- func RegisterAuth(middlewares ...gin.HandlerFunc)
- func RequestSizeLimit(maxSize int64) gin.HandlerFunc
- func SecurityHeaders(config *SecurityHeadersConfig) gin.HandlerFunc
- func Timeout(timeout time.Duration) gin.HandlerFunc
- type IPFilterConfig
- type SecurityHeadersConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Authz ¶
func Authz() gin.HandlerFunc
Authz authorizes requests using RBAC, through rbac.Enforce, the one decision path the gRPC interceptor of the module takes as well: the subject is read off the gin context, the object and action are the request path and method, and a refusal is answered in the API envelope with the status and message the service error carries. Authz must be called before config.Init so config.Init can read AUTH_RBAC_ENABLED from the environment and enable RBAC initialization.
Authz must run after an authentication middleware that populates requestctx.KeyUserID. When using built-in IAM sessions, register IAMSession before Authz; otherwise a valid session cookie is rejected as "permission denied" because Authz cannot find the authenticated subject yet.
The request tenant has exactly one source: requestctx.KeyTenantID, read as it stands when this middleware runs, defaulted to tenant.Default when empty. Whatever trusted middleware wrote it last decides. IAMSession writes the session's tenant; a deployment whose tenant arrives another way — a header a trusted gateway injects, a subdomain — installs its own middleware after IAMSession and before Authz and overwrites it. The value must only ever be written from something the deployment vouches for, never from client input passed through as it stands; rbac.Enforce says why.
func CircuitBreaker ¶
func CircuitBreaker() gin.HandlerFunc
CircuitBreaker returns a middleware that runs each request through the circuit breaker configured under server.circuit_breaker, which the framework builds as it bootstraps. A request counts as failed when its handler writes a response with a 5xx status, or writes nothing and records an error. Once enough requests have been counted and the configured share of them failed, the breaker opens: requests are refused with 503 until its timeout has passed and trial requests succeed again. A request the breaker lets through keeps the answer its handlers gave, failed or not. Requests to streaming routes bypass the breaker.
func Delay ¶
func Delay(duration time.Duration) gin.HandlerFunc
Delay returns a middleware that adds a fixed delay before processing the request. This is primarily used for testing purposes to simulate network latency or slow responses.
Parameters:
- duration: The delay duration to add before processing the request
Returns:
- A gin.HandlerFunc that adds the specified delay
Example, from an init function (see Register):
// Add a 100ms delay to every API route middleware.Register(middleware.Delay(100 * time.Millisecond)) // Add a 1 second delay middleware.Register(middleware.Delay(1 * time.Second))
func DelayRandom ¶
func DelayRandom(minDuration, maxDuration time.Duration) gin.HandlerFunc
DelayRandom returns a middleware that adds a random delay within the specified range before processing the request. This is primarily used for testing purposes to simulate variable network latency or slow responses.
Parameters:
- minDuration: The minimum delay duration
- maxDuration: The maximum delay duration
Returns:
- A gin.HandlerFunc that adds a random delay between minDuration and maxDuration
Example, from an init function (see Register):
// Add a random delay between 0 and 3000ms middleware.Register(middleware.DelayRandom(0, 3000*time.Millisecond)) // Add a random delay between 100ms and 500ms short, long := 100*time.Millisecond, 500*time.Millisecond middleware.Register(middleware.DelayRandom(short, long))
func DelayWithConfig ¶
DelayWithConfig returns a middleware that adds a configurable delay based on request properties. This allows for more flexible testing scenarios, such as different delays for different paths or methods.
Parameters:
- delayFunc: A function that determines the delay duration based on the request context
Returns:
- A gin.HandlerFunc that adds the delay determined by delayFunc
Example, from an init function (see Register):
// Add a delay based on the path
byPath := func(c *gin.Context) time.Duration {
if strings.HasPrefix(c.Request.URL.Path, "/api/slow") {
return 2 * time.Second
}
return 100 * time.Millisecond
}
middleware.Register(middleware.DelayWithConfig(byPath))
func IAMSession ¶
func IAMSession() gin.HandlerFunc
IAMSession authenticates a request from the IAM session its cookie names, through serviceiamsession.Authenticate, the one path the gRPC interceptor of the module takes as well: the session is admitted or refused the same way over both listeners, and what differs here is only where the session id comes from, the cookie, and how a refusal is answered, in the API envelope with the status and message the service error carries. Building the middleware declares the cookie to the OpenAPI document as the cookieAuth scheme.
func IPBlacklist ¶
func IPBlacklist(blacklist []string) gin.HandlerFunc
IPBlacklist returns a middleware that blocks requests from IP addresses in the blacklist.
Parameters:
- blacklist: List of blocked IP addresses or CIDR ranges (e.g., "192.168.1.100", "10.0.0.0/8")
Returns:
- A gin.HandlerFunc that enforces IP blacklist
Example, from an init function (see Register):
// Block specific IPs
blocked := []string{"192.168.1.100", "10.0.0.0/8"}
middleware.Register(middleware.IPBlacklist(blocked))
// Block known malicious IPs
known := []string{"1.2.3.4", "5.6.7.8"}
middleware.Register(middleware.IPBlacklist(known))
func IPFilter ¶
func IPFilter(config *IPFilterConfig) gin.HandlerFunc
IPFilter returns a middleware that filters requests based on IP whitelist and blacklist. Blacklist takes precedence over whitelist.
The address filtered on is the one the engine reports: the peer of the connection, or the address a trusted proxy forwarded. Which proxies count is server.trusted_proxies, applied to the engine at startup — behind a proxy that is not named there, every request filters as the proxy's own address.
Entries match the way net.IP compares addresses: an IPv4-mapped IPv6 address, such as ::ffff:10.1.2.3, matches the IPv4 entries, while every other IPv6 address, the loopback ::1 among them, matches IPv6 entries alone, so letting local callers in over both families takes 127.0.0.1 and ::1.
Parameters:
- config: Configuration for IP filtering
Returns:
- A gin.HandlerFunc that enforces IP filtering rules
Example, from an init function (see Register):
// Use both whitelist and blacklist
middleware.Register(middleware.IPFilter(&middleware.IPFilterConfig{
Whitelist: []string{"192.168.0.0/16"},
Blacklist: []string{"192.168.1.100"},
}))
func IPWhitelist ¶
func IPWhitelist(whitelist []string) gin.HandlerFunc
IPWhitelist returns a middleware that only allows requests from IP addresses in the whitelist.
Parameters:
- whitelist: List of allowed IP addresses or CIDR ranges (e.g., "192.168.1.1", "10.0.0.0/8")
Returns:
- A gin.HandlerFunc that enforces IP whitelist
Example, from an init function (see Register):
// Allow only specific IPs
allowed := []string{"192.168.1.1", "10.0.0.0/8"}
middleware.Register(middleware.IPWhitelist(allowed))
// Allow only localhost
middleware.Register(middleware.IPWhitelist([]string{"127.0.0.1", "::1"}))
func JwtAuth ¶
func JwtAuth() gin.HandlerFunc
JwtAuth authenticates a request from the bearer token in its Authorization header.
The token answers for itself: it is verified from its signature and claims, with nothing read from storage. Revoking one before it expires therefore is not something this middleware can do, which is the trade a stateless token makes and the reason IAM's own sessions are not built on it. Building the middleware declares the token to the OpenAPI document as the bearerAuth scheme.
func Register ¶
func Register(middlewares ...gin.HandlerFunc)
Register adds middlewares that run on every API route. Call it from an init function: gin fixes the chain of a route as the route registers, so a call once a route is registered, or once the server runs, panics rather than leave the routes registered before it without the middleware. Registered that way, they run in registration order, and on the routes of router.Auth ahead of every middleware RegisterAuth adds. When tracing is enabled, each middleware runs in a span of its own.
func RegisterAuth ¶
func RegisterAuth(middlewares ...gin.HandlerFunc)
RegisterAuth adds middlewares that run only on the routes registered on router.Auth: the place for authentication and authorization. Call it from an init function: like Register, a call once a route is registered, or once the server runs, panics rather than leave the routes registered before it without the middleware. Registered that way, they run in registration order, after every middleware Register adds. When tracing is enabled, each middleware runs in a span of its own.
func RequestSizeLimit ¶
func RequestSizeLimit(maxSize int64) gin.HandlerFunc
RequestSizeLimit returns a middleware that limits the size of incoming request bodies. This helps prevent DoS attacks by limiting the amount of data that can be sent in a single request.
Parameters:
- maxSize: Maximum allowed size in bytes for the request body
Returns:
- A gin.HandlerFunc that enforces the request size limit
Example, from an init function (see Register):
// Limit request body to 10MB middleware.Register(middleware.RequestSizeLimit(10 * 1024 * 1024)) // Limit request body to 1MB middleware.Register(middleware.RequestSizeLimit(1024 * 1024))
func SecurityHeaders ¶
func SecurityHeaders(config *SecurityHeadersConfig) gin.HandlerFunc
SecurityHeaders returns a middleware that sets security-related HTTP headers. This helps protect against various web vulnerabilities.
Parameters:
- config: Configuration for security headers. If nil, default secure headers will be used.
Returns:
- A gin.HandlerFunc that sets security headers
Example, from an init function (see Register):
// Use default secure headers
middleware.Register(middleware.SecurityHeaders(nil))
// Use custom configuration
headers := &middleware.SecurityHeadersConfig{
XFrameOptions: "DENY",
XContentTypeOptions: "nosniff",
XXSSProtection: "1; mode=block",
StrictTransportSecurity: "max-age=31536000; includeSubDomains",
ContentSecurityPolicy: "default-src 'self'",
ReferrerPolicy: "strict-origin-when-cross-origin",
}
middleware.Register(middleware.SecurityHeaders(headers))
func Timeout ¶
func Timeout(timeout time.Duration) gin.HandlerFunc
Timeout returns a middleware that puts a deadline on the request context and answers 504 when the rest of the chain has not started its response by then.
The deadline is cooperative. The chain runs to completion on the request goroutine, and code that honors the request context (database, cache and outbound calls) stops once the deadline passes. A response the chain starts writing before the deadline goes out as written; one it would only start after the deadline is dropped, together with the headers the chain set, and the 504 envelope is written in its place once the chain returns, so a handler that ignores the context delays the 504 until it returns. The chain never runs on a goroutine of its own: gin takes the context back for the next request as soon as this one returns, and a chain still running on it would read and write another request.
Streaming routes are left alone, since a stream legitimately outlives any request timeout.
Example, from an init function (see Register):
// Set a 30 second timeout on every API route middleware.Register(middleware.Timeout(30 * time.Second)) // Set a 5 second timeout middleware.Register(middleware.Timeout(5 * time.Second))
Types ¶
type IPFilterConfig ¶
type IPFilterConfig struct {
// Whitelist contains allowed IP addresses or CIDR ranges
// If non-empty, only IPs in this list will be allowed
Whitelist []string
// Blacklist contains blocked IP addresses or CIDR ranges
// IPs in this list will always be blocked
Blacklist []string
}
IPFilterConfig holds configuration for IP filtering middleware
type SecurityHeadersConfig ¶
type SecurityHeadersConfig struct {
// XFrameOptions controls the X-Frame-Options header
// Options: "DENY", "SAMEORIGIN", or empty string to disable
XFrameOptions string
// XContentTypeOptions controls the X-Content-Type-Options header
// Set to "nosniff" to enable, or empty string to disable
XContentTypeOptions string
// XXSSProtection controls the X-XSS-Protection header
// Set to "1; mode=block" to enable, or empty string to disable
XXSSProtection string
// StrictTransportSecurity controls the Strict-Transport-Security header
// Set to a value like "max-age=31536000; includeSubDomains" to enable, or empty string to disable
StrictTransportSecurity string
// ContentSecurityPolicy controls the Content-Security-Policy header
// Set to a CSP policy string to enable, or empty string to disable
ContentSecurityPolicy string
// ReferrerPolicy controls the Referrer-Policy header
// Options: "no-referrer", "no-referrer-when-downgrade", "origin", etc., or empty string to disable
ReferrerPolicy string
// PermissionsPolicy controls the Permissions-Policy header
// Set to a permissions policy string to enable, or empty string to disable
PermissionsPolicy string
}
SecurityHeadersConfig holds configuration for security headers middleware