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

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

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

如何做到这一点?

如果有一个使用http.ResponseWriter作为参数而不是http.Response的httputil.DumpResponse等效项,那将是完美的,但是目前我只能从http.ResponseWriter访问标头

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)

回答:

中间件链接

一个常见的解决方案是所谓的 中间件链

。有几个提供此功能的库,例如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.HandlerFunc执行foo,然后执行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

以上是 在http.HandleFunc内记录对传入HTTP请求的响应 的全部内容, 来源链接: utcz.com/qa/400454.html

回到顶部