使用外部客户端时 http 响应的内容类型发生变化,但在单元测试中是正确的

我有一个奇怪的情况。我想application/json; charset=utf-8从 http 处理程序返回内容类型。


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

我用 curl、insomnia 和 python 试过这个。在所有 3 种情况下,内容类型都是text/plain; charset=utf-8.


是什么导致了这个问题,我该如何解决?


潇湘沐
浏览 71回答 1
1回答

温温酱

从http 包文档:WriteHeader 发送带有提供的状态代码的 HTTP 响应标头。和在调用 WriteHeader(或 Write)之后更改标头映射无效,除非修改的标头是预告片。因此,您在标头已发送到客户端之后设置“Content-Type”标头。WriteHeader虽然模拟这可能有效,因为可以在调用后修改存储标头的缓冲区。但是当实际使用 TCP 连接时,您不能这样做。所以只需移动你的w.WriteHeader(http.StatusOK),这样它就会在之后发生w.Header().Set(...)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go