request.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. package request
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "net"
  8. "net/http"
  9. "net/url"
  10. "strconv"
  11. "time"
  12. libnet "github.com/fatedier/golib/net"
  13. )
  14. type Request struct {
  15. protocol string
  16. // for all protocol
  17. addr string
  18. port int
  19. body []byte
  20. timeout time.Duration
  21. // for http
  22. method string
  23. host string
  24. path string
  25. headers map[string]string
  26. proxyURL string
  27. }
  28. func New() *Request {
  29. return &Request{
  30. protocol: "tcp",
  31. addr: "127.0.0.1",
  32. method: "GET",
  33. path: "/",
  34. }
  35. }
  36. func (r *Request) Protocol(protocol string) *Request {
  37. r.protocol = protocol
  38. return r
  39. }
  40. func (r *Request) TCP() *Request {
  41. r.protocol = "tcp"
  42. return r
  43. }
  44. func (r *Request) UDP() *Request {
  45. r.protocol = "udp"
  46. return r
  47. }
  48. func (r *Request) HTTP() *Request {
  49. r.protocol = "http"
  50. return r
  51. }
  52. func (r *Request) Proxy(url string) *Request {
  53. r.proxyURL = url
  54. return r
  55. }
  56. func (r *Request) Addr(addr string) *Request {
  57. r.addr = addr
  58. return r
  59. }
  60. func (r *Request) Port(port int) *Request {
  61. r.port = port
  62. return r
  63. }
  64. func (r *Request) HTTPParams(method, host, path string, headers map[string]string) *Request {
  65. r.method = method
  66. r.host = host
  67. r.path = path
  68. r.headers = headers
  69. return r
  70. }
  71. func (r *Request) HTTPHost(host string) *Request {
  72. r.host = host
  73. return r
  74. }
  75. func (r *Request) HTTPPath(path string) *Request {
  76. r.path = path
  77. return r
  78. }
  79. func (r *Request) HTTPHeaders(headers map[string]string) *Request {
  80. r.headers = headers
  81. return r
  82. }
  83. func (r *Request) Timeout(timeout time.Duration) *Request {
  84. r.timeout = timeout
  85. return r
  86. }
  87. func (r *Request) Body(content []byte) *Request {
  88. r.body = content
  89. return r
  90. }
  91. func (r *Request) Do() (*Response, error) {
  92. var (
  93. conn net.Conn
  94. err error
  95. )
  96. addr := net.JoinHostPort(r.addr, strconv.Itoa(r.port))
  97. // for protocol http
  98. if r.protocol == "http" {
  99. return sendHTTPRequest(r.method, fmt.Sprintf("http://%s%s", addr, r.path),
  100. r.host, r.headers, r.proxyURL, r.body)
  101. }
  102. // for protocol tcp and udp
  103. if len(r.proxyURL) > 0 {
  104. if r.protocol != "tcp" {
  105. return nil, fmt.Errorf("only tcp protocol is allowed for proxy")
  106. }
  107. conn, err = libnet.DialTcpByProxy(r.proxyURL, addr)
  108. if err != nil {
  109. return nil, err
  110. }
  111. } else {
  112. switch r.protocol {
  113. case "tcp":
  114. conn, err = net.Dial("tcp", addr)
  115. case "udp":
  116. conn, err = net.Dial("udp", addr)
  117. default:
  118. return nil, fmt.Errorf("invalid protocol")
  119. }
  120. if err != nil {
  121. return nil, err
  122. }
  123. }
  124. defer conn.Close()
  125. if r.timeout > 0 {
  126. conn.SetDeadline(time.Now().Add(r.timeout))
  127. }
  128. buf, err := sendRequestByConn(conn, r.body)
  129. if err != nil {
  130. return nil, err
  131. }
  132. return &Response{Content: buf}, nil
  133. }
  134. type Response struct {
  135. Code int
  136. Header http.Header
  137. Content []byte
  138. }
  139. func sendHTTPRequest(method, urlstr string, host string, headers map[string]string, proxy string, body []byte) (*Response, error) {
  140. var inBody io.Reader
  141. if len(body) != 0 {
  142. inBody = bytes.NewReader(body)
  143. }
  144. req, err := http.NewRequest(method, urlstr, inBody)
  145. if err != nil {
  146. return nil, err
  147. }
  148. if host != "" {
  149. req.Host = host
  150. }
  151. for k, v := range headers {
  152. req.Header.Set(k, v)
  153. }
  154. tr := &http.Transport{
  155. DialContext: (&net.Dialer{
  156. Timeout: time.Second,
  157. KeepAlive: 30 * time.Second,
  158. DualStack: true,
  159. }).DialContext,
  160. MaxIdleConns: 100,
  161. IdleConnTimeout: 90 * time.Second,
  162. TLSHandshakeTimeout: 10 * time.Second,
  163. ExpectContinueTimeout: 1 * time.Second,
  164. }
  165. if len(proxy) != 0 {
  166. tr.Proxy = func(req *http.Request) (*url.URL, error) {
  167. return url.Parse(proxy)
  168. }
  169. }
  170. client := http.Client{Transport: tr}
  171. resp, err := client.Do(req)
  172. if err != nil {
  173. return nil, err
  174. }
  175. ret := &Response{Code: resp.StatusCode, Header: resp.Header}
  176. buf, err := ioutil.ReadAll(resp.Body)
  177. if err != nil {
  178. return nil, err
  179. }
  180. ret.Content = buf
  181. return ret, nil
  182. }
  183. func sendRequestByConn(c net.Conn, content []byte) ([]byte, error) {
  184. _, err := c.Write(content)
  185. if err != nil {
  186. return nil, fmt.Errorf("write error: %v", err)
  187. }
  188. buf := make([]byte, 2048)
  189. n, err := c.Read(buf)
  190. if err != nil {
  191. return nil, fmt.Errorf("read error: %v", err)
  192. }
  193. return buf[:n], nil
  194. }