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.