diff --git a/cmd/server/main.go b/cmd/server/main.go index 5ca1afa..78b103e 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -121,6 +121,7 @@ func main() { // 5. Setup Gin Router r := gin.Default() + r.Use(middleware.RequestID()) // CORS Middleware r.Use(func(c *gin.Context) { diff --git a/internal/middleware/request_id.go b/internal/middleware/request_id.go new file mode 100644 index 0000000..f305711 --- /dev/null +++ b/internal/middleware/request_id.go @@ -0,0 +1,35 @@ +package middleware + +import ( + "crypto/rand" + "encoding/hex" + "strings" + "time" + + "github.com/gin-gonic/gin" +) + +// RequestID ensures every request has an X-Request-ID and echoes it back to the client. +func RequestID() gin.HandlerFunc { + return func(c *gin.Context) { + id := strings.TrimSpace(c.GetHeader("X-Request-ID")) + if id == "" { + id = strings.TrimSpace(c.GetHeader("X-Request-Id")) + } + if id == "" { + id = newRequestID() + } + c.Request.Header.Set("X-Request-ID", id) + c.Writer.Header().Set("X-Request-ID", id) + c.Set("request_id", id) + c.Next() + } +} + +func newRequestID() string { + var b [16]byte + if _, err := rand.Read(b[:]); err != nil { + return hex.EncodeToString([]byte(time.Now().Format(time.RFC3339Nano))) + } + return hex.EncodeToString(b[:]) +}