goproxy
goproxy copied to clipboard
Use http.RoundTripper instead of http.Transport
In ProxyHttpServer we use http.Transport, bit it's implementation of http.RoundTripper
type ProxyHttpServer struct {
// session variable must be aligned in i386
// see http://golang.org/src/pkg/sync/atomic/doc.go#L41
sess int64
// KeepDestinationHeaders indicates the proxy should retain any headers present in the http.Response before proxying
KeepDestinationHeaders bool
// setting Verbose to true will log information on each request sent to the proxy
Verbose bool
Logger Logger
NonproxyHandler http.Handler
reqHandlers []ReqHandler
respHandlers []RespHandler
httpsHandlers []HttpsHandler
Tr *http.Transport
// ConnectDial will be used to create TCP connections for CONNECT requests
// if nil Tr.Dial will be used
ConnectDial func(network string, addr string) (net.Conn, error)
ConnectDialWithReq func(req *http.Request, network string, addr string) (net.Conn, error)
CertStore CertStorage
KeepHeader bool
}
Because of that I can't redefine Tr with my own Round Tripper.
For example I want to to otelhttp.NewTransport(), it returns http.RoundTripper, but I cannot assign it to proxy object.
In such situation I can only use http.Transport, but it doesn't let me intercept requests
Workaround
import (
"context"
"net/http"
"github.com/elazarl/goproxy"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)
func main() {
gproxy := goproxy.NewProxyHttpServer()
otelTr := otelhttp.NewTransport(gproxy.Tr)
// Wrap the transport with OpenTelemetry instrumentation
gproxy.OnRequest().DoFunc(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
ctx.RoundTripper = goproxy.RoundTripperFunc(func(req *http.Request, ctx2 *goproxy.ProxyCtx) (*http.Response, error) {
return otelTr.RoundTrip(req)
})
return req, nil
})
}
But I'd Prefer to create and set transport once, it would be clear and understandable.
👍 for this issue. It'd make it easier to test/mock/increase flexibility.