goproxy icon indicating copy to clipboard operation
goproxy copied to clipboard

Use http.RoundTripper instead of http.Transport

Open paraddise opened this issue 6 months ago • 2 comments

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

paraddise avatar Aug 18 '25 14:08 paraddise

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.

paraddise avatar Aug 18 '25 14:08 paraddise

👍 for this issue. It'd make it easier to test/mock/increase flexibility.

jeffwidman avatar Dec 03 '25 23:12 jeffwidman