在http.ResponseWriter flush / end上执行处理函数?

时间:2015-11-16 11:11:46

标签: go

有没有办法挂钩http.ResponseWriter上的flush / end事件,以便执行一个处理程序,在发送之前将更多内容写入writer。

2 个答案:

答案 0 :(得分:3)

您可以简单地包装HandleFunc,在包装的处理程序返回后,您可以将更多数据写入ResponseWriter

func myhandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello"))
}

func wrapper(w http.ResponseWriter, r *http.Request) {
    myhandler(w, r)           // Call original
    w.Write([]byte(" World")) // Write further data to output
}

func main() {
    http.HandleFunc("/", wrapper)
    http.ListenAndServe("", nil)
}

访问任何网址都会产生回复:

Hello World

在生产环境中要记住的事项:

  • 包装器还应该检查响应代码或包装处理程序的成功,并采取行动(例如,如果提供了错误页面,则可能不希望仍然执行额外的写入。)
  • 如果包装的处理程序设置了"Content-length"标头,则写入更多数据将使其无效(因为内容将大于标题中指示的内容)。

对此的一种可能的“保护”可能是传递自定义ResponseWriter实现,该实现仅写入缓冲区(例如bytes.Buffer),并且包装器将附加到此并设置"Content-length"根据新的长度,然后将缓冲区的内容写入“实际”输出。

答案 1 :(得分:2)

您可以创建自己的http.ResponseWriter来做到这一点,或者您可以使用"中间件模式":

// foo is the main handler
type foo struct{}

func (foo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("foo"))
}

// bar writes after foo
type bar struct {
    h http.Handler
}

func (b bar) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    b.h.ServeHTTP(w, r)
    w.Write([]byte("BAR"))
}

游乐场:http://play.golang.org/p/fB2OXNSTIe