Hone logo
Hone
Problems

Implementing Request IDs for Enhanced Traceability in Go

Request IDs are crucial for debugging and tracing requests through distributed systems. This challenge asks you to implement a middleware in Go that automatically generates and injects a unique request ID into incoming HTTP requests and makes it available in the request context. This will allow downstream services and logging to easily correlate events related to a specific request.

Problem Description

You need to create a Go middleware that performs the following actions:

  1. Generate a Unique Request ID: Upon receiving an HTTP request, generate a unique request ID. A simple UUID (Universally Unique Identifier) is sufficient for this purpose.
  2. Inject into Request Context: Store the generated request ID in the request's context using context.WithValue. This allows subsequent handlers and middleware to access the ID.
  3. Add to Request Headers: Add a custom HTTP header named X-Request-ID containing the generated request ID.
  4. Handle Errors: The middleware should not panic or crash if any errors occur during ID generation or context manipulation.

The middleware should be compatible with the standard net/http package. It should take an http.Handler as input and return a new http.Handler.

Key Requirements:

  • The request ID should be a string representation of a UUID.
  • The middleware should be non-blocking and efficient.
  • The middleware should not modify the original request or response objects beyond adding the header and context value.
  • The middleware should be reusable and easily integrated into existing Go applications.

Expected Behavior:

When a request is processed by the middleware, the following should occur:

  • A unique request ID is generated.
  • The request ID is stored in the request context.
  • The X-Request-ID header is added to the response.
  • Subsequent handlers and middleware can retrieve the request ID from the context.

Edge Cases to Consider:

  • What happens if the provided http.Handler is nil? The middleware should handle this gracefully (e.g., return itself or panic with a clear error message).
  • Consider the performance implications of generating UUIDs and storing them in the context. While a simple UUID is acceptable for this challenge, be mindful of potential bottlenecks in production environments.
  • How should the middleware behave if the context already contains a value with the same key (X-Request-ID)? Overwriting is acceptable for this challenge.

Examples

Example 1:

Input: A request to `/hello` without an X-Request-ID header.
Output: A response to `/hello` with an X-Request-ID header containing a UUID and the request ID stored in the context.
Explanation: The middleware generates a UUID, adds it to the header, and stores it in the context.

Example 2:

Input: A request to `/hello` with an existing X-Request-ID header.
Output: A response to `/hello` with an X-Request-ID header containing a *new* UUID (overwriting the existing one) and the new request ID stored in the context.
Explanation: The middleware generates a new UUID, overwrites the header, and stores the new ID in the context.

Example 3: (Edge Case)

Input: A nil http.Handler passed to the middleware.
Output: The middleware returns itself (or panics with a clear error message).
Explanation: The middleware handles the case where the input handler is nil.

Constraints

  • UUID Generation: Use the github.com/google/uuid package for UUID generation. You'll need to install it: go get github.com/google/uuid
  • Performance: The middleware should add minimal overhead to the request processing pipeline. Avoid unnecessary allocations or complex operations.
  • Input Format: The input is an http.Handler.
  • Output Format: The output is an http.Handler.
  • Error Handling: The middleware should not panic. Handle potential errors gracefully.

Notes

  • The context.WithValue function is key to making the request ID available to downstream handlers.
  • Consider using a closure to encapsulate the middleware logic.
  • Think about how to test your middleware effectively. You'll need to verify that the header is added correctly and that the request ID is stored in the context.
  • This challenge focuses on the core functionality of request ID injection. More advanced implementations might include logging, tracing integration, and propagation of request IDs across service boundaries.
Loading editor...
go