package middleware import ( "github.com/gin-gonic/gin" "github.com/google/uuid" ) const ( // RequestIDHeader is the primary header for request IDs RequestIDHeader = "X-Request-ID" // CorrelationIDHeader is an alternative header for distributed tracing CorrelationIDHeader = "X-Correlation-ID" // RequestIDKey is the context key for storing the request ID RequestIDKey = "request_id" ) // RequestID returns a middleware that generates and propagates request IDs. // // For each incoming request: // 1. Check for existing X-Request-ID or X-Correlation-ID header // 2. If not present, generate a new UUID // 3. Store in Gin context for use by handlers and logging // 4. Add to response headers // // Usage: // // r.Use(middleware.RequestID()) // // func handler(c *gin.Context) { // requestID := middleware.GetRequestID(c) // log.Printf("[%s] Processing request", requestID) // } func RequestID() gin.HandlerFunc { return func(c *gin.Context) { // Try to get existing request ID from headers requestID := c.GetHeader(RequestIDHeader) if requestID == "" { requestID = c.GetHeader(CorrelationIDHeader) } // Generate new ID if not provided if requestID == "" { requestID = uuid.New().String() } // Store in context for handlers and logging c.Set(RequestIDKey, requestID) // Add to response headers c.Header(RequestIDHeader, requestID) c.Header(CorrelationIDHeader, requestID) c.Next() } } // GetRequestID retrieves the request ID from the Gin context. // Returns empty string if no request ID is set. // // Usage: // // requestID := middleware.GetRequestID(c) func GetRequestID(c *gin.Context) string { if id, exists := c.Get(RequestIDKey); exists { if idStr, ok := id.(string); ok { return idStr } } return "" } // RequestIDFromContext is an alias for GetRequestID for API compatibility. func RequestIDFromContext(c *gin.Context) string { return GetRequestID(c) }