skip to content

Network Services and Clients

Building and calling HTTP services with net/http alone: routing, middleware, timeouts, shutdown, client reuse and retries, where most production incidents are born.

part ofGo (Golang)overview, primer and where to startread it →
on this pageshow

explore

questions

152 · 7 sections

Why is http.FileServer usually wrapped in http.StripPrefix when mounted under /static/?

level: juniorimportance: must knowfreq 78%
basics
~20 s

http.FileServer resolves the entire request path against its root directory, so a request for /static/app.css looks for static/app.css inside that root. http.StripPrefix removes the /static/ mount prefix first, so the file server looks up app.css.

open as a page

In a Go HTTP handler, what does r.Context() return and what cancels it?

level: juniorimportance: must knowfreq 72%
basics
~20 s

r.Context() returns a context.Context scoped to that one HTTP request. Go's net/http server cancels it when the client's connection goes away and, unconditionally, when your handler returns from ServeHTTP. Pass it to every downstream call.

open as a page

In a Go http.Handler, why must w.Header().Set calls come before WriteHeader or Write?

level: juniorimportance: must knowfreq 72%
basics
~20 s

The header map is only copied onto the wire when the status line is sent. w.WriteHeader sends it, and the first w.Write sends it implicitly with status 200, so any Header().Set after that point is silently ignored.

open as a page

In Go's http.ServeMux, what does the pattern "GET /items/{id}" match, and how does the handler read id?

level: juniorimportance: must knowfreq 72%
basics
~10 s

It matches GET and HEAD requests whose path is exactly two segments: the literal items followed by any single segment. The handler reads that segment with r.PathValue("id"), which returns it as a string.

open as a page

In Go's net/http, what is the http.Handler interface, and what does http.HandlerFunc do?

level: juniorimportance: must knowfreq 82%
basics
~10 s

http.Handler is a one-method interface: ServeHTTP(http.ResponseWriter, *http.Request). http.HandlerFunc is a function type that has its own ServeHTTP method, so converting a plain function to it turns that function into a Handler.

open as a page

In net/http, how do you write a func(http.Handler) http.Handler wrapper, and where does next.ServeHTTP sit?

level: juniorimportance: must knowfreq 78%
basics
~20 s

A net/http middleware takes the next http.Handler and returns a new one. Inside its ServeHTTP it runs setup code, calls next.ServeHTTP(w, r) to invoke the wrapped handler, then runs teardown code after that call returns.

open as a page

In a Go net/http middleware, how do you recognise a CORS preflight request and answer it?

level: juniorimportance: must knowfreq 55%
basics
~20 s

A CORS preflight is an OPTIONS request that also carries an Access-Control-Request-Method header. A Go middleware tests both, writes the Access-Control-Allow-Origin, -Methods and -Headers response headers, sends 204 via w.WriteHeader(http.StatusNoContent), and returns without calling next.ServeHTTP.

open as a page

What happens when an http.Handler in a Go net/http server panics?

level: juniorimportance: must knowfreq 62%
basics
~20 s

Go's net/http server recovers a panic raised by a handler, so the process keeps serving other requests. It prints the panic value and a stack trace to Server.ErrorLog and closes that one connection, so the client gets no HTTP status at all.

open as a page

What does (*http.Request).WithContext return, and why must middleware pass on that copy?

level: juniorimportance: must knowfreq 68%
basics
~20 s

WithContext returns a shallow copy of the request carrying the new context and leaves the original untouched. Middleware must reassign r = r.WithContext(ctx) and hand that copy to next.ServeHTTP, or the inner handler still sees the old context.

open as a page

Why compare an API shared secret with crypto/subtle.ConstantTimeCompare rather than Go's == operator?

level: middleimportance: must knowfreq 61%
basics
~20 s

Comparing strings with == stops at the first differing byte, so how long it takes depends on how much of the secret the caller guessed. subtle.ConstantTimeCompare examines every byte and returns 1 for equal or 0 otherwise, in time that does not depend on the contents.

open as a page

Does Go's http.Server reuse a client connection for later requests by default, and how do you stop it?

level: juniorimportance: must knowfreq 45%
basics
~20 s

