From a6b4306d08141e75a2acec6295354367c561dae6 Mon Sep 17 00:00:00 2001 From: zenfun Date: Sat, 13 Dec 2025 22:24:37 +0800 Subject: [PATCH] feat(server): add request ID middleware Add request ID middleware to trace requests through the system. The middleware checks for existing X-Request-ID headers, generates a new UUID if not present, and sets the ID in both request/response headers and Gin context. --- cmd/server/main.go | 1 + internal/middleware/request_id.go | 35 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 internal/middleware/request_id.go 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[:]) +}