dongyan1993
dongyan1993
2016-04-18 23:32

转到HTTP ListenAndServe日志记录响应

  • IT行业问题
  • 计算机技术
  • it技术
  • 编程语言问答
  • 互联网问答
已采纳

I was wondering if there is a way to log the responses when using ListenAndServe.

As far as I can tell, the handler doesn't have access to a "Response" object. Just a ResponseWriter, so I cannot call httputil.DumpResponse.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

3条回答

  • doulu7921 doulu7921 5年前

    http.ResponseWriter is an interface. You can use embedding to extend it for logging as follows.

    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)
    }
    

    You can wrap the handler functions that you want to log responses for with responseLogger.

    点赞 评论 复制链接分享
  • duanqiao2225 duanqiao2225 5年前

    As an alternative, one can use fasthttp.

    点赞 评论 复制链接分享
  • dongmen1925 dongmen1925 5年前

    You can't because the response technically doesn't exist until you write it to the ResponseWriter.

    But in the response is just the header, body and response code so in the handler function you can use method Header() on the ResponseWriter to get the header and then you can log the response code and the body before you write it to the ResponseWriter.

    If you provide an example of what you are trying to do, I can elaborate on how to do it.

    This is what I did to fix this for a small project: I use this in all my handlers:

    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
    }
    

    And at the end of the handler function, after having served the requested data, I update the values for the request and the response.

    And have a goroutine listening to the channel Log and doing all your logging.

    Also you can write a wrapper function that serves the file and returns the response.

    点赞 评论 复制链接分享

为你推荐