client.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package htp
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "net/http"
  6. "time"
  7. "kettle/utl"
  8. )
  9. type ClientOption func(*Client)
  10. // Setup User-Agent
  11. func ClientOptionWithUserAgent(ua string) ClientOption {
  12. return func(c *Client) {
  13. c.ua = ua
  14. }
  15. }
  16. type Client struct {
  17. c *http.Client
  18. ua string
  19. }
  20. func NewClient(options ...ClientOption) *Client {
  21. c := &http.Client{
  22. Transport: &http.Transport{
  23. TLSHandshakeTimeout: 3 * time.Second,
  24. MaxIdleConnsPerHost: 20,
  25. MaxIdleConns: 20,
  26. IdleConnTimeout: 90 * time.Second,
  27. },
  28. Timeout: 3 * time.Second,
  29. }
  30. clt := &Client{
  31. c: c,
  32. }
  33. for _, opt := range options {
  34. opt(clt)
  35. }
  36. return clt
  37. }
  38. func (self *Client) Get(url string) ([]byte, error) {
  39. return self.request(http.MethodGet, url, nil, nil)
  40. }
  41. func (self *Client) Post(url string, headers map[string]string, body []byte) ([]byte, error) {
  42. return self.request(http.MethodPost, url, headers, body)
  43. }
  44. func (self *Client) request(method, url string, headers map[string]string, body []byte) ([]byte, error) {
  45. params := bytes.NewReader(body)
  46. req, err := http.NewRequest(method, url, params)
  47. if err != nil {
  48. return nil, err
  49. }
  50. if len(self.ua) > 0 {
  51. req.Header.Set("User-Agent", self.ua)
  52. }
  53. for k, v := range headers {
  54. req.Header.Add(k, v)
  55. }
  56. resp, err := self.c.Do(req)
  57. if err != nil {
  58. return nil, err
  59. }
  60. if resp.StatusCode != http.StatusOK { // sometime StatusCode <> 200 may not represents an error
  61. return nil, utl.ErrForCode(resp.StatusCode)
  62. }
  63. if resp == nil {
  64. return nil, utl.ErrContainerEmpty
  65. }
  66. defer resp.Body.Close()
  67. return ioutil.ReadAll(resp.Body)
  68. }
  69. /////////////////////// chaining call