9 // RequestModifier represents an object which will do an inplace
10 // modification of an HTTP request.
11 type RequestModifier interface {
12 ModifyRequest(*http.Request) error
15 type headerModifier http.Header
17 // NewHeaderRequestModifier returns a new RequestModifier which will
18 // add the given headers to a request.
19 func NewHeaderRequestModifier(header http.Header) RequestModifier {
20 return headerModifier(header)
23 func (h headerModifier) ModifyRequest(req *http.Request) error {
24 for k, s := range http.Header(h) {
25 req.Header[k] = append(req.Header[k], s...)
31 // NewTransport creates a new transport which will apply modifiers to
32 // the request on a RoundTrip call.
33 func NewTransport(base http.RoundTripper, modifiers ...RequestModifier) http.RoundTripper {
40 // transport is an http.RoundTripper that makes HTTP requests after
41 // copying and modifying the request
42 type transport struct {
43 Modifiers []RequestModifier
44 Base http.RoundTripper
46 mu sync.Mutex // guards modReq
47 modReq map[*http.Request]*http.Request // original -> modified
50 // RoundTrip authorizes and authenticates the request with an
51 // access token. If no token exists or token is expired,
52 // tries to refresh/fetch a new token.
53 func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
54 req2 := cloneRequest(req)
55 for _, modifier := range t.Modifiers {
56 if err := modifier.ModifyRequest(req2); err != nil {
61 t.setModReq(req, req2)
62 res, err := t.base().RoundTrip(req2)
67 res.Body = &onEOFReader{
69 fn: func() { t.setModReq(req, nil) },
74 // CancelRequest cancels an in-flight request by closing its connection.
75 func (t *transport) CancelRequest(req *http.Request) {
76 type canceler interface {
77 CancelRequest(*http.Request)
79 if cr, ok := t.base().(canceler); ok {
81 modReq := t.modReq[req]
84 cr.CancelRequest(modReq)
88 func (t *transport) base() http.RoundTripper {
92 return http.DefaultTransport
95 func (t *transport) setModReq(orig, mod *http.Request) {
99 t.modReq = make(map[*http.Request]*http.Request)
102 delete(t.modReq, orig)
108 // cloneRequest returns a clone of the provided *http.Request.
109 // The clone is a shallow copy of the struct and its Header map.
110 func cloneRequest(r *http.Request) *http.Request {
111 // shallow copy of the struct
112 r2 := new(http.Request)
114 // deep copy of the Header
115 r2.Header = make(http.Header, len(r.Header))
116 for k, s := range r.Header {
117 r2.Header[k] = append([]string(nil), s...)
123 type onEOFReader struct {
128 func (r *onEOFReader) Read(p []byte) (n int, err error) {
129 n, err = r.rc.Read(p)
136 func (r *onEOFReader) Close() error {
142 func (r *onEOFReader) runFunc() {
143 if fn := r.fn; fn != nil {