Request ID middleware for Fiber generates a unique identifier for each request. This helps with request tracking, debugging, and correlation across distributed systems.
Signatures
func New(config ...Config) fiber.Handler
func FromContext(c fiber.Ctx) string
Usage
import (
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/requestid"
)
Basic Usage
app.Use(requestid.New())
app.Get("/", func(c fiber.Ctx) error {
return c.SendString("Request ID: " + requestid.FromContext(c))
})
app.Use(requestid.New(requestid.Config{
Header: "X-Custom-Request-ID",
}))
Custom Generator
import "github.com/google/uuid"
app.Use(requestid.New(requestid.Config{
Generator: func() string {
return uuid.New().String()
},
}))
Skip Specific Routes
app.Use(requestid.New(requestid.Config{
Next: func(c fiber.Ctx) bool {
return c.Path() == "/health"
},
}))
Configuration
Next
func(fiber.Ctx) bool
default:"nil"
Defines a function to skip this middleware when it returns true.
The header key where the unique request ID is stored. The middleware will check this header on incoming requests and set it on responses.
Generator
func() string
default:"utils.SecureToken"
Defines a function to generate the unique request identifier. The default uses a secure random token generator.
Default Config
var ConfigDefault = Config{
Next: nil,
Header: fiber.HeaderXRequestID, // "X-Request-ID"
Generator: utils.SecureToken,
}
Helper Functions
FromContext
func FromContext(c fiber.Ctx) string
Retrieves the request ID from the context. This is useful for accessing the request ID in handlers.
app.Get("/user/:id", func(c fiber.Ctx) error {
requestID := requestid.FromContext(c)
log.Printf("[%s] Fetching user %s", requestID, c.Params("id"))
return c.JSON(user)
})
Common Use Cases
Logging with Request ID
import (
"github.com/gofiber/fiber/v3/middleware/requestid"
"github.com/gofiber/fiber/v3/middleware/logger"
)
app.Use(requestid.New())
app.Use(logger.New(logger.Config{
CustomTags: map[string]logger.LogFunc{
"requestid": func(output logger.Buffer, c fiber.Ctx, data *logger.Data, extraParam string) (int, error) {
return output.WriteString(requestid.FromContext(c))
},
},
Format: "[${requestid}] ${status} - ${method} ${path}\n",
}))
Error Tracking
app.Use(requestid.New())
app.Use(func(c fiber.Ctx) error {
err := c.Next()
if err != nil {
requestID := requestid.FromContext(c)
log.Printf("[%s] Error: %v", requestID, err)
return c.Status(500).JSON(fiber.Map{
"error": "Internal Server Error",
"request_id": requestID,
})
}
return nil
})
Distributed Tracing
app.Use(requestid.New(requestid.Config{
Header: "X-Trace-ID",
Generator: func() string {
return uuid.New().String()
},
}))
app.Get("/api/user/:id", func(c fiber.Ctx) error {
traceID := requestid.FromContext(c)
// Pass trace ID to downstream services
req := fasthttp.AcquireRequest()
req.Header.Set("X-Trace-ID", traceID)
// Make request...
return c.JSON(response)
})
Client-Provided Request ID
// Accept request ID from client or generate new one
app.Use(requestid.New(requestid.Config{
Header: "X-Request-ID",
Generator: func() string {
return uuid.New().String()
},
}))
// Client can send: X-Request-ID: client-generated-id
// If not provided, server generates one
Correlation Across Services
app.Use(requestid.New())
func callDownstreamService(c fiber.Ctx) error {
requestID := requestid.FromContext(c)
client := &http.Client{}
req, _ := http.NewRequest("GET", "http://service2/api", nil)
req.Header.Set("X-Request-ID", requestID)
resp, err := client.Do(req)
// Handle response...
return nil
}
Best Practices
Register Early
// Register request ID middleware early so all logs include it
app.Use(requestid.New())
app.Use(logger.New())
// Other middleware and routes...
// Use standard headers across your microservices
const TraceHeader = "X-Trace-ID"
app.Use(requestid.New(requestid.Config{
Header: TraceHeader,
}))
Include in Error Responses
app.Use(requestid.New())
app.Use(func(c fiber.Ctx) error {
err := c.Next()
if err != nil {
return c.Status(500).JSON(fiber.Map{
"error": err.Error(),
"request_id": requestid.FromContext(c),
"timestamp": time.Now().Unix(),
})
}
return nil
})
Structured Logging
import "log/slog"
app.Use(requestid.New())
app.Get("/api/data", func(c fiber.Ctx) error {
requestID := requestid.FromContext(c)
slog.Info("Processing request",
"request_id", requestID,
"path", c.Path(),
"method", c.Method(),
)
return c.JSON(data)
})
Notes
- If the request already contains the configured header, its value is used instead of generating a new one
- The request ID is stored in the response header for client reference
- The default generator uses
utils.SecureToken which provides cryptographically secure random tokens
- Request IDs are useful for debugging, logging, and tracing requests through distributed systems