在 http.HandleFunc 中记录对传入 HTTP 请求的响应

这是Go中的后续问题,如何检查写入http.ResponseWriter的http响应?因为那里的解决方案需要伪造请求,这对单元测试很有用,但不适用于实时服务器。


我想将我的 Web 服务响应它从用户收到的请求而返回的 HTTP 响应转储到日志文件(或控制台)中。输出应该告诉我标头是什么和 JSON 有效负载。


怎么做呢?


如果有一个 httputil.DumpResponse 等价物将 http.ResponseWriter 作为参数而不是 http.Response 就完美了,但目前我只能从 http.ResponseWriter 访问 Header


r = mux.NewRouter()

r.HandleFunc("/path", func (w http.ResponseWriter, r *http.Request) {


    fmt.Printf("r.HandleFunc /path\n")


    resp := server.NewResponse()

    defer resp.Close()


    r.ParseForm()


    // Server does some work here

    // ...


    // Insert debug code here, something like

    //

    // dump = http.DumpResponseFromWriter(w)

    // fmt.Printf("%s\n", dump)

});

http.Handle("/path", r)


天涯尽头无女友
浏览 208回答 3
3回答

小怪兽爱吃肉

中间件链这个问题的一个常见解决方案是所谓的中间件链。有几个库提供此功能,例如negroni。这是一种延续传递风格的形式,您可以像这样编写中间件函数(取自 negroni 的自述文件):func MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {  // do some stuff before  next(rw, r)  // do some stuff after}然后 negroni 为您提供一个 HTTP 处理程序,以正确的顺序调用您的中间件。我们可以以稍微不同的方式实现这个解决方案,而不是一种不太神奇但功能更多的方法(如在函数式编程中)。定义处理程序组合子如下:func NewFooHandler(next http.HandlerFunc) http.HandlerFunc {    return func(w http.ResponseWriter, r *http.Request) {        // do some stuff before        next(r,w)        // do some stuff after    }}然后将您的链定义为一个组合:h := NewFooHandler(NewBarHandler(NewBazHandler(Sink)))现在h是http.HandlerFuncfoo,然后是 bar,然后是 baz。Sink只是一个空的最后一个处理程序,什么都不做(“完成”链。)将此解决方案应用于您的问题定义一个处理程序组合子:func NewResponseLoggingHandler(next http.HandlerFunc) http.HandlerFunc {    return func(w http.ResponseWriter, r *http.Request) {        // switch out response writer for a recorder        // for all subsequent handlers        c := httptest.NewRecorder()        next(c, r)        // copy everything from response recorder        // to actual response writer        for k, v := range c.HeaderMap {            w.Header()[k] = v        }        w.WriteHeader(c.Code)        c.Body.WriteTo(w)    }}现在问题归结为处理程序管理。您可能希望将此处理程序应用于某个类别中的所有链。为此,您可以再次使用组合器(这在某种程度上相当于 negroni 的Classic()方法):func NewDefaultHandler(next http.HandlerFunc) http.HandlerFunc {    return NewResponseLoggingHandler(NewOtherStuffHandler(next))}在此之后,每当您启动这样的链时:h := NewDefaultHandler(...)它将自动包含响应日志记录和您在NewDefaultHandler.
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go