You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

transport.go 2.3KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. package oauth2
  5. import (
  6. "errors"
  7. "log"
  8. "net/http"
  9. "sync"
  10. )
  11. // Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests,
  12. // wrapping a base RoundTripper and adding an Authorization header
  13. // with a token from the supplied Sources.
  14. //
  15. // Transport is a low-level mechanism. Most code will use the
  16. // higher-level Config.Client method instead.
  17. type Transport struct {
  18. // Source supplies the token to add to outgoing requests'
  19. // Authorization headers.
  20. Source TokenSource
  21. // Base is the base RoundTripper used to make HTTP requests.
  22. // If nil, http.DefaultTransport is used.
  23. Base http.RoundTripper
  24. }
  25. // RoundTrip authorizes and authenticates the request with an
  26. // access token from Transport's Source.
  27. func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
  28. reqBodyClosed := false
  29. if req.Body != nil {
  30. defer func() {
  31. if !reqBodyClosed {
  32. req.Body.Close()
  33. }
  34. }()
  35. }
  36. if t.Source == nil {
  37. return nil, errors.New("oauth2: Transport's Source is nil")
  38. }
  39. token, err := t.Source.Token()
  40. if err != nil {
  41. return nil, err
  42. }
  43. req2 := cloneRequest(req) // per RoundTripper contract
  44. token.SetAuthHeader(req2)
  45. // req.Body is assumed to be closed by the base RoundTripper.
  46. reqBodyClosed = true
  47. return t.base().RoundTrip(req2)
  48. }
  49. var cancelOnce sync.Once
  50. // CancelRequest does nothing. It used to be a legacy cancellation mechanism
  51. // but now only it only logs on first use to warn that it's deprecated.
  52. //
  53. // Deprecated: use contexts for cancellation instead.
  54. func (t *Transport) CancelRequest(req *http.Request) {
  55. cancelOnce.Do(func() {
  56. log.Printf("deprecated: golang.org/x/oauth2: Transport.CancelRequest no longer does anything; use contexts")
  57. })
  58. }
  59. func (t *Transport) base() http.RoundTripper {
  60. if t.Base != nil {
  61. return t.Base
  62. }
  63. return http.DefaultTransport
  64. }
  65. // cloneRequest returns a clone of the provided *http.Request.
  66. // The clone is a shallow copy of the struct and its Header map.
  67. func cloneRequest(r *http.Request) *http.Request {
  68. // shallow copy of the struct
  69. r2 := new(http.Request)
  70. *r2 = *r
  71. // deep copy of the Header
  72. r2.Header = make(http.Header, len(r.Header))
  73. for k, s := range r.Header {
  74. r2.Header[k] = append([]string(nil), s...)
  75. }
  76. return r2
  77. }