Go

How is context used in net/http on both server and client sides? What happens when a client disconnects mid-request?

Question 449MediumGo 1.22 to 1.25

Server: each request carries r.Context(), which is canceled when the client closes the connection, when an HTTP/2 stream is reset, or when ServeHTTP returns. Pass it to every downstream call (DB, RPC) so abandoned work stops. The handler goroutine itself is not killed — you must check ctx.Done() or rely on context-aware libraries.

Client: use http.NewRequestWithContext; cancellation aborts dialing, waiting for headers and reading the body.

func search(w http.ResponseWriter, r *http.Request) {
	ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
	defer cancel()

	rows, err := db.QueryContext(ctx, "SELECT id FROM items WHERE name LIKE $1", r.URL.Query().Get("q"))
	if err != nil {
		switch {
		case errors.Is(err, context.Canceled):
			return // client went away; nobody to respond to
		case errors.Is(err, context.DeadlineExceeded):
			http.Error(w, "timeout", http.StatusGatewayTimeout)
		default:
			http.Error(w, "db error", http.StatusInternalServerError)
		}
		return
	}
	defer rows.Close()
	// ...
}

For work that must outlive the request (audit log write), use context.WithoutCancel(r.Context()) (Go 1.21) to keep values but drop cancellation. Store request-scoped values with an unexported key type to avoid collisions: type ctxKey struct{}.

More on Standard Library, HTTP & Systems Design in Go

All 35 Standard Library, HTTP & Systems Design in Go questions