package proxy_test import ( "fmt" "net/http" "net/http/httptest" "strings" "testing" "git.wntrmute.dev/kyle/crossbar/internal/config" "git.wntrmute.dev/kyle/crossbar/internal/health" "git.wntrmute.dev/kyle/crossbar/internal/proxy" ) // noFlush is a ResponseWriter that does not implement http.Flusher. Middleware and test // recorders like this exist in the wild; the proxy must degrade to buffering, never panic. type noFlush struct{ w http.ResponseWriter } func (n noFlush) Header() http.Header { return n.w.Header() } func (n noFlush) Write(b []byte) (int, error) { return n.w.Write(b) } func (n noFlush) WriteHeader(code int) { n.w.WriteHeader(code) } func TestStreamingWriterWithoutFlusherDoesNotPanic(t *testing.T) { up := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/event-stream") w.WriteHeader(200) for i := 0; i < 3; i++ { fmt.Fprintf(w, "data: chunk %d\n\n", i) w.(http.Flusher).Flush() } })) t.Cleanup(up.Close) cfg, err := config.Parse(strings.NewReader(fmt.Sprintf(` listen = "127.0.0.1:1" [hosts.alpha] base_url = %q models = { "m" = { } } [routes.r] hosts = ["alpha"] `, up.URL))) if err != nil { t.Fatal(err) } h := &fakeHealth{st: map[string]health.Status{"alpha": {Healthy: true, Loaded: []string{"m"}}}} p := proxy.New(cfg, h, nil, nil, nil, nil) rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/r/v1/chat/completions", strings.NewReader(`{"model":"m","stream":true}`)) func() { defer func() { if r := recover(); r != nil { t.Fatalf("ServeHTTP panicked on a writer without Flush: %v", r) } }() p.ServeHTTP(noFlush{rec}, req) }() if rec.Code != 200 { t.Fatalf("status %d", rec.Code) } if got := rec.Body.String(); !strings.Contains(got, "chunk 0") || !strings.Contains(got, "chunk 2") { t.Errorf("body = %q, want all three chunks", got) } if rec.Header().Get(proxy.HostHeader) != "alpha" { t.Errorf("host header %q", rec.Header().Get(proxy.HostHeader)) } }