50 lines
1.2 KiB
Go
50 lines
1.2 KiB
Go
package transport
|
|
|
|
import (
|
|
"net/http"
|
|
)
|
|
|
|
// Decorator is an http.RoundTripper that makes HTTP requests,
|
|
// wrapping a base RoundTripper and modifying given base requests.
|
|
type Decorator struct {
|
|
// Decorator modifies the outgoing request
|
|
Decorator func(*http.Request) error
|
|
|
|
// Base is the base RoundTripper used to make HTTP requests.
|
|
Base http.RoundTripper
|
|
}
|
|
|
|
// RoundTrip decorates the request using the Decorator.
|
|
func (t *Decorator) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
if t.Decorator == nil {
|
|
return t.Base.RoundTrip(req)
|
|
}
|
|
|
|
reqBodyClosed := false
|
|
if req.Body != nil {
|
|
defer func() {
|
|
if !reqBodyClosed {
|
|
req.Body.Close()
|
|
}
|
|
}()
|
|
}
|
|
|
|
req2 := cloneRequest(req) // per RoundTripper contract
|
|
if err := t.Decorator(req2); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// req.Body is assumed to be closed by the base RoundTripper.
|
|
reqBodyClosed = true
|
|
return t.Base.RoundTrip(req2)
|
|
}
|
|
|
|
// cloneRequest returns a clone of the provided *http.Request.
|
|
// The clone is a shallow copy of the struct and its Header map.
|
|
func cloneRequest(r *http.Request) *http.Request {
|
|
// shallow copy of the struct
|
|
r2 := new(http.Request)
|
|
*r2 = *r
|
|
r2.Header = r.Header.Clone()
|
|
return r2
|
|
}
|