Use http.HandlerFunc when an HTTP endpoint can be handled by a function that accepts an http.ResponseWriter and an *http.Request. Register that function with a route, read what it needs from the request, and write the response. A handler can be a standalone function or a server method. section 8.2.2 section 11.3.1
For an endpoint with a path parameter:
- Register a method and route, such as GET /games/{id}, with HandleFunc. Keep the parameter name available to the handler. section 8.2.2
- Read the value with request.PathValue. If a required value is missing, call http.Error and return before writing anything else. section 8.2.2 section 11.3.1
- Test the function directly with a request, SetPathValue, and httptest.NewRecorder; check the recorded status and body. section 8.2.2 section 11.3.1
Listing 11.29 tick_test.go: Testing with URL parameters
func TestServer_Tick(t *testing.T) {
rr := httptest.NewRecorder()
req := httptest.NewRequest(#1
http.MethodGet, "/tick/", nil)
req.SetPathValue("habitID", "1234") #2
s := New(nil, t)
s.tick(rr, req)
assert.Equal(t,
http.StatusSeeOther, rr.Result().StatusCode) #3
assert.Contains(t, rr.Body.String(), `<a href="/">`) #3
}
The tick test supplies a path value without sending the request through the router, then checks the recorded redirect response. section 11.3.1
A handler can also coordinate a client call and navigation. The habit-tick handler reads an ID before calling a gRPC client and redirects to the index with HTTP 303 rather than displaying the index directly after the action. Its GET route is temporary: the action is intended to move to POST. section 11.3.1
A test-only HTTP response
To test an HTTP client without calling its external service, pass http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "...") }) to httptest.NewServer. Point the client at the test server’s URL and close the server after the test. The handler can instead write an error status to exercise failure handling. section 6.5.4

