blob: 90657915fbcf0ea51e8d97858432d793060de436 [file] [log] [blame]
Andrew Gerrand038cb4a2015-08-27 10:42:02 +10001// Copyright 2014 The Go Authors. All rights reserved.
Burcu Doganabc4bcd2014-05-17 17:26:57 +02002// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
Burcu Dogand7c8bcd2014-05-13 21:06:46 +03004
Burcu Doganc32deba2014-05-05 23:54:23 +02005package oauth2
6
7import (
Brad Fitzpatricka5680782014-12-10 10:17:33 +11008 "errors"
Tim Cooper858c2ad2018-06-28 19:10:32 -03009 "log"
Burcu Doganc32deba2014-05-05 23:54:23 +020010 "net/http"
11 "sync"
Burcu Doganc32deba2014-05-05 23:54:23 +020012)
13
Brad Fitzpatricka5680782014-12-10 10:17:33 +110014// 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.
Burcu Dogan0ae3d4e2014-10-27 17:35:35 -070017//
Brad Fitzpatricka5680782014-12-10 10:17:33 +110018// Transport is a low-level mechanism. Most code will use the
19// higher-level Config.Client method instead.
Burcu Doganee772462014-08-13 22:22:35 -070020type Transport struct {
Brad Fitzpatricka5680782014-12-10 10:17:33 +110021 // Source supplies the token to add to outgoing requests'
22 // Authorization headers.
23 Source TokenSource
Burcu Doganc32deba2014-05-05 23:54:23 +020024
Brad Fitzpatricka5680782014-12-10 10:17:33 +110025 // Base is the base RoundTripper used to make HTTP requests.
26 // If nil, http.DefaultTransport is used.
27 Base http.RoundTripper
Burcu Dogan2af52e72014-05-10 09:41:39 +020028}
29
Burcu Doganee772462014-08-13 22:22:35 -070030// RoundTrip authorizes and authenticates the request with an
Tim Cooperec22f462018-05-28 17:23:04 -030031// access token from Transport's Source.
Burcu Doganb8463882014-11-24 17:07:50 -080032func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
Tim Cooper30b72df2018-05-28 18:26:48 -030033 reqBodyClosed := false
34 if req.Body != nil {
35 defer func() {
36 if !reqBodyClosed {
37 req.Body.Close()
38 }
39 }()
40 }
41
Brad Fitzpatricka5680782014-12-10 10:17:33 +110042 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
Burcu Doganc32deba2014-05-05 23:54:23 +020048 }
49
Brad Fitzpatricka5680782014-12-10 10:17:33 +110050 req2 := cloneRequest(req) // per RoundTripper contract
51 token.SetAuthHeader(req2)
Tim Cooper30b72df2018-05-28 18:26:48 -030052
Tim Cooper858c2ad2018-06-28 19:10:32 -030053 // req.Body is assumed to be closed by the base RoundTripper.
Tim Cooper30b72df2018-05-28 18:26:48 -030054 reqBodyClosed = true
Tim Cooper858c2ad2018-06-28 19:10:32 -030055 return t.base().RoundTrip(req2)
Burcu Doganc32deba2014-05-05 23:54:23 +020056}
57
Tim Cooper858c2ad2018-06-28 19:10:32 -030058var 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.
Brad Fitzpatricka5680782014-12-10 10:17:33 +110064func (t *Transport) CancelRequest(req *http.Request) {
Tim Cooper858c2ad2018-06-28 19:10:32 -030065 cancelOnce.Do(func() {
66 log.Printf("deprecated: golang.org/x/oauth2: Transport.CancelRequest no longer does anything; use contexts")
67 })
Burcu Doganc32deba2014-05-05 23:54:23 +020068}
69
Brad Fitzpatricka5680782014-12-10 10:17:33 +110070func (t *Transport) base() http.RoundTripper {
71 if t.Base != nil {
72 return t.Base
73 }
74 return http.DefaultTransport
75}
76
Burcu Doganc32deba2014-05-05 23:54:23 +020077// cloneRequest returns a clone of the provided *http.Request.
78// The clone is a shallow copy of the struct and its Header map.
79func 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
Brad Fitzpatricka5680782014-12-10 10:17:33 +110084 r2.Header = make(http.Header, len(r.Header))
Burcu Doganc32deba2014-05-05 23:54:23 +020085 for k, s := range r.Header {
Brad Fitzpatricka5680782014-12-10 10:17:33 +110086 r2.Header[k] = append([]string(nil), s...)
Burcu Doganc32deba2014-05-05 23:54:23 +020087 }
88 return r2
89}