An answer from the app without a Content-Type reaches the client without one (closes #127) #148
@@ -192,6 +192,36 @@ 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, "<!doctype html><title>page</title>")
|
||||
})
|
||||
addr, _ := startProxy(t, app.URL, nil)
|
||||
|
||||
got := get(t, addr, "/")
|
||||
if got.header.Values("Content-Type") != nil {
|
||||
t.Errorf("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()
|
||||
|
||||
|
||||
@@ -431,6 +431,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()
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"sneak.berlin/go/smallwebwaf/internal/config"
|
||||
)
|
||||
|
||||
func TestAnAnswerWithoutAContentTypeGetsNone(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, _ *http.Request) {
|
||||
rq := &request{
|
||||
h: &handler{config: &config.Config{}},
|
||||
out: &responseWriter{ResponseWriter: w},
|
||||
}
|
||||
app := &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Header: http.Header{},
|
||||
Body: http.NoBody,
|
||||
}
|
||||
|
||||
err := rq.modifyResponse(app)
|
||||
if err != nil {
|
||||
t.Errorf("modifyResponse: %v", err)
|
||||
}
|
||||
|
||||
// The headers go out with this, the first part of the body,
|
||||
// which Go's server would guess a Content-Type from.
|
||||
_, _ = io.WriteString(w, "<!doctype html><title>page</title>")
|
||||
}))
|
||||
t.Cleanup(srv.Close)
|
||||
|
||||
req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, srv.URL,
|
||||
http.NoBody)
|
||||
if err != nil {
|
||||
t.Fatalf("new request: %v", err)
|
||||
}
|
||||
|
||||
res, err := srv.Client().Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("get: %v", err)
|
||||
}
|
||||
|
||||
_ = res.Body.Close()
|
||||
|
||||
if res.Header.Values("Content-Type") != nil {
|
||||
t.Errorf("client got Content-Type %q, want none",
|
||||
res.Header.Get("Content-Type"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user