如果存在连接/代理错误,我正在尝试重试请求。由于某些原因,我不断收到此错误,无论尝试重试该请求,该错误似乎都无法恢复:
Post https://m.somewebsite.co.uk/api/di/34433: http: ContentLength=222 with Body length 0
难道我做错了什么?我的第一个怀疑是http.Request以某种方式被消耗了,因此在下一次尝试中它不再是好东西。我应该管理副本吗?
func Post(URL string, form url.Values, cl *http.Client) ([]byte, error) { req, err := http.NewRequest("POST", URL, strings.NewReader(form.Encode())) if err != nil { log.Error(err) return nil, err } req.Header.Set("User-Agent", ua) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rsp, err := do(cl, req) if err != nil { return nil, err } defer rsp.Body.Close() b, err := ioutil.ReadAll(rsp.Body) if err != nil { log.Error(err) return nil, err } return b, nil } func do(cl *http.Client, req *http.Request)(*http.Response, error){ rsp, err := cl.Do(req) for i := 0; IsErrProxy(err); i++ { log.Errorf("Proxy is slow or down ") time.Sleep(6 * time.Second) 5t rsp, err = cl.Do(&ncp) if err == nil{ return rsp, nil } if i > 10 { return nil, fmt.Errorf("after %v tries error: %v", i, err) } } return rsp, err }
问题在于在第一次调用Do()时将请求主体读到末尾。在随后对Do()的调用中,没有从响应主体读取任何数据。
解决方法是将主体阅读器的创建移到for循环内。这要求在for循环内也创建请求。
func Post(URL string, form url.Values, cl *http.Client) ([]byte, error) { body := form.Encode() for i := 0; i < 10; i++ { req, err := http.NewRequest("POST", URL, strings.NewReader(body)) if err != nil { log.Error(err) return nil, err } req.Header.Set("User-Agent", ua) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rsp, err := cl.Do(req) if err == nil { defer rsp.Body.Close() b, err := ioutil.ReadAll(rsp.Body) if err != nil { log.Error(err) return nil, err } return b, nil } if !IsErrorProxy(err) { return nil, err } log.Errorf("Proxy is slow or down ") time.Sleep(6 * time.Second) } return nil, fmt.Errorf("after 10 tries error: %v", err) }