gpt4 book ai didi

go - 使用 httptest 和 curl 的不同内容类型

转载 作者:IT王子 更新时间:2023-10-29 01:56:30 24 4
gpt4 key购买 nike

我正在尝试这段 Go 代码

package main

import (
"github.com/gorilla/mux"
"io"
"log"
"net/http"
)

func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")

io.WriteString(w, `{"alive": true}`)
}

func main() {

router := mux.NewRouter()
router.HandleFunc("/health", HealthCheckHandler).Methods("GET")

log.Printf("running server ...")
log.Fatal(http.ListenAndServe(":8000", router))
}

通过这个测试

package main

import (
"net/http"
"net/http/httptest"
"testing"
)

func TestHealthCheckHandler(t *testing.T) {
req, err := http.NewRequest("GET", "/health", nil)
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
handler := http.HandlerFunc(HealthCheckHandler)

handler.ServeHTTP(rr, req)

if status := rr.Code; status != http.StatusOK {
t.Errorf("handler returned wrong status code: got %v want %v",
status, http.StatusOK)
}

t.Logf("%v", rr.Header())

if ctype := rr.Header().Get("Content-Type"); ctype != "application/json" {
t.Errorf("content type header does not match: got %v want %v",
ctype, "application/json")
}
}

当我运行测试时,一切正常

go test -v
=== RUN TestHealthCheckHandler
--- PASS: TestHealthCheckHandler (0.00s)
handlers_test.go:24: map[Content-Type:[application/json]]
PASS
ok 0.012s

Content-Typeapplication/json,但是当我运行该服务并使用 curl 调用它时,Content-Typetext/plain

curl -v localhost:8000/health
* Trying ::1...
* Connected to localhost (::1) port 8000 (#0)
> GET /health HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 14 Feb 2019 01:37:15 GMT
< Content-Length: 15
< Content-Type: text/plain; charset=utf-8
<
* Connection #0 to host localhost left intact

为什么行为不同于测试和执行?

(示例基于https://github.com/gorilla/mux#testing-handlers)

编辑 1

当我改变行与行之间的顺序时,从

w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)

使用 curl,我得到了预期的行为,Content-Type: application/json

curl -v localhost:8000/health
* Trying ::1...
* Connected to localhost (::1) port 8000 (#0)
> GET /health HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Date: Thu, 14 Feb 2019 01:43:18 GMT
< Content-Length: 15
<
* Connection #0 to host localhost left intact

但无论如何,在原始情况下,为什么测试和执行显示不同的 Content-Type

编辑 2

我复制了一个 tcpdump,它包含 Content-Type: text/plain

11:51:05.686149 IP localhost.47368 > localhost.32000: Flags [P.], seq 1:92, ack 1, win 342, options [nop,nop,TS val 23544153 ecr 23544153], length 91
E...-L@.@.............}..Vl..WAu...V.......
.gAY.gAYGET /health-check HTTP/1.1
Host: localhost:32000
User-Agent: curl/7.47.0
Accept: */*


11:51:05.686847 IP localhost.32000 > localhost.47368: Flags [P.], seq 1:133, ack 92, win 342, options [nop,nop,TS val 23544153 ecr 23544153], length 132
E....-@.@.<.........}....WAu.Vln...V.......
.gAY.gAYHTTP/1.1 200 OK
Date: Thu, 14 Feb 2019 14:51:05 GMT
Content-Length: 15
Content-Type: text/plain; charset=utf-8

{"alive": true}

最佳答案

问题是,正如@colminator 所说,您是在标题之前发送正文。这在任何语言中都行不通 - 这是 HTTP 的事实,而不是 Go 的事实。

它没有被你的测试捕获的原因是你的测试实际上滥用了 ResponseRecorder;您在 map 中设置字段,然后直接从该 map 读取字段。测试应该只检查 ResponseRecorder.Result ,旨在为您提供客户端实际收到的结果,包括在发送正文时锁定 header :

if ctype := rr.Response().Header.Get("Content-Type"); ctype != "application/json" {
t.Errorf("content type header does not match: got %v want %v",
ctype, "application/json")
}

关于go - 使用 httptest 和 curl 的不同内容类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54682017/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com