package deps
import (
"net/http"
"time"
"go.uber.org/zap"
)
type Transport struct {
Base http.RoundTripper
Log *zap.Logger
ReqID func() string
}
func (t Transport) RoundTrip(req *http.Request) (*http.Response, error) {
base := t.Base
if base == nil {
base = http.DefaultTransport
}
if t.ReqID != nil {
req.Header.Set("X-Request-Id", t.ReqID())
}
start := time.Now()
resp, err := base.RoundTrip(req)
if t.Log != nil {
t.Log.Info("http.client",
zap.String("method", req.Method),
zap.String("host", req.URL.Host),
zap.Duration("duration", time.Since(start)),
zap.Error(err),
)
}
return resp, err
}
When multiple services call the same upstream, I like a custom http.RoundTripper to centralize cross-cutting behavior: inject headers, measure duration, and apply consistent redaction rules. This keeps call sites clean and prevents copy/paste mistakes like forgetting to set User-Agent or missing an auth header for a new endpoint. The wrapper below adds an X-Request-Id and records a simple log line with duration; in real systems I’d record a Prometheus histogram and emit trace spans. The important design detail is to preserve the underlying transport so connection pooling still works; you wrap Transport, you don’t replace it with ad-hoc http.Clients. This pattern scales nicely as you add retries, rate limiting, and circuit breakers.
Related snips
package api
import (
"net/http"
"runtime/debug"
)
Expose build metadata for debugging deploys
export interface RetryOptions {
retries: number;
baseMs: number;
maxMs: number;
signal?: AbortSignal;
onRetry?: (attempt: number, delay: number, err: unknown) => void;
Exponential backoff with jitter for retries
package dbutil
import (
"context"
"github.com/jackc/pgconn"
Retry Postgres serialization failures with bounded attempts
use tracing::{info, instrument};
#[instrument]
fn process_request(user_id: u64) {
info!(user_id, "Processing request");
// Work happens here
tracing for structured logging and distributed tracing
package files
import (
"context"
"time"
Presigned S3 upload URLs (AWS SDK v2)
package deps
import (
"net"
"net/http"
"time"
HTTP client tuned for production: timeouts, transport, and connection reuse
Share this code
Here's the card — post it anywhere.