diff --git a/httpbin/handlers.go b/httpbin/handlers.go index 2b6986b..36b9a59 100644 --- a/httpbin/handlers.go +++ b/httpbin/handlers.go @@ -341,19 +341,23 @@ func (h *HTTPBin) Unstable(w http.ResponseWriter, r *http.Request) { // values in the JSON response body will be escaped. func (h *HTTPBin) ResponseHeaders(w http.ResponseWriter, r *http.Request) { args := r.URL.Query() + + // only set our own content type if one was not already set based on + // incoming request params contentType := args.Get("Content-Type") + if contentType == "" { + contentType = jsonContentType + args.Set("Content-Type", contentType) + } - // response headers are not escaped, regardless of content type + // actual HTTP response headers are not escaped, regardless of content type + // (unlike the JSON serialized representation of those headers in the + // response body, which MAY be escaped based on content type) for k, vs := range args { for _, v := range vs { w.Header().Add(k, v) } } - // only set our own content type if one was not already set based on - // incoming request params - if contentType == "" { - w.Header().Set("Content-Type", jsonContentType) - } // if response content type is dangrous, escape keys and values before // serializing response body diff --git a/httpbin/handlers_test.go b/httpbin/handlers_test.go index ae680ef..2942e9d 100644 --- a/httpbin/handlers_test.go +++ b/httpbin/handlers_test.go @@ -1241,6 +1241,13 @@ func TestResponseHeaders(t *testing.T) { resultValues := result[k] assert.DeepEqual(t, resultValues, expectedValues, "JSON response headers mismatch") } + + // if no content-type is specified in the request params, the response + // defaults to JSON. + // + // Note that if this changes, we need to ensure we maintain safety + // around escapig HTML in the response (see the subtest below) + assert.Header(t, resp, "Content-Type", jsonContentType) }) t.Run("override content-type", func(t *testing.T) { @@ -1271,8 +1278,11 @@ func TestResponseHeaders(t *testing.T) { {"text/plain", false}, {"application/octet-string", false}, + // if no content-type is provided, we default to JSON, which is + // safe + {"", false}, + // everything else requires escaping - {"", true}, {"application/xml", true}, {"image/png", true}, {"text/html; charset=utf8", true},