...

Source file src/golang.org/x/oauth2/transport.go

Documentation: golang.org/x/oauth2

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package oauth2
     6  
     7  import (
     8  	"errors"
     9  	"log"
    10  	"net/http"
    11  	"sync"
    12  )
    13  
    14  // Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests,
    15  // wrapping a base RoundTripper and adding an Authorization header
    16  // with a token from the supplied Sources.
    17  //
    18  // Transport is a low-level mechanism. Most code will use the
    19  // higher-level Config.Client method instead.
    20  type Transport struct {
    21  	// Source supplies the token to add to outgoing requests'
    22  	// Authorization headers.
    23  	Source TokenSource
    24  
    25  	// Base is the base RoundTripper used to make HTTP requests.
    26  	// If nil, http.DefaultTransport is used.
    27  	Base http.RoundTripper
    28  }
    29  
    30  // RoundTrip authorizes and authenticates the request with an
    31  // access token from Transport's Source.
    32  func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
    33  	reqBodyClosed := false
    34  	if req.Body != nil {
    35  		defer func() {
    36  			if !reqBodyClosed {
    37  				req.Body.Close()
    38  			}
    39  		}()
    40  	}
    41  
    42  	if t.Source == nil {
    43  		return nil, errors.New("oauth2: Transport's Source is nil")
    44  	}
    45  	token, err := t.Source.Token()
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	req2 := cloneRequest(req) // per RoundTripper contract
    51  	token.SetAuthHeader(req2)
    52  
    53  	// req.Body is assumed to be closed by the base RoundTripper.
    54  	reqBodyClosed = true
    55  	return t.base().RoundTrip(req2)
    56  }
    57  
    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.
    64  func (t *Transport) CancelRequest(req *http.Request) {
    65  	cancelOnce.Do(func() {
    66  		log.Printf("deprecated: golang.org/x/oauth2: Transport.CancelRequest no longer does anything; use contexts")
    67  	})
    68  }
    69  
    70  func (t *Transport) base() http.RoundTripper {
    71  	if t.Base != nil {
    72  		return t.Base
    73  	}
    74  	return http.DefaultTransport
    75  }
    76  
    77  // cloneRequest returns a clone of the provided *http.Request.
    78  // The clone is a shallow copy of the struct and its Header map.
    79  func cloneRequest(r *http.Request) *http.Request {
    80  	// shallow copy of the struct
    81  	r2 := new(http.Request)
    82  	*r2 = *r
    83  	// deep copy of the Header
    84  	r2.Header = make(http.Header, len(r.Header))
    85  	for k, s := range r.Header {
    86  		r2.Header[k] = append([]string(nil), s...)
    87  	}
    88  	return r2
    89  }
    90  

View as plain text