diff --git a/internal/server/request_id_internal_test.go b/internal/server/request_id_internal_test.go new file mode 100644 index 0000000..d81a05b --- /dev/null +++ b/internal/server/request_id_internal_test.go @@ -0,0 +1,58 @@ +package server + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +// requestIDHeader is the header that carries a request's ID. +const requestIDHeader = "X-Request-Id" + +// TestResponsesCarryRequestID verifies that every response, whatever its route +// and status, carries the request's ID as X-Request-Id, so a client can quote +// it when reporting a problem: one pixa made up when the request brought none, +// and the request's own X-Request-Id when it brought one. +func TestResponsesCarryRequestID(t *testing.T) { + t.Parallel() + + const clientRequestID = "client-request-id" + + s := newTestServer(t) + + paths := []string{ + "/robots.txt", + "/no-such-path", + unsignedImagePath, + encryptedImagePath, + } + + for _, path := range paths { + t.Run(path, func(t *testing.T) { + t.Parallel() + + rec := httptest.NewRecorder() + s.ServeHTTP(rec, httptest.NewRequestWithContext( + t.Context(), http.MethodGet, path, nil)) + t.Logf("status %d, %s %q", + rec.Code, requestIDHeader, rec.Header().Get(requestIDHeader)) + + if rec.Header().Get(requestIDHeader) == "" { + t.Errorf("response has no %s", requestIDHeader) + } + + req := httptest.NewRequestWithContext( + t.Context(), http.MethodGet, path, nil) + req.Header.Set(requestIDHeader, clientRequestID) + + rec = httptest.NewRecorder() + s.ServeHTTP(rec, req) + + got := rec.Header().Get(requestIDHeader) + if got != clientRequestID { + t.Errorf("%s = %q, want the request's own %q", + requestIDHeader, got, clientRequestID) + } + }) + } +}