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) {
|
func TestStreamsTheRequestBody(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
@@ -431,6 +431,13 @@ func (rq *request) modifyResponse(res *http.Response) error {
|
|||||||
return errResponseTooLarge
|
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}
|
res.Body = &responseBody{body: limitBody(res.Body, maxBytes), rq: rq}
|
||||||
rq.startClientResponseTimeout()
|
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