/
http.go
138 lines (115 loc) · 2.82 KB
/
http.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
129
130
131
132
133
134
135
136
137
138
package main
import (
"encoding/base64"
"net/http"
"log"
"net/url"
)
const (
GET = "GET"
POST = "POST"
DEFAULT_VERB = GET
)
type Cookie struct {
Name, Value string
}
//Hold information about how to connect and
//authenticate to the server
type HTTPClient struct {
addr, method, user, password string
basicAuth bool
contentType string
cookie Cookie
}
//HTTPClient constructor. If method is "", DEFAULT_VERB is
//then used.
func NewHTTPClient(addr, contentType string, cookie Cookie) (c *HTTPClient) {
var m string
if contentType != "" {
m = POST
} else {
m = DEFAULT_VERB
}
c = &HTTPClient{
addr: addr,
method: m,
user: "",
password: "",
contentType: contentType,
basicAuth: false,
cookie: cookie,
}
return
}
//Used to set auth information for HTTP Basic Authentication.
func (c *HTTPClient) Auth(usr, passwd string) {
c.user = usr
c.password = passwd
c.basicAuth = true
}
//Uses base64 to encode "user: password" for
//Http Header Authorization.
func authInfo(user, password string) string {
srcs := []byte(user + ": " + password)
dsts := make([]byte, base64.StdEncoding.EncodedLen(len(srcs)))
base64.StdEncoding.Encode(dsts, srcs)
return string(dsts)
}
type Error string
func (e Error) String() string {
return string(e)
}
func (self *HTTPClient) defaultRequest() (req *http.Request, err error) {
var h http.Header = map[string][]string{}
req = new(http.Request)
req.Method = self.method
if self.contentType != "" {
headers := map[string]string{"Content-Type": self.contentType}
for k, v := range headers {
h.Add(k, v)
}
}
//Request should have a Header, otherwise the
//transport will not work.
req.Header = h
req.ProtoMajor = 1
req.ProtoMinor = 1
if self.cookie.Name != "" && self.cookie.Value != "" {
req.AddCookie(&http.Cookie{Name: self.cookie.Name, Value: self.cookie.Value})
}
if req.URL, err = url.Parse(self.addr); err != nil {
return
}
return
}
var gbTransport *http.Transport = &http.Transport{DisableKeepAlives: true}
//Perform the HTTP method against the target host.
//Auth is handled if Auth was previously invoked to set
//user info.
func (c *HTTPClient) DoRequest() (response *http.Response, err error) {
//Recover if things goes really bad
defer func() {
if e := recover(); e != nil {
log.Print(e)
}
}()
//creates a default request
req, err := c.defaultRequest()
if err != nil {
return
}
response, err = gbTransport.RoundTrip(req)
if err != nil {
log.Printf("Error performing Request: %v", err)
return nil, err
}
if response.StatusCode == http.StatusUnauthorized && c.basicAuth {
req.Header.Add("Authorization", authInfo(c.user, c.password))
_, err = gbTransport.RoundTrip(req)
if err != nil {
log.Println(err)
return
}
}
return
}