Overview
Theproxy middleware provides reverse proxy functionality, forwarding requests to upstream servers. It supports load balancing, request modification, and response handling.
Installation
Quick Start
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
Target | *url.URL | required | Upstream server URL |
Rewrite | func(string) string | - | Path rewriter |
ModifyRequest | func(*http.Request) | - | Request modifier |
ModifyResponse | func(*http.Response) error | - | Response modifier |
Transport | http.RoundTripper | Default | HTTP transport |
Timeout | time.Duration | 30s | Request timeout |
PreserveHost | bool | false | Keep original Host header |
ErrorHandler | func(*mizu.Ctx, error) error | - | Error handler |
Examples
Basic Proxy
Path Rewriting
Load Balancing
Request Modification
Response Modification
Preserve Host Header
Custom Timeout
API Reference
Headers Added
| Header | Value |
|---|---|
X-Forwarded-For | Client IP chain |
X-Forwarded-Host | Original host |
X-Forwarded-Proto | http or https |
Technical Details
Request Flow
-
URL Construction: The target URL is built by combining the upstream target with the request path. If a
Rewritefunction is provided, it transforms the path before joining. -
Path Joining: The
singleJoiningSlashhelper ensures proper path construction by handling slash prefixes/suffixes correctly, preventing issues like double slashes or missing slashes. - Request Creation: A new HTTP request is created with the same method, context, and body as the original request.
-
Header Propagation: All headers from the original request are copied to the proxy request using the
copyHeadersfunction, which preserves multi-value headers. -
Forwarded Headers: The middleware automatically sets standard forwarding headers:
X-Forwarded-For: Appends client IP to any existing value (creates a chain)X-Forwarded-Host: Sets the original hostX-Forwarded-Proto: Setshttpsorhttpbased on TLS presence
-
Host Header Handling: By default, the Host header is set to the upstream target’s host. When
PreserveHostis true, the original Host header is preserved. -
Request Modification: If
ModifyRequestis provided, it’s called before sending the request, allowing custom header manipulation or other modifications. -
HTTP Client Configuration:
- Uses configurable transport (defaults to
http.DefaultTransport) - Applies the specified timeout (defaults to 30 seconds)
- Disables automatic redirect following (
CheckRedirectreturnsErrUseLastResponse)
- Uses configurable transport (defaults to
-
Response Handling: After receiving the upstream response:
ModifyResponsecallback is invoked if configured- Response headers are copied to the client
- Status code is written
- Response body is streamed to the client using
io.Copy
-
Error Handling: Errors are passed to the custom
ErrorHandlerif configured, otherwise returns a 502 Bad Gateway response.
Load Balancer Implementation
TheBalancer function implements simple round-robin load balancing:
- Maintains a counter for selecting the next upstream
- Uses modulo arithmetic to cycle through targets
- Counter is not thread-safe but provides good-enough distribution for most use cases
- Each request creates a new proxy middleware instance with the selected target
Performance Considerations
- Streaming: Response body is streamed using
io.Copy, avoiding buffering large responses in memory - Connection Reuse: Uses
http.DefaultTransportby default, which includes connection pooling - Context Propagation: Request context is preserved, enabling timeout and cancellation propagation
- Header Copying: Headers are copied efficiently without additional allocations for single-value headers
Best Practices
- Set Appropriate Timeouts: Configure timeouts based on your upstream service characteristics to prevent hanging requests.
- Error Handling: Implement custom error handlers for better error reporting and monitoring.
-
Security: Be cautious with
ModifyRequestto avoid exposing sensitive headers to untrusted upstreams. -
Path Rewriting: Use the
Rewritefunction for API versioning or routing transformations. - Load Balancing: For production load balancing, consider implementing health checks and weighted distributions.
Testing
The proxy middleware includes comprehensive test coverage for all functionality:| Test Case | Description | Expected Behavior |
|---|---|---|
TestNew | Basic proxy functionality | Forwards request to upstream, returns upstream response with headers |
TestWithOptions_Rewrite | Path rewriting with custom function | Transforms request path before forwarding (e.g., /users → /api/v2/users) |
TestWithOptions_ModifyRequest | Request modification callback | Custom headers are added to upstream request |
TestWithOptions_ModifyResponse | Response modification callback | Custom headers are added to client response |
TestWithOptions_PreserveHost | Host header preservation | Original Host header is preserved when PreserveHost is true |
TestWithOptions_ErrorHandler | Custom error handling | Custom error handler is invoked on proxy failure |
TestWithOptions_QueryString | Query parameter forwarding | Query strings are preserved and forwarded to upstream |
TestWithOptions_POST | POST request handling | POST requests with body are proxied correctly |
TestNew_InvalidURL | Invalid target URL validation | Panics with descriptive error on invalid URL |
TestWithOptions_NoTarget | Missing target validation | Panics when target is not provided |
TestBalancer | Round-robin load balancing | Distributes requests across multiple upstreams in rotation |
TestBalancer_Empty | Empty balancer targets validation | Panics when no targets are provided |