Skip to main content

Overview

The requestid middleware generates or propagates unique request IDs for distributed tracing and debugging. Each request gets a unique identifier that can be logged and passed to downstream services.

Installation

import "github.com/go-mizu/mizu/middlewares/requestid"

Quick Start

app := mizu.New()
app.Use(requestid.New())

Configuration

OptionTypeDefaultDescription
Headerstring"X-Request-ID"Header name
Generatorfunc() stringUUID v4ID generator function

Examples

Basic Usage

app.Use(requestid.New())

app.Get("/", func(c *mizu.Ctx) error {
    id := requestid.Get(c)
    c.Logger().Info("processing", "request_id", id)
    return c.JSON(200, map[string]string{"id": id})
})

Custom Header

app.Use(requestid.WithOptions(requestid.Options{
    Header: "X-Trace-ID",
}))

Custom Generator

var counter uint64

app.Use(requestid.WithOptions(requestid.Options{
    Generator: func() string {
        return fmt.Sprintf("req-%d-%d", time.Now().Unix(), atomic.AddUint64(&counter, 1))
    },
}))

ID Propagation

If the incoming request has a request ID header, it’s preserved:
Client → X-Request-ID: abc123 → Server
                              → Response X-Request-ID: abc123
If not, a new one is generated:
Client → (no header) → Server generates: xyz789
                    → Response X-Request-ID: xyz789

Logging with Request ID

app.Use(requestid.New())

app.Get("/", func(c *mizu.Ctx) error {
    logger := c.Logger().With("request_id", requestid.Get(c))
    logger.Info("handling request")
    // ...
    return c.JSON(200, data)
})

Pass to Downstream Services

func callService(c *mizu.Ctx) error {
    req, _ := http.NewRequest("GET", "http://service/api", nil)
    req.Header.Set("X-Request-ID", requestid.Get(c))
    // ...
}

API Reference

func New() mizu.Middleware
func WithOptions(opts Options) mizu.Middleware
func FromContext(c *mizu.Ctx) string
func Get(c *mizu.Ctx) string  // Alias for FromContext

Technical Details

Implementation

The requestid middleware is implemented with the following key components:
  • Context Storage: Request IDs are stored in the request context using a private contextKey{} struct type to prevent collisions
  • ID Generation: Default generator creates UUID v4-style identifiers using crypto/rand for cryptographic randomness
  • Header Propagation: The middleware checks for existing request IDs in incoming headers and preserves them, or generates new ones if absent
  • Response Headers: Request IDs are automatically added to response headers for client visibility

UUID v4 Format

The default generator produces IDs in the format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
  • Uses 16 random bytes from crypto/rand
  • Version bits (byte 6): Set to 0x40 to indicate version 4
  • Variant bits (byte 8): Set to 0x80 to indicate RFC 4122 variant 2
  • Final format: 32 hexadecimal characters in 5 groups (8-4-4-4-12)

Context Key Design

The middleware uses a private struct type as the context key:
type contextKey struct{}
This prevents accidental key collisions with other middleware or application code that might use string or integer keys.

Flow

  1. Extract request ID from incoming header (if present)
  2. If no header, generate new ID using configured generator
  3. Store ID in request context with private key
  4. Set ID in response header
  5. Continue to next handler

Best Practices

  • Add early in middleware chain
  • Include in all logs
  • Pass to downstream services
  • Use for error correlation

Testing

The middleware includes comprehensive test coverage for all functionality:
Test CaseDescriptionExpected Behavior
TestNew/generates request IDTests default middleware behavior when no request ID is providedGenerates a new UUID v4-style request ID, stores it in context, and sets it in response header
TestNew/uses existing request IDTests ID propagation when client provides an existing request IDPreserves the existing request ID from request header, stores it in context, and returns it in response header
TestWithOptions_CustomHeaderTests custom header name configurationUses custom header name (e.g., “X-Correlation-ID”) instead of default “X-Request-ID”
TestWithOptions_CustomGeneratorTests custom ID generator functionUses provided generator function to create sequential custom IDs instead of UUID v4 format
TestGenerateIDTests default UUID v4 generator format and uniquenessGenerates IDs in correct UUID v4 format (8-4-4-4-12), sets version 4 bit, and ensures uniqueness across 1000 generations
TestGetTests that Get() and FromContext() are equivalentBoth functions return the same request ID value from context
  • timing - Performance tracing
  • recover - Panic recovery with context