Go's http.Server enables HTTP keep-alives by default, so one accepted TCP connection serves many requests. Server.SetKeepAlivesEnabled(false) turns them off for the whole server; setting a Connection: close response header in a handler closes only that one connection.

open as a page

What does a dependency-free liveness http.HandlerFunc in a Go service do, and what must it not touch?

level: juniorimportance: must knowfreq 58%
basics
~20 s

A liveness handler reports only that the process is alive and still serving HTTP. In Go it is a tiny http.HandlerFunc that writes 200 OK and touches nothing else: no locks, no database, no outbound calls.

open as a page

In Go's net/http, how does Server.Shutdown differ from Server.Close?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Server.Shutdown stops accepting new connections, closes idle ones, and waits for in-flight requests to finish; it takes a context that bounds the wait. Server.Close closes every connection immediately, cutting requests off mid-response.

open as a page

What does an http.Server bound when ReadTimeout, WriteTimeout and IdleTimeout are all left at zero?

level: juniorimportance: must knowfreq 72%
basics
~10 s

Nothing. Zero means no timeout on every http.Server timeout field, so a connection may spend forever sending a request, receiving a response, or sitting idle. The convenience helper http.ListenAndServe builds exactly such a server.

open as a page

Why does ListenAndServe return http.ErrServerClosed as soon as Server.Shutdown begins?

level: middleimportance: must knowfreq 58%
basics
~20 s

The first thing Server.Shutdown does is close the listeners, and that is what makes ListenAndServe return. It reports that accepting has stopped, not that the drain is done — the drain ends later, when Shutdown itself returns.

open as a page

Why must you call resp.Body.Close() on an http.Response, and where does that defer belong?

level: juniorimportance: must knowfreq 82%
basics
~20 s

An http.Response body is an open stream on a live connection; closing it releases that connection and its socket. Put defer resp.Body.Close() straight after the error check, because a failed request returns a nil response.

open as a page

What does Go's http.Client.Timeout field cover, and does it include reading the response body?

level: juniorimportance: must knowfreq 80%
basics
~20 s

http.Client.Timeout bounds one whole call: DNS, dial, TLS handshake, sending the request, any redirects, and reading the response body. The clock keeps running after Do returns, so a slow body read fails too. Zero means no timeout.

open as a page

Why does http.Client.Do return a nil error when the server replies 500?

level: juniorimportance: must knowfreq 80%
basics
~10 s

http.Client.Do reports only transport-level failures - DNS, dial, TLS, a deadline, a broken connection. A 500 is a completed HTTP exchange, so err is nil; you must check resp.StatusCode yourself and close the body.

open as a page

Does Go's http.Get follow a 302 redirect automatically, and how do you find the final URL?

level: juniorimportance: must knowfreq 48%
basics
~10 s

Go's http.Get follows redirects automatically: http.DefaultClient stops only after ten consecutive hops, so you receive the final response, not the 302. The field resp.Request.URL holds the URL of the last request actually sent.

open as a page

Why does retrying the same *http.Request send an empty body on the second attempt?

level: juniorimportance: must knowfreq 55%
basics
~20 s

A request body is a one-shot io.ReadCloser. The first Do drains it and the Transport closes it, so a second Do on the same *http.Request finds nothing left to read. Build a fresh request for every attempt.

open as a page

Why does a net/http handler that writes a log line every second deliver nothing to the client until it returns?

level: juniorimportance: must knowfreq 42%
basics
~20 s

Go's HTTP server buffers the response body, so small writes sit in memory until the handler returns. Flush after each line - with http.NewResponseController(w).Flush() or an http.Flusher type assertion - to push the bytes out.

open as a page

What does httputil.NewSingleHostReverseProxy do, and how do you serve it in a Go HTTP server?

level: juniorimportance: must knowfreq 60%
basics
~10 s

httputil.NewSingleHostReverseProxy returns a *httputil.ReverseProxy whose Director points every request at one upstream URL's scheme, host and base path. ReverseProxy implements http.Handler, so you mount it on a ServeMux like any other handler.

open as a page

What does http.Hijacker's Hijack return, and what does a handler take on by calling it?

level: middleimportance: must knowfreq 50%
basics
~10 s

Hijack returns the underlying net.Conn plus a *bufio.ReadWriter already buffered on it. From then on net/http writes nothing more on that connection, never reuses it and never closes it. The handler owns the socket.

