-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimplerequest.go
More file actions
executable file
·143 lines (119 loc) · 3.87 KB
/
simplerequest.go
File metadata and controls
executable file
·143 lines (119 loc) · 3.87 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package simplerequest
import (
"github.com/pkg/errors"
"io/ioutil"
"net/http"
"net/http/httputil"
"net/url"
"time"
)
// Create is a mechanism to make a suitable http request header
// to find some information out about a web resouse.
func Create(method string, reqURL string) (SimpleRequest, error) {
var sr SimpleRequest
sr.Method = method
req, err := url.Parse(reqURL)
if err != nil {
return sr, errors.Wrap(err, "url parse failed in CreateSimpleRequest")
}
sr.URL = req
return sr, nil
}
// Default will create a default object to make work easier for all.
func Default(reqURL *url.URL) SimpleRequest {
// we're not concerned about error here, as internally, we've
// already parsed the URL which is the only source of potential
// error in CreateSimpleRequest
sr, _ := Create(GET, reqURL.String())
return sr
}
// Do will perform the request for us from the
// SimpleRequest object itself.
func (sr *SimpleRequest) Do() (SimpleResponse, error) {
resp, err := sr.handlehttp(sr.Method, sr.URL)
return resp, err
}
// Timeout sets the client timeout in seconds...
func (sr *SimpleRequest) Timeout(duration time.Duration) {
sr.timeout = time.Duration(duration * time.Second)
}
// NoRedirect tells the client whether or not to follow redirects...
func (sr *SimpleRequest) NoRedirect(redirect bool) {
sr.noredirect = redirect
}
// GetHeader can be used to retrieve headers from the server's response
func (sr *SimpleResponse) GetHeader(key string) string {
return sr.Header.Get(key)
}
// prettyRequest is used internally to pretty print the request
func prettyRequest(sr SimpleResponse, req *http.Request) SimpleResponse {
pr, _ := httputil.DumpRequest(req, false)
sr.PrettyRequest = string(pr)
return sr
}
// prettyResponse is used internally to pretty print the response
func prettyResponse(sr SimpleResponse, resp *http.Response) SimpleResponse {
pr, _ := httputil.DumpResponse(resp, false)
sr.PrettyResponse = string(pr)
return sr
}
// status is used internally to populate status elements of SimpleResponse
func status(sr SimpleResponse, resp *http.Response) SimpleResponse {
sr.StatusText = http.StatusText(resp.StatusCode)
sr.StatusCode = resp.StatusCode
return sr
}
// location is used internally to populate status elements of SimpleResponse
func location(sr SimpleResponse, resp *http.Response) SimpleResponse {
var err error
sr.Location, err = resp.Location()
if err != nil {
sr.Location = nil
}
return sr
}
// Handle the HTTP request and response functions of the calling application.
func (sr *SimpleRequest) handlehttp(method string, reqURL *url.URL) (SimpleResponse, error) {
var simpleresponse SimpleResponse
var client http.Client
if sr.timeout != 0 {
client.Timeout = sr.timeout
}
if sr.noredirect {
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
}
req, err := http.NewRequest(method, reqURL.String(), nil)
if err != nil {
return simpleresponse, errors.Wrap(err, "request generation failed")
}
if sr.agent != "" {
req.Header.Add("User-Agent", sr.agent)
}
if sr.byterange != "" {
req.Header.Add("Range", sr.byterange)
}
if sr.accept != "" {
req.Header.Add("Accept", sr.accept)
}
resp, err := client.Do(req)
if err != nil {
return simpleresponse, errors.Wrap(err, "client.Do failed")
}
// once we've closed the body we can't do anything else
// with the packet content...
data, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return simpleresponse, errors.Wrap(err, "reading http response body")
}
// Populate the remainder of the SimpleResponse elements
simpleresponse.Header = resp.Header
simpleresponse.Data = string(data)
simpleresponse = prettyRequest(simpleresponse, req)
simpleresponse = prettyResponse(simpleresponse, resp)
simpleresponse = status(simpleresponse, resp)
simpleresponse = location(simpleresponse, resp)
return simpleresponse, err
}