text: // Copyright 2014 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  package oauth2
  
  import (
  	"errors"
  	"io"
  	"net/http"
  	"sync"
  )
  
  // Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests,
  // wrapping a base RoundTripper and adding an Authorization header
  // with a token from the supplied Sources.
  //
  // Transport is a low-level mechanism. Most code will use the
  // higher-level Config.Client method instead.
  type Transport struct {
  	// Source supplies the token to add to outgoing requests'
  	// Authorization headers.
  	Source TokenSource
  
  	// Base is the base RoundTripper used to make HTTP requests.
  	// If nil, http.DefaultTransport is used.
  	Base http.RoundTripper
  
  	mu     sync.Mutex                      // guards modReq
  	modReq map[*http.Request]*http.Request // original -> modified
  }
  
  // RoundTrip authorizes and authenticates the request with an
  // access token. If no token exists or token is expired,
  // tries to refresh/fetch a new token.
  func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
  	if t.Source == nil {
  		return nil, errors.New("oauth2: Transport's Source is nil")
  	}
  	token, err := t.Source.Token()
  	if err != nil {
  		return nil, err
  	}
  
  	req2 := cloneRequest(req) // per RoundTripper contract
  	token.SetAuthHeader(req2)
  	t.setModReq(req, req2)
  	res, err := t.base().RoundTrip(req2)
  	if err != nil {
  		t.setModReq(req, nil)
  		return nil, err
  	}
  	res.Body = &onEOFReader{
  		rc: res.Body,
  		fn: func() { t.setModReq(req, nil) },
  	}
  	return res, nil
  }
  
  // CancelRequest cancels an in-flight request by closing its connection.
  func (t *Transport) CancelRequest(req *http.Request) {
  	type canceler interface {
  		CancelRequest(*http.Request)
  	}
  	if cr, ok := t.base().(canceler); ok {
  		t.mu.Lock()
  		modReq := t.modReq[req]
  		delete(t.modReq, req)
  		t.mu.Unlock()
  		cr.CancelRequest(modReq)
  	}
  }
  
  func (t *Transport) base() http.RoundTripper {
  	if t.Base != nil {
  		return t.Base
  	}
  	return http.DefaultTransport
  }
  
  func (t *Transport) setModReq(orig, mod *http.Request) {
  	t.mu.Lock()
  	defer t.mu.Unlock()
  	if t.modReq == nil {
  		t.modReq = make(map[*http.Request]*http.Request)
  	}
  	if mod == nil {
  		delete(t.modReq, orig)
  	} else {
  		t.modReq[orig] = mod
  	}
  }
  
  // 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
  	// deep copy of the Header
  	r2.Header = make(http.Header, len(r.Header))
  	for k, s := range r.Header {
  		r2.Header[k] = append([]string(nil), s...)
  	}
  	return r2
  }
  
  type onEOFReader struct {
  	rc io.ReadCloser
  	fn func()
  }
  
  func (r *onEOFReader) Read(p []byte) (n int, err error) {
  	n, err = r.rc.Read(p)
  	if err == io.EOF {
  		r.runFunc()
  	}
  	return
  }
  
  func (r *onEOFReader) Close() error {
  	err := r.rc.Close()
  	r.runFunc()
  	return err
  }
  
  func (r *onEOFReader) runFunc() {
  	if fn := r.fn; fn != nil {
  		fn()
  		r.fn = nil
  	}
  }
  