【问题标题】:How can I tell if net/http's ResponseWriter.Write() has been called?如何判断 net/http 的 ResponseWriter.Write() 是否已被调用?
【发布时间】:2015-08-08 18:53:48
【问题描述】:

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

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

【问题讨论】:

    标签: http go


    【解决方案1】:

    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 所做的最后一件事,你应该没问题,因为那时wr 不会'甚至到达内部处理程序。例如

    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().
    }
    

    【讨论】:

    • 不调用下一个处理程序并提前返回是正确的方法。
    【解决方案2】:

    首先:可能存在更轻量级的解决方案。

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

    【讨论】:

      猜你喜欢
      • 2011-05-19
      • 1970-01-01
      • 1970-01-01
      • 2012-10-10
      • 2011-08-26
      • 2016-01-04
      • 2017-03-29
      • 2011-10-12
      • 1970-01-01
      相关资源
      最近更新 更多