To put it another way, excluding error conditions, the request isn't done 
until you've consumed the response body and closed it.


On Monday, July 25, 2016 at 3:11:01 PM UTC-4, fabian....@gmail.com wrote:
>
> Hi,
>
> first, two points on the more obvious aspects:
>
>    - The ContentLength header is just a hint for the server. Nothing 
>    prevents you from setting the content length to some value (like 1896240) 
>    and then sending a request body with a different size. The resulting 
>    request might not be a valid HTTP request, but if you explicitly set the 
>    ContentLength to an invalid value, there is nothing to prevent this.
>    - The Read() function should return EOF to signal that all bytes are 
>    read. As long as the reader does not return EOF, the caller must assume 
>    that there are more bytes to be read.
>
> Taking these two points into account, the code basically sends an 
> infinitely long HTTP request with a false ContentLength header of 1896240. 
> As the request is infinitely long, the code will never finish sending this 
> request.
>
> The less obvious aspect of your question is: Why do you receive a response 
> when the request is never finished?
>
> The answer is found in a small comment in the implementation of Go's http 
> transport (
> https://github.com/golang/go/blob/master/src/net/http/transport.go#L1768-L1770
> ):
>
> // Write the request concurrently with waiting for a response,
> // in case the server decides to reply before reading our full
> // request body.
>
> Because of this optimisation, you receive a response while you are still 
> sending the request.
>
> The server interprets the ContentLength header and stops reading after 
> 1896240 bytes, and sends you the response. http.DefaultClient.Do(req) 
> returns the response, but in the background you continue sending your 
> infinitely long request.
>
> Hope this helps,
> Fabian
>
> On Monday, July 25, 2016 at 2:49:30 PM UTC+2, Feng Liyuan wrote:
>>
>> Set a io.Reader in http.NewRequest and do a http request, I found that 
>> someone reads the io.Reader even after the http request done.
>>
>> Is it a correct behaviour? And is it documented?
>>
>> My client code is
>>
>> package main
>> import (
>>     "log"
>>     "net/http"
>>     "time")
>> type reader struct{}
>> func (r reader) Read(p []byte) (int, error) {
>>     log.Println("READ")
>>     return len(p), nil}
>> func (r reader) Close() error {
>>     log.Println("CLOSE")
>>     return nil}
>> func main() {
>>     r := reader{}
>>     req, _ := http.NewRequest("GET", "http://localhost:12306/";, r)
>>     req.ContentLength = 1896240
>>     resp, err := http.DefaultClient.Do(req)
>>     if resp != nil {
>>         resp.Body.Close()
>>     }
>>     log.Println("http.DefaultClient.Do", err)
>>     time.Sleep(1e9)}
>>
>> and the server localhost:12306 simple write an http code and do nothing.
>>
>> This is the output of the program.
>>
>> [sunrunaway:/tmp]$ go run test.go 
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 READ
>> 2016/07/25 13:04:32 http.DefaultClient.Do <nil>
>> 2016/07/25 13:04:32 READ
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to