sourcegraph/internal/httpcli/transport.go
Robert Lin 7426570670
httpcli: introduce mutable, wrapped transports (#39775)
Makes our wrapped transports fully unwrappable, such that a pointer to the implementation can be retrieved and replaced, namely with a clone of the underlying *http.Transport. This fixes the issue described in #39702, and removes what seems to be an old workaround around some options not supporting wrapped transports.

Co-authored-by: Molly Weitzel <molly.weitzel@sourcegraph.com>
Co-authored-by: Thorsten Ball <mrnugget@gmail.com>
2022-08-02 13:12:10 +00:00

39 lines
1.3 KiB
Go

package httpcli
import "net/http"
// WrappedTransport can be implemented to allow a wrapped transport to expose its
// underlying transport for modification.
type WrappedTransport interface {
// RoundTripper is the transport implementation that should be exposed.
http.RoundTripper
// Unwrap should provide a pointer to the underlying transport that has been wrapped.
// The returned value should never be nil.
Unwrap() *http.RoundTripper
}
// unwrapAll performs a recursive unwrap on transport until we reach a transport that
// cannot be unwrapped. The pointer to the pointer can be used to replace the underlying
// transport, most commonly by attempting to cast it as an *http.Transport.
//
// WrappedTransport.Unwrap should never return nil, so unwrapAll will never return nil.
func unwrapAll(transport WrappedTransport) *http.RoundTripper {
wrapped := transport.Unwrap()
if unwrappable, ok := (*wrapped).(WrappedTransport); ok {
return unwrapAll(unwrappable)
}
return wrapped
}
// wrappedTransport is an http.RoundTripper that allows the underlying RoundTripper to be
// exposed for modification.
type wrappedTransport struct {
http.RoundTripper
Wrapped http.RoundTripper
}
var _ WrappedTransport = &wrappedTransport{}
func (wt *wrappedTransport) Unwrap() *http.RoundTripper { return &wt.Wrapped }