client.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package htp
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "net/http"
  6. "one.com/kettle/utl"
  7. "time"
  8. )
  9. type ClientOption func(*Client)
  10. func WithUserAgent(ua string) ClientOption {
  11. return func(c *Client){
  12. c.ua = ua
  13. }
  14. }
  15. type Client struct {
  16. c *http.Client
  17. req *http.Request
  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