request.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. package myth
  2. import (
  3. "compress/gzip"
  4. "crypto/tls"
  5. "crypto/x509"
  6. "encoding/json"
  7. "encoding/xml"
  8. "errors"
  9. "io"
  10. "net"
  11. "net/http"
  12. "time"
  13. )
  14. const (
  15. // ReqContentTypeURL application/x-www-form-urlencoded
  16. ReqContentTypeURL = `application/x-www-form-urlencoded; charset=utf-8`
  17. // ReqContentTypeJSON application/json
  18. ReqContentTypeJSON = `application/json; charset=utf-8`
  19. // ReqContentTypeXML application/xml
  20. ReqContentTypeXML = `application/xml; charset=utf-8`
  21. // ReqContentTypeMultipart multipart/form-data
  22. ReqContentTypeMultipart = `multipart/form-data`
  23. // HTTP header Accept
  24. Accept = `Accept`
  25. // HTTP header Accept-Encoding
  26. AcceptEncoding = `Accept-Encoding`
  27. // HTTP header Content-Type
  28. ContentType = `Content-Type`
  29. // Default Accept-Encoding
  30. DefaultAcceptEncoding = `gzip, deflate, br`
  31. // ContentTypeJSON application/json
  32. ContentTypeJSON = `application/json; charset=utf-8`
  33. // RequestTimeOut http request timeout (second)
  34. RequestTimeOut = 30
  35. )
  36. const (
  37. // response header Content-Encoding
  38. ResContentEncoding = `Content-Encoding`
  39. // encoding gzip
  40. EncodingGZIP = `gzip`
  41. )
  42. var (
  43. reqTimeOut = time.Duration(RequestTimeOut)
  44. ErrStausCodeNotOk = errors.New(`StatusCode not 200`)
  45. )
  46. // GetRealIP get real IP from Request
  47. func GetRealIP(req *http.Request) (ip string) {
  48. if ips := req.Header["X-Real-Ip"]; ips != nil {
  49. ip = ips[0]
  50. }
  51. return
  52. }
  53. // SetHTTPRequestTimeout set request timeout
  54. func SetHTTPRequestTimeout(seconds int) {
  55. reqTimeOut = time.Duration(seconds)
  56. }
  57. // HTTPHeader HTTP header
  58. type HTTPHeader struct {
  59. header map[string]string
  60. }
  61. // DefaultTTPHeader default HTTP header
  62. var DefaultTTPHeader = NewDefaultHTTPHeader()
  63. // NewHTTPHeader new HTTPHeader
  64. func NewHTTPHeader() (h *HTTPHeader) {
  65. return &HTTPHeader{header: map[string]string{}}
  66. }
  67. // NewDefaultHTTPHeader new HTTPHeader
  68. func NewDefaultHTTPHeader() (h *HTTPHeader) {
  69. h = NewHTTPHeader()
  70. //h.Add(ContentType, ContentTypeJSON)
  71. h.Add(AcceptEncoding, DefaultAcceptEncoding)
  72. return
  73. }
  74. // Headers return header
  75. func (h *HTTPHeader) Headers() map[string]string {
  76. return h.header
  77. }
  78. // Add add new k-v
  79. func (h *HTTPHeader) Add(k, v string) {
  80. h.header[k] = v
  81. }
  82. // Del del k
  83. func (h *HTTPHeader) Del(k string) {
  84. delete(h.header, k)
  85. }
  86. // HTTPReqOption request option
  87. type HTTPReqOption struct {
  88. }
  89. // HTTPMessage HTTP response
  90. type HTTPMessage struct {
  91. StatusCode int
  92. Body []byte
  93. Header http.Header
  94. Req *http.Request
  95. Res *http.Response
  96. }
  97. // JSON Body to JSON
  98. func (m HTTPMessage) JSON(dest interface{}) (err error) {
  99. if m.StatusCode != http.StatusOK {
  100. err = ErrStausCodeNotOk
  101. return
  102. }
  103. err = json.Unmarshal(m.Body, &dest)
  104. return
  105. }
  106. // XML Body to XML
  107. func (m HTTPMessage) XML(dest interface{}) (err error) {
  108. if m.StatusCode != http.StatusOK {
  109. err = ErrStausCodeNotOk
  110. return
  111. }
  112. err = xml.Unmarshal(m.Body, &dest)
  113. return
  114. }
  115. // JSONQuery Body to JSONQuery
  116. func (m HTTPMessage) JSONQuery() (jq *JSONQuery, err error) {
  117. if m.StatusCode != http.StatusOK {
  118. err = ErrStausCodeNotOk
  119. return
  120. }
  121. jq, err = NewJSONQuery(m.Body)
  122. return
  123. }
  124. func newRequest(method, uri, certPath, keyPath string, header map[string]string, body io.Reader) (req *http.Request, res *http.Response, err error) {
  125. t := &http.Transport{
  126. Dial: func(netw, addr string) (net.Conn, error) {
  127. var c net.Conn
  128. c, err = net.DialTimeout(netw, addr, time.Second*RequestTimeOut)
  129. if err != nil {
  130. return nil, err
  131. }
  132. c.SetDeadline(time.Now().Add(time.Second * reqTimeOut))
  133. return c, nil
  134. },
  135. MaxIdleConnsPerHost: 50,
  136. ResponseHeaderTimeout: time.Second * reqTimeOut,
  137. }
  138. if certPath != "" {
  139. cert, e := tls.LoadX509KeyPair(certPath, keyPath)
  140. if e != nil {
  141. t.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
  142. } else {
  143. pool := x509.NewCertPool()
  144. t.TLSClientConfig = &tls.Config{InsecureSkipVerify: true, Certificates: []tls.Certificate{cert}, RootCAs: pool}
  145. }
  146. }
  147. var (
  148. client = &http.Client{Transport: t}
  149. )
  150. req, err = http.NewRequest(method, uri, body)
  151. if err != nil {
  152. return
  153. }
  154. for k := range header {
  155. req.Header.Add(k, header[k])
  156. }
  157. res, err = client.Do(req)
  158. return
  159. }
  160. func readBody(msg *HTTPMessage, res *http.Response) (err error) {
  161. var (
  162. body []byte
  163. reader io.Reader
  164. )
  165. encoding := res.Header.Get(ResContentEncoding)
  166. switch encoding {
  167. case EncodingGZIP:
  168. reader, err = gzip.NewReader(res.Body)
  169. if err == nil {
  170. body, err = io.ReadAll(reader)
  171. }
  172. default:
  173. body, err = io.ReadAll(res.Body)
  174. }
  175. if err != nil {
  176. return
  177. }
  178. msg.StatusCode = res.StatusCode
  179. msg.Header = res.Header
  180. msg.Body = body
  181. return
  182. }
  183. // Post HTTP request POST
  184. func Post(uri, certPath, keyPath string, header map[string]string, data io.Reader) (msg HTTPMessage, err error) {
  185. if msg.Req, msg.Res, err = newRequest(http.MethodPost, uri, certPath, keyPath, header, data); err != nil {
  186. return
  187. }
  188. defer msg.Res.Body.Close()
  189. err = readBody(&msg, msg.Res)
  190. return
  191. }
  192. // Get HTTP request GET
  193. func Get(uri, certPath, keyPath string, header map[string]string) (msg HTTPMessage, err error) {
  194. //var res *http.Response
  195. if msg.Req, msg.Res, err = newRequest(http.MethodGet, uri, certPath, keyPath, header, nil); err != nil {
  196. return
  197. }
  198. defer msg.Res.Body.Close()
  199. err = readBody(&msg, msg.Res)
  200. return
  201. }