使用外部客户端时 http 响应的内容类型发生变化,但在单元测试中是正确的
content type of http response changes when using external clients but is correct in unit test
我有一个奇怪的情况。我想从 http 处理程序 return 内容类型 application/json; charset=utf-8
。
func handleTest() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Accept") != "application/json" {
w.WriteHeader(http.StatusNotAcceptable)
return
}
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(map[string]string{"foo": "bar"})
}
}
当我在单元测试中检查它时,它是正确的。这个测试没有失败。
func TestTestHandler(t *testing.T) {
request, _ := http.NewRequest(http.MethodGet, "/test", nil)
request.Header.Set("Accept", "application/json")
response := httptest.NewRecorder()
handleTest().ServeHTTP(response, request)
contentType := response.Header().Get("Content-Type")
if contentType != "application/json; charset=utf-8" {
t.Errorf("Expected Content-Type to be application/json; charset=utf-8, got %s", contentType)
return
}
}
但是当我尝试使用 curl(和其他客户端)时,结果显示为 text/plain; charset=utf-8
。
$ curl -H 'Accept: application/json' localhost:8080/test -v
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /test HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: application/json
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Tue, 28 Dec 2021 13:02:27 GMT
< Content-Length: 14
< Content-Type: text/plain; charset=utf-8
<
{"foo":"bar"}
* Connection #0 to host localhost left intact
我已经尝试过卷曲、失眠和 python。在所有 3 种情况下,内容类型都显示为 text/plain; charset=utf-8
.
是什么导致了这个问题,我该如何解决?
WriteHeader sends an HTTP response header with the provided status code.
和
Changing the header map after a call to WriteHeader (or Write) has no effect unless the modified headers are trailers.
因此,在 header 已经发送给客户端之后,您正在设置“Content-Type”header。虽然模拟这可能有效,因为可以在 WriteHeader
调用之后修改存储 header 的缓冲区。但是当实际使用TCP连接时你不能这样做。
因此只需移动您的 w.WriteHeader(http.StatusOK)
,使其发生在 w.Header().Set(...)
之后
我有一个奇怪的情况。我想从 http 处理程序 return 内容类型 application/json; charset=utf-8
。
func handleTest() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Accept") != "application/json" {
w.WriteHeader(http.StatusNotAcceptable)
return
}
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(map[string]string{"foo": "bar"})
}
}
当我在单元测试中检查它时,它是正确的。这个测试没有失败。
func TestTestHandler(t *testing.T) {
request, _ := http.NewRequest(http.MethodGet, "/test", nil)
request.Header.Set("Accept", "application/json")
response := httptest.NewRecorder()
handleTest().ServeHTTP(response, request)
contentType := response.Header().Get("Content-Type")
if contentType != "application/json; charset=utf-8" {
t.Errorf("Expected Content-Type to be application/json; charset=utf-8, got %s", contentType)
return
}
}
但是当我尝试使用 curl(和其他客户端)时,结果显示为 text/plain; charset=utf-8
。
$ curl -H 'Accept: application/json' localhost:8080/test -v
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /test HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: application/json
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Tue, 28 Dec 2021 13:02:27 GMT
< Content-Length: 14
< Content-Type: text/plain; charset=utf-8
<
{"foo":"bar"}
* Connection #0 to host localhost left intact
我已经尝试过卷曲、失眠和 python。在所有 3 种情况下,内容类型都显示为 text/plain; charset=utf-8
.
是什么导致了这个问题,我该如何解决?
WriteHeader sends an HTTP response header with the provided status code.
和
Changing the header map after a call to WriteHeader (or Write) has no effect unless the modified headers are trailers.
因此,在 header 已经发送给客户端之后,您正在设置“Content-Type”header。虽然模拟这可能有效,因为可以在 WriteHeader
调用之后修改存储 header 的缓冲区。但是当实际使用TCP连接时你不能这样做。
因此只需移动您的 w.WriteHeader(http.StatusOK)
,使其发生在 w.Header().Set(...)