Go HTTP ListenAndServe 记录响应日志

6

我想知道在使用ListenAndServe时是否有记录响应的方法。

据我所知,句柄没有访问“Response”对象的权限。只有一个ResponseWriter,因此我无法调用httputil.DumpResponse。


你需要记录整个响应吗?只记录头部信息可以吗? - elithrar
3个回答

7

http.ResponseWriter是一个接口。您可以使用嵌入来扩展它进行记录,如下所示。

package main
import (
    "log"
    "net/http"
)

func sampleHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    response := []byte("Sample Response")
    w.Write(response)
}

type loggingResponseWriter struct {
    status int
    body   string
    http.ResponseWriter
}

func (w *loggingResponseWriter) WriteHeader(code int) {
    w.status = code
    w.ResponseWriter.WriteHeader(code)
}

func (w *loggingResponseWriter) Write(body []byte) (int, error) {
    w.body = string(body)
    return w.ResponseWriter.Write(body)
}

func responseLogger(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        loggingRW := &loggingResponseWriter{
            ResponseWriter: w,
        }
        h.ServeHTTP(loggingRW, r)
        log.Println("Status : ", loggingRW.status, "Response : ", loggingRW.body)
    })
}

func main() {
    http.Handle("/", responseLogger(http.HandlerFunc(sampleHandler)))
    http.ListenAndServe(":8080", nil)
}

您可以使用responseLogger对希望记录响应的处理程序函数进行封装。


1
你无法进行处理,因为响应在写入ResponseWriter之前并不存在。

但在response中只有headerbodyresponse code,所以在处理函数中,你可以使用ResponseWriter上的Header()方法获取头信息,然后你可以在将其写入ResponseWriter之前记录response codebody

如果你提供一个你想要做的例子,我可以详细说明如何实现。

这是我为一个小项目修复此问题的方法:

我在所有处理函数中都使用了这种方式:

type transaction struct {
    res Response // Create this type also
    req Request // Create this type also
}

func NewTransaction(w http.ResponseWriter, req *http.Request) *transaction{}

Log := make(chan transaction, 100)
go func{
    // Read from channel and log the info however you want.
}()

func indexHandler(w http.ResponseWriter, req *http.Request) {
    tx := NewTransaction(w, req) // Struct with the request and response
    defer func() {
        Log <- tx
    }()

    /*
    Handle request here
    */

    // Update request and response
    Request.Body = body
}

在处理程序函数的末尾,在提供所请求的数据后,我会更新请求和响应的值。同时,有一个goroutine监听Log通道并执行所有日志记录。此外,您可以编写一个包装函数来服务文件并返回响应。

这种方法的问题在于它不可伸缩。我有成百上千个处理程序函数,所以我不想在每个函数中都重复同样的事情。我宁愿在一个中心位置进行统一处理。 - user827329
@SFO 你说得没错。我添加了一个我以前如何解决这个问题的例子。虽然不是很完美,但至少是一个开始。 - Topo

-1
作为替代方案,可以使用fasthttp。

如果您希望答案有用,您应该提供一些代码示例,例如如何使用fasthttp编写HTTP处理程序以记录响应。 - Sankar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接