open as a page

When does Go's net/http server frame a response as chunked instead of sending a Content-Length header?

level: middleimportance: should knowfreq 38%
basics
~20 s

Whenever the body length is still unknown when the headers go out. A handler that returns with a short body buffered gets Content-Length; one that flushes first, or overruns the buffer, gets chunked framing on HTTP/1.1.

open as a page

How do you write the 101 Switching Protocols response yourself after calling Hijack?

level: middleimportance: should knowfreq 38%
basics
~20 s

Write the raw HTTP/1.1 status line and headers through the *bufio.ReadWriter Hijack returned, end the head with a blank CRLF line, then call Flush. The ResponseWriter cannot do it for you: after a hijack it returns http.ErrHijacked.

open as a page

Why must a Go read loop call net.Conn.SetReadDeadline again before every read?

level: juniorimportance: must knowfreq 55%
basics
~20 s

A net.Conn deadline is an absolute wall-clock instant, not a per-call timeout. Once that instant passes, every later read fails immediately instead of waiting, so a loop must set a fresh time.Now().Add(...) before each read.

open as a page

In Go, what does net.ListenPacket give you, and how does PacketConn.ReadFrom differ from reading a stream?

level: juniorimportance: must knowfreq 46%
basics
~20 s

net.ListenPacket binds a datagram socket and returns a net.PacketConn. There is nothing to accept: one ReadFrom call returns exactly one whole datagram plus the sender's address, while a stream read returns whatever bytes happen to have arrived.

open as a page

Why can one Read on a net.Conn return fewer bytes than the peer sent in one Write?

level: middleimportance: must knowfreq 58%
basics
~20 s

A net.Conn is a byte stream, not a message queue. Read returns whatever has arrived, so writes can split across reads or merge into one. The application supplies its own framing, such as newline-delimited lines or a length prefix.

open as a page

When does Go's net package use its pure-Go DNS resolver instead of the cgo one?

level: middleimportance: must knowfreq 40%
basics
~20 s

Go has two name resolvers: its own DNS client and one that calls the C library. The Go one is the default on Unix; Go falls back to C when the platform forbids direct queries or the host's resolver configuration needs features Go lacks.

open as a page

In Go, what does net.Listen return, and how do you serve clients from it?

level: juniorimportance: should knowfreq 54%
basics
~20 s

net.Listen returns a net.Listener bound to the given address. You call its Accept method in a loop: each call blocks until a client connects and returns a net.Conn you read from, write to and close, usually in its own goroutine.

open as a page

In Go's net/http, how do you set a cookie on a response and read it back on the next request?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Build an http.Cookie value and pass it to http.SetCookie(w, c) before writing anything to the response; it adds a Set-Cookie header. On a later request, call r.Cookie("name"), which returns the cookie or the error http.ErrNoCookie.

open as a page

In a Go HTTP handler, what does r.URL.Query().Get("page") return when the URL carries no page parameter?

level: juniorimportance: must knowfreq 78%
basics
~10 s

It returns the empty string and never an error, so a missing parameter and a present-but-empty one look identical. Use url.Values.Has, or index the url.Values map directly, when that difference matters.

open as a page

Why does r.Header.Get("x-request-id") find a header that r.Header["x-request-id"] misses?

level: juniorimportance: must knowfreq 68%
basics
~20 s

Go's http.Header is a plain map whose keys are stored in canonical form, such as X-Request-Id. Header.Get canonicalizes the name you pass before the lookup; indexing the map does not, so a lowercase key finds nothing.

open as a page

In Go, why build a query string with url.Values.Encode instead of concatenating the parameters yourself?

level: juniorimportance: must knowfreq 60%
basics
~10 s

url.Values.Encode escapes every key and value with url.QueryEscape, so an ampersand or equals sign inside a value cannot invent a new parameter. It also carries repeated keys and emits the pairs sorted by key.

open as a page

In a Go net/http handler, what does r.FormFile("avatar") return and what must the handler do with it?

level: juniorimportance: should knowfreq 55%
basics
~10 s

r.FormFile returns a multipart.File to read the upload from, a *multipart.FileHeader carrying the client-supplied filename, size and part headers, and an error. The handler must close the file, normally with defer file.Close().

open as a page