reverseproxy

package module
v0.0.0-...-4912690 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 28, 2026 License: MIT Imports: 23 Imported by: 1

README

goutils/http/reverseproxy

Enhanced HTTP reverse proxy with WebSocket and HTTP/2 support, integrated with godoxy's logging and access control systems.

Overview

This package extends Go's net/http/httputil/reverse_proxy with:

  • Integrated logging: Uses godoxy's zerolog logger for structured logging
  • Access logging: Built-in support for accesslog.AccessLogger
  • Scheme mismatch handling: Custom callback for HTTP/HTTPS scheme mismatches
  • Enhanced header manipulation: X-Forwarded headers, WebSocket header normalization
  • HTTP/2 h2c support: Cleartext HTTP/2 support
  • Error suppression: Suppresses certain unimportant/expected errors to prevent logging them
  • Performance optimizations: Uses CopyCloseContext with sync.Pool for efficient body copying, reducing GC pressure

Key Differences from stdlib

Feature stdlib httputil/reverse_proxy This Package
Logging log.Printf zerolog.Logger
Access logging Not supported AccessLogger interface
Scheme mismatch Not supported OnSchemeMisMatch callback
X-Forwarded headers Manual via Director Built-in SetXForwarded()
WebSocket headers Basic handling Normalized casing
Body copy io.Copy CopyCloseContext with buffer pool

Integration with GoDoxy

import (
    "github.com/yusing/godoxy/goutils/http/reverseproxy"
    "github.com/yusing/godoxy/internal/logging"
)

// Create proxy with godoxy's logger
rp := reverseproxy.NewReverseProxy("backend", target, nil)
rp.Logger = logging.Logger  // Uses godoxy's zerolog logger
rp.AccessLogger = logging.AccessLogger  // Uses godoxy's access logging

API Reference

ReverseProxy
type ReverseProxy struct {
    zerolog.Logger  // Embedded for structured logging
    Transport http.RoundTripper
    ModifyResponse func(*http.Response) error
    AccessLogger accesslog.AccessLogger
    HandlerFunc http.HandlerFunc
    OnSchemeMisMatch func() bool  // Called on HTTP/HTTPS scheme mismatch
    TargetName string
    TargetURL *url.URL
}
ProxyRequest
type ProxyRequest struct {
    In *http.Request   // Incoming request (read-only)
    Out *http.Request  // Outgoing request (modifiable)
}
Functions
NewReverseProxy
func NewReverseProxy(name string, target *url.URL, transport http.RoundTripper) *ReverseProxy

Creates a proxy. Transport can be nil to use default.

SetXForwarded
func (p *ProxyRequest) SetXForwarded()

Sets all X-Forwarded headers (For, Host, Proto, Method, URI, Port) on the outbound request.

Handler
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request)

Main request handler with automatic:

  • Hop-by-hop header removal
  • X-Forwarded header setting
  • WebSocket upgrade handling
  • Response modification

Usage Examples

Basic Setup
target, _ := url.Parse("http://localhost:8080")
rp := reverseproxy.NewReverseProxy("backend", target, nil)
http.Handle("/", rp)
With GoDoxy Logging
import "github.com/yusing/godoxy/internal/logging"

rp := reverseproxy.NewReverseProxy("backend", target, nil)
rp.Logger = logging.With().Str("component", "reverse_proxy").Logger()
With Scheme Mismatch Detection
rp := reverseproxy.NewReverseProxy("backend", target, nil)
rp.OnSchemeMisMatch = func() bool {
    rp.Logger.Warn().Msg("Scheme mismatch detected")
    return true  // Retry with different scheme
}
Custom Request Rewrite
rewriteFunc := func(pr *reverseproxy.ProxyRequest) {
    pr.SetXForwarded()
    pr.Out.URL.Path = strings.TrimPrefix(pr.Out.URL.Path, "/api")
}

Performance

  • Buffer pooling: Uses CopyCloseContext with sync.Pool for efficient body copying, reducing GC pressure

  • Context propagation: Properly handles request cancellation via context

  • HTTP/1.1: Full support

  • HTTP/2: h2c cleartext support

  • WebSocket: Automatic upgrade handling with header normalization

Header Handling

  1. Removes hop-by-hop headers: Connection, Transfer-Encoding, Upgrade, etc.
  2. Sets X-Forwarded headers automatically
  3. Removes service headers: X-Powered-By, Server
  4. Normalizes WebSocket header casing

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsPrint

func IsPrint(s string) bool

Types

type ProxyRequest

type ProxyRequest struct {
	// In is the request received by the proxy.
	// The Rewrite function must not modify In.
	In *http.Request

	// Out is the request which will be sent by the proxy.
	// The Rewrite function may modify or replace this request.
	// Hop-by-hop headers are removed from this request
	// before Rewrite is called.
	Out *http.Request
}

A ProxyRequest contains a request to be rewritten by a ReverseProxy.

type ReverseProxy

type ReverseProxy struct {
	zerolog.Logger

	// The transport used to perform proxy requests.
	Transport http.RoundTripper

	// ModifyResponse is an optional function that modifies the
	// Response from the backend. It is called if the backend
	// returns a response at all, with any HTTP status code.
	// If the backend is unreachable, the optional ErrorHandler is
	// called before ModifyResponse.
	//
	// If ModifyResponse returns an error, ErrorHandler is called
	// with its error value. If ErrorHandler is nil, its default
	// implementation is used.
	ModifyResponse func(*http.Response) error
	AccessLogger   accesslog.AccessLogger

	HandlerFunc http.HandlerFunc

	OnSchemeMisMatch func() (retry bool)

	TargetName string
	TargetURL  *url.URL
	// contains filtered or unexported fields
}

ReverseProxy is an HTTP Handler that takes an incoming request and sends it to another server, proxying the response back to the client.

1xx responses are forwarded to the client if the underlying transport supports ClientTrace.Got1xxResponse.

func NewReverseProxy

func NewReverseProxy(name string, target *url.URL, transport http.RoundTripper) *ReverseProxy

NewReverseProxy returns a new ReverseProxy that routes URLs to the scheme, host, and base path provided in target. If the target's path is "/base" and the incoming request was for "/dir", the target request will be for /base/dir.

func (*ReverseProxy) ServeHTTP

func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL