Skip to content

Commit d6bce32

Browse files
committed
net/http: use TCP keep-alives for ListenAndServe and ListenAndServeTLS
Our default behavior for the common cases shouldn't lead to leaked TCP connections (e.g. from people closing laptops) when their Go servers are exposed to the open Internet without a proxy in front. Too many users on golang-nuts have learned this the hard way. No API change. Only ListenAndServe and ListenAndServeTLS are updated. R=golang-codereviews, cespare, gobot, rsc, minux.ma CC=golang-codereviews https://golang.org/cl/48300043
1 parent 8da8b37 commit d6bce32

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

src/pkg/net/http/server.go

+24-6
Original file line numberDiff line numberDiff line change
@@ -1608,11 +1608,11 @@ func (srv *Server) ListenAndServe() error {
16081608
if addr == "" {
16091609
addr = ":http"
16101610
}
1611-
l, e := net.Listen("tcp", addr)
1612-
if e != nil {
1613-
return e
1611+
ln, err := net.Listen("tcp", addr)
1612+
if err != nil {
1613+
return err
16141614
}
1615-
return srv.Serve(l)
1615+
return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
16161616
}
16171617

16181618
// Serve accepts incoming connections on the Listener l, creating a
@@ -1742,12 +1742,12 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
17421742
return err
17431743
}
17441744

1745-
conn, err := net.Listen("tcp", addr)
1745+
ln, err := net.Listen("tcp", addr)
17461746
if err != nil {
17471747
return err
17481748
}
17491749

1750-
tlsListener := tls.NewListener(conn, config)
1750+
tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
17511751
return srv.Serve(tlsListener)
17521752
}
17531753

@@ -1837,6 +1837,24 @@ func (tw *timeoutWriter) WriteHeader(code int) {
18371837
tw.w.WriteHeader(code)
18381838
}
18391839

1840+
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
1841+
// connections. It's used by ListenAndServe and ListenAndServeTLS so
1842+
// dead TCP connections (e.g. closing laptop mid-download) eventually
1843+
// go away.
1844+
type tcpKeepAliveListener struct {
1845+
*net.TCPListener
1846+
}
1847+
1848+
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
1849+
tc, err := ln.AcceptTCP()
1850+
if err != nil {
1851+
return
1852+
}
1853+
tc.SetKeepAlive(true)
1854+
tc.SetKeepAlivePeriod(3 * time.Minute)
1855+
return tc, nil
1856+
}
1857+
18401858
// globalOptionsHandler responds to "OPTIONS *" requests.
18411859
type globalOptionsHandler struct{}
18421860

0 commit comments

Comments
 (0)