1
0
mirror of https://github.com/golang/go synced 2024-11-24 04:30:14 -07:00

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
This commit is contained in:
Brad Fitzpatrick 2014-01-09 15:05:09 -08:00
parent 8da8b37674
commit d6bce32a36

View File

@ -1608,11 +1608,11 @@ func (srv *Server) ListenAndServe() error {
if addr == "" {
addr = ":http"
}
l, e := net.Listen("tcp", addr)
if e != nil {
return e
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return srv.Serve(l)
return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}
// Serve accepts incoming connections on the Listener l, creating a
@ -1742,12 +1742,12 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
return err
}
conn, err := net.Listen("tcp", addr)
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
tlsListener := tls.NewListener(conn, config)
tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
return srv.Serve(tlsListener)
}
@ -1837,6 +1837,24 @@ func (tw *timeoutWriter) WriteHeader(code int) {
tw.w.WriteHeader(code)
}
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
// connections. It's used by ListenAndServe and ListenAndServeTLS so
// dead TCP connections (e.g. closing laptop mid-download) eventually
// go away.
type tcpKeepAliveListener struct {
*net.TCPListener
}
func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
tc, err := ln.AcceptTCP()
if err != nil {
return
}
tc.SetKeepAlive(true)
tc.SetKeepAlivePeriod(3 * time.Minute)
return tc, nil
}
// globalOptionsHandler responds to "OPTIONS *" requests.
type globalOptionsHandler struct{}