web / server limits

A default Go http.Server has no timeouts. A client can open a connection, stream request header bytes slowly, and hold the connection indefinitely.

I set limits on every server that parses HTTP requests:

var p http.Protocols
p.SetHTTP1(true)
srv := &http.Server{
	Handler:           h,
	ReadHeaderTimeout: 10 * time.Second,
	MaxHeaderBytes:    64 << 10,
	Protocols:         &p,
}

Read header timeout

ReadHeaderTimeout limits the time a client has to send the complete request header. When the timeout expires, the server closes the connection.

ReadTimeout covers the request body as well, which breaks slow file uploads. Request headers are small, and 10 seconds is generous for legitimate clients.

Max header bytes

MaxHeaderBytes limits the request header size. The default is 1 MiB. Setting it to 64 KiB protects memory while allowing common cookies. Headers above this limit receive 431 Request Header Fields Too Large.

Protocols

The server sits behind a gateway and speaks plain HTTP over a private network without TLS. I disable HTTP/2 over plain text with Protocols and allow HTTP/1.1 only.

What I leave out

I set no IdleTimeout. The gateway maintains persistent connections to the server between requests, and an idle timeout would close them.

See also web / health checks and go / web framework.

← All articles