【发布时间】:2021-03-18 02:56:59
【问题描述】:
我正在编写一个向 WebSocket 网关发送请求的 HTTP API。我正在使用go1.14.7 和gorilla/mux v1.8.0。代码将使用GOOS=linuxGOARCH=armGOARM=7进行交叉编译。
我的问题如下:
-
respondBadRequest()总是记录这个,即使我从不使用WriteHeader:http: superfluous response.WriteHeader call from main.(*HttpHandler).respondBadRequest
- API 响应始终为
200 OK,即使在调用respondBadRequest()时也是如此 - API 响应的正文始终为空
我对 Go 完全陌生。下面是我的代码结构。
type HttpHandler struct {
gateway Gateway
}
func (h *HttpHandler) respondSuccess(w http.ResponseWriter, text string) {
w.Write([]byte(text))
}
func (h *HttpHandler) respondBadRequest(w http.ResponseWriter, text string) {
http.Error(w, text, http.StatusBadRequest)
}
func (h *HttpHandler) respondError(w http.ResponseWriter, text string) {
http.Error(w, text, http.StatusInternalServerError)
}
func (h *HttpHandler) OnFoobar(w http.ResponseWriter, r *http.Request) {
f := func(success bool, e error) {
if e != nil {
h.respondError(w, e.Error())
} else if success {
h.respondSuccess(w, "Foobar Accepted")
} else {
h.respondBadRequest(w, "Unknown Foobar")
}
}
//...
e := h.gateway.Foobar(f)
if e != nil {
log.Println(e)
}
}
//...
httpHandler := &HttpHandler{
gateway: gateway,
}
r := mux.NewRouter()
r.HandleFunc("/foobar", httpHandler.OnFoobar)
http.ListenAndServe(":8000", r)
【问题讨论】:
-
如果你写了响应的任何部分,
WriteHeader已经被调用了。写完响应后,不能再发送不同的标头。 -
您不是直接调用
WriteHeader,而是在多个地方间接调用它;如果您调用Write并且WriteHeader尚未被调用,Write将调用WriteHeader(200)(如文档中所述)。http.Error也调用WriteHeader。如果您想以错误响应,您必须在调用Write发送任何正文内容之前 这样做(在HTTP 响应中,状态和标头必须 在响应正文)。 -
f看起来像一个回调,所以我猜Foobar是异步的?它是在 goroutine 中完成它的工作吗?如果是这样,处理程序OnFoobar不会等待Foobar完成并且当它退出时,如果尚未写入w,则Go 的服务多路复用器将默认写入200ok,然后稍后当Foobar完成,它会调用你得到错误的回调。 -
@Steffen 在这种情况下使用
sync.WaitGroup。 -
@Steffen 应该这样做,我相信:play.golang.org/p/_2DkCVXmhcS