如何判断是否已调用net / http的ResponseWriter.Write()?

时间:2015-08-08 18:53:49

标签: http go

假设我有一个net / http处理程序链,而早期的处理程序响应HTTP错误(例如http.StatusInternalServerError)。如何在以下处理程序中检测到这一点,并避免向客户端发送其他数据?

或者这完全是解决这个问题的错误方法吗?

2 个答案:

答案 0 :(得分:6)

http.ResponseWriter是一个界面。所以只需撰写一个新实例:

type MyResponseWriter struct {
    http.ResponseWriter
    WroteHeader bool
}

func (w *MyResponseWriter) Write(b []byte) (int, error) {
    w.WroteHeader = true
    return w.ResponseWriter.Write(b)
}

func (w *MyResponseWriter) WriteHeader(code int) {
    w.WroteHeader = true
    w.ResponseWriter.WriteHeader(code)
}

在你的处理程序中:

//...
if w, ok := w.(*MyResponseWriter); ok && w.WroteHeader {
    log.Println("Already wrote, skipping")
    return
}

编辑:需要考虑的另一件事。大多数时候,如果你有一个"链"处理程序,这意味着在处理程序内调用处理程序。所以如果你有像

这样的东西
type Handler1 struct { http.Handler }
type Handler2 struct { http.Handler }
type Handler3 struct { http.Handler }
var MyHandler http.Handler = Handler1{Handler2{Handler3{h}}}

只要每个人调用内部处理程序作为他们使用wr 做的最后一件事,你应该没事,因为w并且r甚至没有达到内部处理程序。 E.g。

func (h Handler2) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if somethingBadHappened() {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
    h.ServeHTTP(w, r) // Not called if somethingBadHappened().
}

答案 1 :(得分:0)

首先:可能存在重量较轻的解决方案。

但是,如果找不到,请考虑使用x/net/context来实现超时,截止日期,当然还要提前终止中间件链。