-
-
Notifications
You must be signed in to change notification settings - Fork 52
/
transport.go
128 lines (114 loc) · 3.67 KB
/
transport.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package requests
import (
"bufio"
"fmt"
"io"
"net/http"
"regexp"
"strings"
"time"
)
// Transport is an alias of http.RoundTripper for documentation purposes.
type Transport = http.RoundTripper
// RoundTripFunc is an adaptor to use a function as an http.RoundTripper.
type RoundTripFunc func(req *http.Request) (res *http.Response, err error)
// RoundTrip implements http.RoundTripper.
func (rtf RoundTripFunc) RoundTrip(r *http.Request) (*http.Response, error) {
return rtf(r)
}
var _ Transport = RoundTripFunc(nil)
// ReplayString returns an http.RoundTripper that always responds with a
// request built from rawResponse. It is intended for use in one-off tests.
//
// Deprecated: Use reqtest.ReplayString.
func ReplayString(rawResponse string) Transport {
return RoundTripFunc(func(req *http.Request) (res *http.Response, err error) {
r := bufio.NewReader(strings.NewReader(rawResponse))
res, err = http.ReadResponse(r, req)
return
})
}
// UserAgentTransport returns a wrapped http.RoundTripper that sets the User-Agent header on requests to s.
func UserAgentTransport(rt http.RoundTripper, s string) Transport {
if rt == nil {
rt = http.DefaultTransport
}
return RoundTripFunc(func(req *http.Request) (res *http.Response, err error) {
r2 := *req
r2.Header = r2.Header.Clone()
r2.Header.Set("User-Agent", s)
return rt.RoundTrip(&r2)
})
}
// PermitURLTransport returns a wrapped http.RoundTripper that rejects any requests whose URL doesn't match the provided regular expression string.
//
// PermitURLTransport will panic if the regexp does not compile.
func PermitURLTransport(rt http.RoundTripper, regex string) Transport {
if rt == nil {
rt = http.DefaultTransport
}
re := regexp.MustCompile(regex)
reErr := fmt.Errorf("requested URL not permitted by regexp: %s", regex)
return RoundTripFunc(func(req *http.Request) (res *http.Response, err error) {
if u := req.URL.String(); !re.MatchString(u) {
return nil, reErr
}
return rt.RoundTrip(req)
})
}
// LogTransport returns a wrapped http.RoundTripper
// that calls fn with details when a response has finished.
// A response is considered finished
// when the wrapper http.RoundTripper returns an error
// or the Response.Body is closed,
// whichever comes first.
// To simplify logging code,
// a nil *http.Response is replaced with a new http.Response.
func LogTransport(rt http.RoundTripper, fn func(req *http.Request, res *http.Response, err error, duration time.Duration)) Transport {
if rt == nil {
rt = http.DefaultTransport
}
return RoundTripFunc(func(req *http.Request) (res *http.Response, err error) {
start := time.Now()
res, err = rt.RoundTrip(req)
if err != nil {
res2 := res
if res == nil {
res2 = new(http.Response)
}
fn(req, res2, err, time.Since(start))
return
}
res.Body = closeLogger{res.Body, func() {
fn(req, res, err, time.Since(start))
}}
return
})
}
type closeLogger struct {
io.ReadCloser
fn func()
}
func (cl closeLogger) Close() error {
cl.fn()
return cl.ReadCloser.Close()
}
// DoerTransport converts a Doer into a Transport.
// It exists for compatibility with other libraries.
// A Doer is an interface with a Do method.
// Users should prefer Transport,
// because Do is the interface of http.Client
// which has higher level concerns.
func DoerTransport(cl interface {
Do(req *http.Request) (*http.Response, error)
}) Transport {
return RoundTripFunc(cl.Do)
}
// ErrorTransport always returns the specified error instead of connecting.
// It is intended for use in testing
// or to prevent accidental use of http.DefaultClient.
func ErrorTransport(err error) Transport {
return RoundTripFunc(func(req *http.Request) (*http.Response, error) {
return nil, err
})
}