vendor/golang.org/x/oauth2/transport.go
changeset 251 1c52a0eeb952
parent 242 2a9ec03fe5a1
equal deleted inserted replaced
250:c040f992052f 251:1c52a0eeb952
     4 
     4 
     5 package oauth2
     5 package oauth2
     6 
     6 
     7 import (
     7 import (
     8 	"errors"
     8 	"errors"
     9 	"io"
     9 	"log"
    10 	"net/http"
    10 	"net/http"
    11 	"sync"
    11 	"sync"
    12 )
    12 )
    13 
    13 
    14 // Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests,
    14 // Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests,
    23 	Source TokenSource
    23 	Source TokenSource
    24 
    24 
    25 	// Base is the base RoundTripper used to make HTTP requests.
    25 	// Base is the base RoundTripper used to make HTTP requests.
    26 	// If nil, http.DefaultTransport is used.
    26 	// If nil, http.DefaultTransport is used.
    27 	Base http.RoundTripper
    27 	Base http.RoundTripper
    28 
       
    29 	mu     sync.Mutex                      // guards modReq
       
    30 	modReq map[*http.Request]*http.Request // original -> modified
       
    31 }
    28 }
    32 
    29 
    33 // RoundTrip authorizes and authenticates the request with an
    30 // RoundTrip authorizes and authenticates the request with an
    34 // access token from Transport's Source.
    31 // access token from Transport's Source.
    35 func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
    32 func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
    50 		return nil, err
    47 		return nil, err
    51 	}
    48 	}
    52 
    49 
    53 	req2 := cloneRequest(req) // per RoundTripper contract
    50 	req2 := cloneRequest(req) // per RoundTripper contract
    54 	token.SetAuthHeader(req2)
    51 	token.SetAuthHeader(req2)
    55 	t.setModReq(req, req2)
       
    56 	res, err := t.base().RoundTrip(req2)
       
    57 
    52 
    58 	// req.Body is assumed to have been closed by the base RoundTripper.
    53 	// req.Body is assumed to be closed by the base RoundTripper.
    59 	reqBodyClosed = true
    54 	reqBodyClosed = true
    60 
    55 	return t.base().RoundTrip(req2)
    61 	if err != nil {
       
    62 		t.setModReq(req, nil)
       
    63 		return nil, err
       
    64 	}
       
    65 	res.Body = &onEOFReader{
       
    66 		rc: res.Body,
       
    67 		fn: func() { t.setModReq(req, nil) },
       
    68 	}
       
    69 	return res, nil
       
    70 }
    56 }
    71 
    57 
    72 // CancelRequest cancels an in-flight request by closing its connection.
    58 var cancelOnce sync.Once
       
    59 
       
    60 // CancelRequest does nothing. It used to be a legacy cancellation mechanism
       
    61 // but now only it only logs on first use to warn that it's deprecated.
       
    62 //
       
    63 // Deprecated: use contexts for cancellation instead.
    73 func (t *Transport) CancelRequest(req *http.Request) {
    64 func (t *Transport) CancelRequest(req *http.Request) {
    74 	type canceler interface {
    65 	cancelOnce.Do(func() {
    75 		CancelRequest(*http.Request)
    66 		log.Printf("deprecated: golang.org/x/oauth2: Transport.CancelRequest no longer does anything; use contexts")
    76 	}
    67 	})
    77 	if cr, ok := t.base().(canceler); ok {
       
    78 		t.mu.Lock()
       
    79 		modReq := t.modReq[req]
       
    80 		delete(t.modReq, req)
       
    81 		t.mu.Unlock()
       
    82 		cr.CancelRequest(modReq)
       
    83 	}
       
    84 }
    68 }
    85 
    69 
    86 func (t *Transport) base() http.RoundTripper {
    70 func (t *Transport) base() http.RoundTripper {
    87 	if t.Base != nil {
    71 	if t.Base != nil {
    88 		return t.Base
    72 		return t.Base
    89 	}
    73 	}
    90 	return http.DefaultTransport
    74 	return http.DefaultTransport
    91 }
       
    92 
       
    93 func (t *Transport) setModReq(orig, mod *http.Request) {
       
    94 	t.mu.Lock()
       
    95 	defer t.mu.Unlock()
       
    96 	if t.modReq == nil {
       
    97 		t.modReq = make(map[*http.Request]*http.Request)
       
    98 	}
       
    99 	if mod == nil {
       
   100 		delete(t.modReq, orig)
       
   101 	} else {
       
   102 		t.modReq[orig] = mod
       
   103 	}
       
   104 }
    75 }
   105 
    76 
   106 // cloneRequest returns a clone of the provided *http.Request.
    77 // cloneRequest returns a clone of the provided *http.Request.
   107 // The clone is a shallow copy of the struct and its Header map.
    78 // The clone is a shallow copy of the struct and its Header map.
   108 func cloneRequest(r *http.Request) *http.Request {
    79 func cloneRequest(r *http.Request) *http.Request {
   114 	for k, s := range r.Header {
    85 	for k, s := range r.Header {
   115 		r2.Header[k] = append([]string(nil), s...)
    86 		r2.Header[k] = append([]string(nil), s...)
   116 	}
    87 	}
   117 	return r2
    88 	return r2
   118 }
    89 }
   119 
       
   120 type onEOFReader struct {
       
   121 	rc io.ReadCloser
       
   122 	fn func()
       
   123 }
       
   124 
       
   125 func (r *onEOFReader) Read(p []byte) (n int, err error) {
       
   126 	n, err = r.rc.Read(p)
       
   127 	if err == io.EOF {
       
   128 		r.runFunc()
       
   129 	}
       
   130 	return
       
   131 }
       
   132 
       
   133 func (r *onEOFReader) Close() error {
       
   134 	err := r.rc.Close()
       
   135 	r.runFunc()
       
   136 	return err
       
   137 }
       
   138 
       
   139 func (r *onEOFReader) runFunc() {
       
   140 	if fn := r.fn; fn != nil {
       
   141 		fn()
       
   142 		r.fn = nil
       
   143 	}
       
   144 }