diff --git a/internal/proxy/passthrough_test.go b/internal/proxy/passthrough_test.go
index 46cb72d..80dfdb3 100644
--- a/internal/proxy/passthrough_test.go
+++ b/internal/proxy/passthrough_test.go
@@ -151,6 +151,41 @@ func wantRequestFields(t *testing.T, line logLine, host string, sent, received i
}
}
+func TestAddsNoContentTypeTheAppDidNotSend(t *testing.T) {
+ t.Parallel()
+
+ const typed = "text/plain"
+
+ app := startApp(t, func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path == "/typed" {
+ w.Header().Set("Content-Type", typed)
+ } else {
+ // The key with no value keeps Go's server from adding one.
+ w.Header()["Content-Type"] = nil
+ }
+
+ _, _ = io.WriteString(w, "
page")
+ })
+ addr, _ := startProxy(t, app.URL, nil)
+
+ // Go's server guesses a Content-Type for an answer without one only
+ // when the first part of the body goes out with the headers, which
+ // happens to some answers and not others: the test asks many times.
+ for range 50 {
+ got := get(t, addr, "/")
+ if got.header.Values("Content-Type") != nil {
+ t.Fatalf("client got Content-Type %q, want none",
+ got.header.Get("Content-Type"))
+ }
+ }
+
+ got := get(t, addr, "/typed")
+ if got.header.Get("Content-Type") != typed {
+ t.Errorf("client got Content-Type %q, want %q",
+ got.header.Get("Content-Type"), typed)
+ }
+}
+
func TestStreamsTheRequestBody(t *testing.T) {
t.Parallel()
diff --git a/internal/proxy/request.go b/internal/proxy/request.go
index e67599c..922afa5 100644
--- a/internal/proxy/request.go
+++ b/internal/proxy/request.go
@@ -421,6 +421,13 @@ func (rq *request) modifyResponse(res *http.Response) error {
return errResponseTooLarge
}
+ // Go's server adds a Content-Type it guesses from the body to a
+ // response whose headers have no Content-Type key. The key with no
+ // value sends none, as the app sent none.
+ if res.Header.Get("Content-Type") == "" {
+ rq.out.Header()["Content-Type"] = nil
+ }
+
res.Body = &responseBody{body: limitBody(res.Body, maxBytes), rq: rq}
rq.startClientResponseTimeout()