github.com/0chain/gosdk@v1.17.11/core/util/httpnet.go (about) 1 package util 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "io/ioutil" 8 "net/http" 9 "net/url" 10 "os" 11 "time" 12 ) 13 14 type GetRequest struct { 15 *PostRequest 16 } 17 18 type GetResponse struct { 19 *PostResponse 20 } 21 22 type PostRequest struct { 23 req *http.Request 24 ctx context.Context 25 cncl context.CancelFunc 26 url string 27 } 28 29 type PostResponse struct { 30 Url string 31 StatusCode int 32 Status string 33 Body string 34 } 35 36 type HttpClient interface { 37 Do(req *http.Request) (*http.Response, error) 38 } 39 40 var Client HttpClient 41 42 func getEnvAny(names ...string) string { 43 for _, n := range names { 44 if val := os.Getenv(n); val != "" { 45 return val 46 } 47 } 48 return "" 49 } 50 51 func (pfe *proxyFromEnv) initialize() { 52 pfe.HTTPProxy = getEnvAny("HTTP_PROXY", "http_proxy") 53 pfe.HTTPSProxy = getEnvAny("HTTPS_PROXY", "https_proxy") 54 pfe.NoProxy = getEnvAny("NO_PROXY", "no_proxy") 55 56 if pfe.NoProxy != "" { 57 return 58 } 59 60 if pfe.HTTPProxy != "" { 61 pfe.http, _ = url.Parse(pfe.HTTPProxy) 62 } 63 if pfe.HTTPSProxy != "" { 64 pfe.https, _ = url.Parse(pfe.HTTPSProxy) 65 } 66 } 67 68 type proxyFromEnv struct { 69 HTTPProxy string 70 HTTPSProxy string 71 NoProxy string 72 73 http, https *url.URL 74 } 75 76 var envProxy proxyFromEnv 77 78 func init() { 79 Client = &http.Client{ 80 Transport: transport, 81 } 82 envProxy.initialize() 83 } 84 85 func httpDo(req *http.Request, ctx context.Context, cncl context.CancelFunc, f func(*http.Response, error) error) error { 86 c := make(chan error, 1) 87 go func() { c <- f(Client.Do(req.WithContext(ctx))) }() 88 defer cncl() 89 select { 90 case <-ctx.Done(): 91 transport.CancelRequest(req) //nolint 92 <-c // Wait for f to return. 93 return ctx.Err() 94 case err := <-c: 95 return err 96 } 97 } 98 99 // NewHTTPGetRequest create a GetRequest instance with 60s timeout 100 func NewHTTPGetRequest(url string) (*GetRequest, error) { 101 var ctx, cancel = context.WithTimeout(context.Background(), 60*time.Second) 102 go func() { 103 //call cancel to avoid memory leak here 104 <-ctx.Done() 105 106 cancel() 107 108 }() 109 110 return NewHTTPGetRequestContext(ctx, url) 111 } 112 113 // NewHTTPGetRequestContext create a GetRequest with context and url 114 func NewHTTPGetRequestContext(ctx context.Context, url string) (*GetRequest, error) { 115 116 req, err := http.NewRequest(http.MethodGet, url, nil) 117 if err != nil { 118 return nil, err 119 } 120 121 req.Header.Set("Content-Type", "application/json; charset=utf-8") 122 req.Header.Set("Access-Control-Allow-Origin", "*") 123 124 gr := new(GetRequest) 125 gr.PostRequest = &PostRequest{} 126 gr.url = url 127 gr.req = req 128 gr.ctx, gr.cncl = context.WithCancel(ctx) 129 return gr, nil 130 } 131 132 func NewHTTPPostRequest(url string, data interface{}) (*PostRequest, error) { 133 pr := &PostRequest{} 134 jsonByte, err := json.Marshal(data) 135 if err != nil { 136 return nil, err 137 } 138 req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(jsonByte)) 139 if err != nil { 140 return nil, err 141 } 142 req.Header.Set("Content-Type", "application/json; charset=utf-8") 143 req.Header.Set("Access-Control-Allow-Origin", "*") 144 pr.url = url 145 pr.req = req 146 pr.ctx, pr.cncl = context.WithTimeout(context.Background(), time.Second*60) 147 return pr, nil 148 } 149 150 func (r *GetRequest) Get() (*GetResponse, error) { 151 response := &GetResponse{} 152 presp, err := r.Post() 153 response.PostResponse = presp 154 return response, err 155 } 156 157 func (r *PostRequest) Post() (*PostResponse, error) { 158 result := &PostResponse{} 159 err := httpDo(r.req, r.ctx, r.cncl, func(resp *http.Response, err error) error { 160 if err != nil { 161 return err 162 } 163 if resp.Body != nil { 164 defer resp.Body.Close() 165 } 166 167 rspBy, err := ioutil.ReadAll(resp.Body) 168 if err != nil { 169 return err 170 } 171 result.Url = r.url 172 result.StatusCode = resp.StatusCode 173 result.Status = resp.Status 174 result.Body = string(rspBy) 175 return nil 176 }) 177 return result, err 178 }