b776e439 by astaxie

merge bat/httplib to httplib

1 parent 6b777f0c
...@@ -36,7 +36,6 @@ import ( ...@@ -36,7 +36,6 @@ import (
36 "crypto/tls" 36 "crypto/tls"
37 "encoding/json" 37 "encoding/json"
38 "encoding/xml" 38 "encoding/xml"
39 "fmt"
40 "io" 39 "io"
41 "io/ioutil" 40 "io/ioutil"
42 "log" 41 "log"
...@@ -48,26 +47,50 @@ import ( ...@@ -48,26 +47,50 @@ import (
48 "net/url" 47 "net/url"
49 "os" 48 "os"
50 "strings" 49 "strings"
50 "sync"
51 "time" 51 "time"
52 ) 52 )
53 53
54 var defaultSetting = BeegoHttpSettings{UserAgent: "beegoServer", ConnectTimeout: 60 * time.Second, ReadWriteTimeout: 60 * time.Second, Gzip: true} 54 var defaultSetting = BeegoHttpSettings{
55 UserAgent: "beegoServer",
56 ConnectTimeout: 60 * time.Second,
57 ReadWriteTimeout: 60 * time.Second,
58 Gzip: true,
59 DumpBody: true,
60 }
61
55 var defaultCookieJar http.CookieJar 62 var defaultCookieJar http.CookieJar
63 var settingMutex sync.Mutex
56 64
57 // createDefaultCookie creates a global cookiejar to store cookies. 65 // createDefaultCookie creates a global cookiejar to store cookies.
58 func createDefaultCookie() { 66 func createDefaultCookie() {
67 settingMutex.Lock()
68 defer settingMutex.Unlock()
59 defaultCookieJar, _ = cookiejar.New(nil) 69 defaultCookieJar, _ = cookiejar.New(nil)
60 } 70 }
61 71
62 // Overwrite default settings 72 // Overwrite default settings
63 func SetDefaultSetting(setting BeegoHttpSettings) { 73 func SetDefaultSetting(setting BeegoHttpSettings) {
74 settingMutex.Lock()
75 defer settingMutex.Unlock()
64 defaultSetting = setting 76 defaultSetting = setting
77 if defaultSetting.ConnectTimeout == 0 {
78 defaultSetting.ConnectTimeout = 60 * time.Second
79 }
80 if defaultSetting.ReadWriteTimeout == 0 {
81 defaultSetting.ReadWriteTimeout = 60 * time.Second
82 }
65 } 83 }
66 84
67 // return *BeegoHttpRequest with specific method 85 // return *BeegoHttpRequest with specific method
68 func newBeegoRequest(url, method string) *BeegoHttpRequest { 86 func NewBeegoRequest(rawurl, method string) *BeegoHttpRequest {
69 var resp http.Response 87 var resp http.Response
88 u, err := url.Parse(rawurl)
89 if err != nil {
90 log.Fatal(err)
91 }
70 req := http.Request{ 92 req := http.Request{
93 URL: u,
71 Method: method, 94 Method: method,
72 Header: make(http.Header), 95 Header: make(http.Header),
73 Proto: "HTTP/1.1", 96 Proto: "HTTP/1.1",
...@@ -75,7 +98,7 @@ func newBeegoRequest(url, method string) *BeegoHttpRequest { ...@@ -75,7 +98,7 @@ func newBeegoRequest(url, method string) *BeegoHttpRequest {
75 ProtoMinor: 1, 98 ProtoMinor: 1,
76 } 99 }
77 return &BeegoHttpRequest{ 100 return &BeegoHttpRequest{
78 url: url, 101 url: rawurl,
79 req: &req, 102 req: &req,
80 params: map[string]string{}, 103 params: map[string]string{},
81 files: map[string]string{}, 104 files: map[string]string{},
...@@ -86,27 +109,27 @@ func newBeegoRequest(url, method string) *BeegoHttpRequest { ...@@ -86,27 +109,27 @@ func newBeegoRequest(url, method string) *BeegoHttpRequest {
86 109
87 // Get returns *BeegoHttpRequest with GET method. 110 // Get returns *BeegoHttpRequest with GET method.
88 func Get(url string) *BeegoHttpRequest { 111 func Get(url string) *BeegoHttpRequest {
89 return newBeegoRequest(url, "GET") 112 return NewBeegoRequest(url, "GET")
90 } 113 }
91 114
92 // Post returns *BeegoHttpRequest with POST method. 115 // Post returns *BeegoHttpRequest with POST method.
93 func Post(url string) *BeegoHttpRequest { 116 func Post(url string) *BeegoHttpRequest {
94 return newBeegoRequest(url, "POST") 117 return NewBeegoRequest(url, "POST")
95 } 118 }
96 119
97 // Put returns *BeegoHttpRequest with PUT method. 120 // Put returns *BeegoHttpRequest with PUT method.
98 func Put(url string) *BeegoHttpRequest { 121 func Put(url string) *BeegoHttpRequest {
99 return newBeegoRequest(url, "PUT") 122 return NewBeegoRequest(url, "PUT")
100 } 123 }
101 124
102 // Delete returns *BeegoHttpRequest DELETE method. 125 // Delete returns *BeegoHttpRequest DELETE method.
103 func Delete(url string) *BeegoHttpRequest { 126 func Delete(url string) *BeegoHttpRequest {
104 return newBeegoRequest(url, "DELETE") 127 return NewBeegoRequest(url, "DELETE")
105 } 128 }
106 129
107 // Head returns *BeegoHttpRequest with HEAD method. 130 // Head returns *BeegoHttpRequest with HEAD method.
108 func Head(url string) *BeegoHttpRequest { 131 func Head(url string) *BeegoHttpRequest {
109 return newBeegoRequest(url, "HEAD") 132 return NewBeegoRequest(url, "HEAD")
110 } 133 }
111 134
112 // BeegoHttpSettings 135 // BeegoHttpSettings
...@@ -120,6 +143,7 @@ type BeegoHttpSettings struct { ...@@ -120,6 +143,7 @@ type BeegoHttpSettings struct {
120 Transport http.RoundTripper 143 Transport http.RoundTripper
121 EnableCookie bool 144 EnableCookie bool
122 Gzip bool 145 Gzip bool
146 DumpBody bool
123 } 147 }
124 148
125 // BeegoHttpRequest provides more useful methods for requesting one url than http.Request. 149 // BeegoHttpRequest provides more useful methods for requesting one url than http.Request.
...@@ -134,6 +158,11 @@ type BeegoHttpRequest struct { ...@@ -134,6 +158,11 @@ type BeegoHttpRequest struct {
134 dump []byte 158 dump []byte
135 } 159 }
136 160
161 // get request
162 func (b *BeegoHttpRequest) GetRequest() *http.Request {
163 return b.req
164 }
165
137 // Change request settings 166 // Change request settings
138 func (b *BeegoHttpRequest) Setting(setting BeegoHttpSettings) *BeegoHttpRequest { 167 func (b *BeegoHttpRequest) Setting(setting BeegoHttpSettings) *BeegoHttpRequest {
139 b.setting = setting 168 b.setting = setting
...@@ -153,14 +182,20 @@ func (b *BeegoHttpRequest) SetEnableCookie(enable bool) *BeegoHttpRequest { ...@@ -153,14 +182,20 @@ func (b *BeegoHttpRequest) SetEnableCookie(enable bool) *BeegoHttpRequest {
153 } 182 }
154 183
155 // SetUserAgent sets User-Agent header field 184 // SetUserAgent sets User-Agent header field
156 func (b *BeegoHttpRequest) SetUserAgent(userAgent string) *BeegoHttpRequest { 185 func (b *BeegoHttpRequest) SetUserAgent(useragent string) *BeegoHttpRequest {
157 b.setting.UserAgent = userAgent 186 b.setting.UserAgent = useragent
158 return b 187 return b
159 } 188 }
160 189
161 // Debug sets show debug or not when executing request. 190 // Debug sets show debug or not when executing request.
162 func (b *BeegoHttpRequest) Debug(isDebug bool) *BeegoHttpRequest { 191 func (b *BeegoHttpRequest) Debug(isdebug bool) *BeegoHttpRequest {
163 b.setting.ShowDebug = isDebug 192 b.setting.ShowDebug = isdebug
193 return b
194 }
195
196 // Dump Body.
197 func (b *BeegoHttpRequest) DumpBody(isdump bool) *BeegoHttpRequest {
198 b.setting.DumpBody = isdump
164 return b 199 return b
165 } 200 }
166 201
...@@ -279,21 +314,18 @@ func (b *BeegoHttpRequest) JsonBody(obj interface{}) (*BeegoHttpRequest, error) ...@@ -279,21 +314,18 @@ func (b *BeegoHttpRequest) JsonBody(obj interface{}) (*BeegoHttpRequest, error)
279 } 314 }
280 315
281 func (b *BeegoHttpRequest) buildUrl(paramBody string) { 316 func (b *BeegoHttpRequest) buildUrl(paramBody string) {
282 if paramBody == "" {
283 return
284 }
285 // build GET url with query string 317 // build GET url with query string
286 if b.req.Method == "GET" { 318 if b.req.Method == "GET" && len(paramBody) > 0 {
287 if strings.Index(b.url, "?") == -1 { 319 if strings.Index(b.url, "?") != -1 {
288 b.url = b.url + "?" + paramBody
289 } else {
290 b.url += "&" + paramBody 320 b.url += "&" + paramBody
321 } else {
322 b.url = b.url + "?" + paramBody
291 } 323 }
292 return 324 return
293 } 325 }
294 326
295 // build POST url and body 327 // build POST/PUT/PATCH url and body
296 if b.req.Method == "POST" && b.req.Body == nil { 328 if (b.req.Method == "POST" || b.req.Method == "PUT" || b.req.Method == "PATCH") && b.req.Body == nil {
297 // with files 329 // with files
298 if len(b.files) > 0 { 330 if len(b.files) > 0 {
299 pr, pw := io.Pipe() 331 pr, pw := io.Pipe()
...@@ -338,16 +370,29 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) { ...@@ -338,16 +370,29 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
338 if b.resp.StatusCode != 0 { 370 if b.resp.StatusCode != 0 {
339 return b.resp, nil 371 return b.resp, nil
340 } 372 }
373 resp, err := b.SendOut()
374 if err != nil {
375 return nil, err
376 }
377 b.resp = resp
378 return resp, nil
379 }
380
381 func (b *BeegoHttpRequest) SendOut() (*http.Response, error) {
341 var paramBody string 382 var paramBody string
342 if len(b.params) > 0 { 383 if len(b.params) > 0 {
384 var buf bytes.Buffer
343 for k, v := range b.params { 385 for k, v := range b.params {
344 paramBody += fmt.Sprintf("&%s=%v", url.QueryEscape(k), url.QueryEscape(v)) 386 buf.WriteString(url.QueryEscape(k))
387 buf.WriteByte('=')
388 buf.WriteString(url.QueryEscape(v))
389 buf.WriteByte('&')
345 } 390 }
346 paramBody = paramBody[1:] 391 paramBody = buf.String()
392 paramBody = paramBody[0 : len(paramBody)-1]
347 } 393 }
348 394
349 b.buildUrl(paramBody) 395 b.buildUrl(paramBody)
350
351 url, err := url.Parse(b.url) 396 url, err := url.Parse(b.url)
352 if err != nil { 397 if err != nil {
353 return nil, err 398 return nil, err
...@@ -357,13 +402,6 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) { ...@@ -357,13 +402,6 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
357 402
358 trans := b.setting.Transport 403 trans := b.setting.Transport
359 404
360 if b.setting.ConnectTimeout == 0 {
361 b.setting.ConnectTimeout = 60 * time.Second
362 }
363 if b.setting.ReadWriteTimeout == 0 {
364 b.setting.ReadWriteTimeout = 60 * time.Second
365 }
366
367 if trans == nil { 405 if trans == nil {
368 // create default transport 406 // create default transport
369 trans = &http.Transport{ 407 trans = &http.Transport{
...@@ -404,15 +442,13 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) { ...@@ -404,15 +442,13 @@ func (b *BeegoHttpRequest) getResponse() (*http.Response, error) {
404 } 442 }
405 443
406 if b.setting.ShowDebug { 444 if b.setting.ShowDebug {
407 dump, err := httputil.DumpRequest(b.req, true) 445 dump, err := httputil.DumpRequest(b.req, b.setting.DumpBody)
408 if err != nil { 446 if err != nil {
409 log.Println(err.Error()) 447 log.Println(err.Error())
410 } 448 }
411 b.dump = dump 449 b.dump = dump
412 } 450 }
413 451 return client.Do(b.req)
414 b.resp, err = client.Do(b.req)
415 return b.resp, err
416 } 452 }
417 453
418 // String returns the body string in response. 454 // String returns the body string in response.
...@@ -433,9 +469,12 @@ func (b *BeegoHttpRequest) Bytes() ([]byte, error) { ...@@ -433,9 +469,12 @@ func (b *BeegoHttpRequest) Bytes() ([]byte, error) {
433 return b.body, nil 469 return b.body, nil
434 } 470 }
435 resp, err := b.getResponse() 471 resp, err := b.getResponse()
436 if resp == nil || resp.Body == nil { 472 if err != nil {
437 return nil, err 473 return nil, err
438 } 474 }
475 if resp.Body == nil {
476 return nil, nil
477 }
439 defer resp.Body.Close() 478 defer resp.Body.Close()
440 if b.setting.Gzip && resp.Header.Get("Content-Encoding") == "gzip" { 479 if b.setting.Gzip && resp.Header.Get("Content-Encoding") == "gzip" {
441 reader, err := gzip.NewReader(resp.Body) 480 reader, err := gzip.NewReader(resp.Body)
...@@ -452,18 +491,20 @@ func (b *BeegoHttpRequest) Bytes() ([]byte, error) { ...@@ -452,18 +491,20 @@ func (b *BeegoHttpRequest) Bytes() ([]byte, error) {
452 // ToFile saves the body data in response to one file. 491 // ToFile saves the body data in response to one file.
453 // it calls Response inner. 492 // it calls Response inner.
454 func (b *BeegoHttpRequest) ToFile(filename string) error { 493 func (b *BeegoHttpRequest) ToFile(filename string) error {
455 resp, err := b.getResponse()
456 if resp == nil || resp.Body == nil {
457 return err
458 }
459 defer resp.Body.Close()
460
461 f, err := os.Create(filename) 494 f, err := os.Create(filename)
462 if err != nil { 495 if err != nil {
463 return err 496 return err
464 } 497 }
465 defer f.Close() 498 defer f.Close()
466 499
500 resp, err := b.getResponse()
501 if err != nil {
502 return err
503 }
504 if resp.Body == nil {
505 return nil
506 }
507 defer resp.Body.Close()
467 _, err = io.Copy(f, resp.Body) 508 _, err = io.Copy(f, resp.Body)
468 return err 509 return err
469 } 510 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!