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.