2015-07-10 7 views
7

यदि कोई कनेक्शन/प्रॉक्सी त्रुटि है तो मैं अनुरोध करने का प्रयास कर रहा हूं।नेट/http: http: सामग्री लम्बाई = 222 शरीर की लंबाई 0

Post https://m.somewebsite.co.uk/api/di/34433: http: ContentLength=222 with Body length 0 

Am मैं कुछ गलत कर: कुछ कारणों से मैं यह त्रुटि जो अनुरोध पुन: प्रयास करने पर ध्यान दिए बिना attepts ठीक करने के लिए प्रतीत नहीं होता बार आ रही है? मेरा पहला संदेह यह है कि 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 
} 

उत्तर

9

समस्या यह है कि अनुरोध निकाय को() के पहले कॉल पर अंत में पढ़ा जाता है। बाद में कॉल करने के लिए कॉल(), प्रतिक्रिया शरीर से कोई डेटा नहीं पढ़ा जाता है।

फिक्स लूप के अंदर शरीर पाठक के निर्माण को स्थानांतरित करना है। इसके लिए यह आवश्यक है कि अनुरोध लूप के अंदर भी बनाया जाए।

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) 
} 
0

की क्या http.NewRequest क्या करता है

rc, ok := body.(io.ReadCloser) 
if !ok && body != nil { 
    rc = ioutil.NopCloser(body) 
} 
// The host's colon:port should be normalized. See Issue 14836. 
u.Host = removeEmptyPort(u.Host) 
req := &Request{ 
    Method:  method, 
    URL:  u, 
    Proto:  "HTTP/1.1", 
    ProtoMajor: 1, 
    ProtoMinor: 1, 
    Header:  make(Header), 
    Body:  rc, 
    Host:  u.Host, 
} 

bodyio.Reader के प्रकार है देखते हैं, और ioutil.NopCloser द्वारा io.ReaderCloser में कन्वर्ट करते हैं। के रूप में @Cerise लिमोन कहा, Request.Body पढ़ा था कर दिया गया और धारा करीब है, इसलिए जब आप फिर से Do(), Body Length है 0.

तो, हम Request.Body से पहले Do आह्वान रीसेट कर सकते हैं।

func Post(URL string, form url.Values, cl *http.Client) ([]byte, error) { 
    requestBodyString := form.Encode() 
    req, err := http.NewRequest("POST", URL, strings.NewReader(requestBodyString)) 
    // ... 

    rsp, err := do(cl, req, requestBodyString) 

    //... 
    return b, nil 
} 

func do(cl *http.Client, req *http.Request, requestBodyString string)(*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) 
     // reset Request.Body 
     req.Body = ioutil.NopCloser(strings.NewReader(requestBodyString)) 
     rsp, err = cl.Do(&req) 
     if err == nil{ 
      return rsp, nil 
     } 
     if i > 10 { 

      return nil, fmt.Errorf("after %v tries error: %v", i, err) 
     } 
    } 
    return rsp, err 
} 
संबंधित मुद्दे