aboutsummaryrefslogtreecommitdiff
path: root/httputil/transport.go
diff options
context:
space:
mode:
Diffstat (limited to 'httputil/transport.go')
-rw-r--r--httputil/transport.go87
1 files changed, 87 insertions, 0 deletions
diff --git a/httputil/transport.go b/httputil/transport.go
new file mode 100644
index 0000000..fdad3b4
--- /dev/null
+++ b/httputil/transport.go
@@ -0,0 +1,87 @@
1// Copyright 2015 The Go Authors. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file or at
5// https://developers.google.com/open-source/licenses/bsd.
6
7// This file implements a http.RoundTripper that authenticates
8// requests issued against api.github.com endpoint.
9
10package httputil
11
12import (
13 "net/http"
14 "net/url"
15)
16
17// AuthTransport is an implementation of http.RoundTripper that authenticates
18// with the GitHub API.
19//
20// When both a token and client credentials are set, the latter is preferred.
21type AuthTransport struct {
22 UserAgent string
23 GithubToken string
24 GithubClientID string
25 GithubClientSecret string
26 Base http.RoundTripper
27}
28
29// RoundTrip implements the http.RoundTripper interface.
30func (t *AuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
31 var reqCopy *http.Request
32 if t.UserAgent != "" {
33 reqCopy = copyRequest(req)
34 reqCopy.Header.Set("User-Agent", t.UserAgent)
35 }
36 if req.URL.Host == "api.github.com" && req.URL.Scheme == "https" {
37 switch {
38 case t.GithubClientID != "" && t.GithubClientSecret != "":
39 if reqCopy == nil {
40 reqCopy = copyRequest(req)
41 }
42 if reqCopy.URL.RawQuery == "" {
43 reqCopy.URL.RawQuery = "client_id=" + t.GithubClientID + "&client_secret=" + t.GithubClientSecret
44 } else {
45 reqCopy.URL.RawQuery += "&client_id=" + t.GithubClientID + "&client_secret=" + t.GithubClientSecret
46 }
47 case t.GithubToken != "":
48 if reqCopy == nil {
49 reqCopy = copyRequest(req)
50 }
51 reqCopy.Header.Set("Authorization", "token "+t.GithubToken)
52 }
53 }
54 if reqCopy != nil {
55 return t.base().RoundTrip(reqCopy)
56 }
57 return t.base().RoundTrip(req)
58}
59
60// CancelRequest cancels an in-flight request by closing its connection.
61func (t *AuthTransport) CancelRequest(req *http.Request) {
62 type canceler interface {
63 CancelRequest(req *http.Request)
64 }
65 if cr, ok := t.base().(canceler); ok {
66 cr.CancelRequest(req)
67 }
68}
69
70func (t *AuthTransport) base() http.RoundTripper {
71 if t.Base != nil {
72 return t.Base
73 }
74 return http.DefaultTransport
75}
76
77func copyRequest(req *http.Request) *http.Request {
78 req2 := new(http.Request)
79 *req2 = *req
80 req2.URL = new(url.URL)
81 *req2.URL = *req.URL
82 req2.Header = make(http.Header, len(req.Header))
83 for k, s := range req.Header {
84 req2.Header[k] = append([]string(nil), s...)
85 }
86 return req2
87}