英文:
Handler function execution upon http.ResponseWriter flush/end?
问题
有没有一种方法可以在http.ResponseWriter上挂接到flush/end事件,以便在发送之前执行一个处理程序,该处理程序会向writer写入更多内容。
英文:
Is there a way to hook onto a flush/end event on an http.ResponseWriter in order to execute a handler which writes more to the writer just before sending.
答案1
得分: 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) // 调用原始处理程序
w.Write([]byte(" World")) // 向输出写入更多的数据
}
func main() {
http.HandleFunc("/", wrapper)
http.ListenAndServe("", nil)
}
访问任何URL都会得到以下响应:
Hello World
在生产环境中需要注意的事项:
- 包装器还应检查包装处理程序的响应代码或成功情况,并根据情况采取行动(例如,如果提供了错误页面,则可能不希望继续执行附加写入)。
- 如果被包装的处理程序设置了
"Content-length"
头部,写入更多的数据将使其无效(因为内容将比头部中指示的大小更大)。
对此的一种可能的"保护"是传递一个自定义的ResponseWriter
实现,该实现仅写入到缓冲区(例如bytes.Buffer
),并且包装器将附加到此缓冲区并根据新长度设置"Content-length"
,然后将缓冲区的内容写入"真正的"输出。
英文:
You can simply wrap your HandleFunc
, and after the wrapped handler returns, you can write further data to the 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)
}
Visiting any URL will result in response:
Hello World
Things to keep in mind in production environment:
- The wrapper should also examine response code or success of the wrapped handler, and act upon (e.g. if an error page is served, it might not be desired to still carry out the additional write).
- If
"Content-length"
header is set by the wrapped handler, writing more data will render it invalid (as the content will be bigger than indicated in the header).
One possible "protection" against this might be to pass a custom ResponseWriter
implementation which writes only to a buffer (e.g. bytes.Buffer
) and the wrapper will append to this and set "Content-length"
according to the new length, and then write the content of the buffer to the "real" output.
答案2
得分: 2
你可以创建自己的http.ResponseWriter
来实现这个功能,或者你可以使用一个"中间件模式":
// foo 是主要的处理器
type foo struct{}
func (foo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("foo"))
}
// bar 在 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"))
}
Playground: http://play.golang.org/p/fB2OXNSTIe。
英文:
You could create your own http.ResponseWriter
to do that, or you could just use a "middleware pattern":
// 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"))
}
Playground: http://play.golang.org/p/fB2OXNSTIe.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论