transport.go (2403B)
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 }