@@ 88,6 88,44 @@ func TestOnlyTheFirstCommitWrites(t *testing.T) {
assert.Equal(t, "ab", rec.Body.String())
}
+// TestAFlushBeforeAnyWriteStillCarriesTheHeaders is what the Flush method earns.
+//
+// A handler that flushes before writing anything commits the response through
+// the flush, not through Write — so the Write hook never runs, and without a
+// Flush of its own the wrapper is bypassed entirely and the response leaves with
+// no Cache-Control and no Vary. Every other test here writes first, which sets
+// the headers on the way in and leaves the flush path unmeasured: deleting Flush
+// kept all of them green.
+//
+// It has to run against a real server. httptest.ResponseRecorder's Header()
+// hands back the live map, so a recorder reports the headers as set no matter
+// when — or whether — the wrapper committed them, and reports a pass for exactly
+// this bug.
+func TestAFlushBeforeAnyWriteStillCarriesTheHeaders(t *testing.T) {
+ release := make(chan struct{})
+ srv := httptest.NewServer(mcphttp.PrivateCache(http.HandlerFunc(
+ func(w http.ResponseWriter, _ *http.Request) {
+ w.Header().Set("Content-Type", "text/event-stream")
+ if err := http.NewResponseController(w).Flush(); err != nil {
+ t.Errorf("flush: %v", err)
+ }
+ <-release
+ _, _ = w.Write([]byte(": keepalive\n\n"))
+ })))
+ t.Cleanup(func() {
+ close(release)
+ srv.Close()
+ })
+
+ resp, err := (&http.Client{Timeout: 5 * time.Second}).Get(srv.URL)
+ require.NoError(t, err)
+ t.Cleanup(func() { _ = resp.Body.Close() })
+
+ assert.Equal(t, wantCacheControl, resp.Header.Get("Cache-Control"),
+ "the response committed through Flush, so only Flush could have set this")
+ assert.Equal(t, wantVary, resp.Header.Get("Vary"))
+}
+
// TestFlushOnTheWrapperStreams covers the flush path, which cacheWriter answers
// itself rather than delegating.
//