Reverse Proxy Handler
Forward requests with httputil.ReverseProxy, add a forwarded-host header, strip internal headers, and return 502 on failure.
Code
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/http/httputil"
"net/url"
"strings"
)
func NewReverseProxy(target *url.URL) *httputil.ReverseProxy {
proxy := httputil.NewSingleHostReverseProxy(target)
originalDirector := proxy.Director
proxy.Director = func(request *http.Request) {
originalDirector(request)
request.Header.Set("X-Forwarded-Host", request.Host)
request.Header.Del("X-Internal-Debug")
}
proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
fmt.Println("proxy error:", err)
http.Error(w, "upstream unavailable", http.StatusBadGateway)
}
return proxy
}
func main() {
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "path=%s host=%s", r.URL.Path, r.Header.Get("X-Forwarded-Host"))
}))
defer backend.Close()
target, err := url.Parse(backend.URL)
if err != nil {
panic(err)
}
front := httptest.NewServer(NewReverseProxy(target))
defer front.Close()
response, err := http.Get(front.URL + "/api/items?page=2")
if err != nil {
panic(err)
}
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
if err != nil {
panic(err)
}
fmt.Println("status:", response.StatusCode)
fmt.Println("body:", strings.TrimSpace(string(body)))
}Report a problem with this exampleOpens a pre-filled issue on GitHub.