You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Run the following program. It creates an HTTP server on :8000 and spawns a goroutine that sends GET requests to the server every 1 second. The server writes nothing in the response body; body-length = 0. The client makes GET requests and does a body.Close() without reading the body. Note that the transport has InsecureSkipVerify.
package main
import (
"crypto/tls""fmt""log""net/http""time"
)
funcServer(w http.ResponseWriter, req*http.Request) {
// If a response is written, the issue isn't triggered.// io.WriteString(w, "hello, world!\n")
}
funcClient(urlstring) {
req, err:=http.NewRequest("GET", url, nil)
iferr!=nil {
log.Fatal(err)
}
// This transport is what's causing unclosed connections.tr:=&http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
hc:=&http.Client{Timeout: 2*time.Second, Transport: tr}
resp, err:=hc.Do(req)
iferr!=nil {
log.Fatal(err)
}
deferresp.Body.Close()
}
funcmain() {
// Wait a bit and launch one client every second.// On the terminal, run `ss | grep :8000` to see// ESTABLISHED connections grow with every request.gofunc() {
time.Sleep(1*time.Second)
n:=0for {
Client("http://localhost:8000")
fmt.Println("Request", n)
n+=1time.Sleep(1*time.Second)
}
}()
http.HandleFunc("/", Server)
log.Fatal(http.ListenAndServe(":8000", nil))
}
What did you expect to see?
Every request the client makes should get a 200 response from the server and immediately close the connection.
What did you see instead?
The client keeps making requests and gets 200 back, but the underlying TCP connection is never closed. It's stuck in the ESTABLISHED state perpetually.
Check the open connections by running ss | grep :8000 every few seconds. They keep growing. netstat n | grep :8000 also shows TIME_WAIT connections.
Writing a response in Server() solves the issue.
Removing InsecureSkipVerify solves the issue.
The text was updated successfully, but these errors were encountered:
knadh
changed the title
net/http: HTTP requests with InsecureSkipVerify transport doesn't close connections
net/http: HTTP requests with InsecureSkipVerify transport don't close TCP connections
Jul 5, 2016
By default, Transport caches connections for future re-use. This may leave many open connections when accessing many hosts. This behavior can be managed using Transport's CloseIdleConnections method and the MaxIdleConnsPerHost and DisableKeepAlives fields.
Transports should be reused instead of created as needed. Transports are safe for concurrent use by multiple goroutines.
go version
)?go version go1.6.2 linux/amd64
go env
)?Run the following program. It creates an HTTP server on :8000 and spawns a goroutine that sends GET requests to the server every 1 second. The server writes nothing in the response body; body-length = 0. The client makes GET requests and does a body.Close() without reading the body. Note that the transport has
InsecureSkipVerify
.Every request the client makes should get a 200 response from the server and immediately close the connection.
The client keeps making requests and gets 200 back, but the underlying TCP connection is never closed. It's stuck in the
ESTABLISHED
state perpetually.Check the open connections by running
ss | grep :8000
every few seconds. They keep growing.netstat n | grep :8000
also shows TIME_WAIT connections.Server()
solves the issue.InsecureSkipVerify
solves the issue.The text was updated successfully, but these errors were encountered: