【问题标题】:In go, how to inspect the http response that is written to http.ResponseWriter?在 go 中,如何检查写入 http.ResponseWriter 的 http 响应?
【发布时间】:2015-03-15 01:17:42
【问题描述】:

我可能缺少一些明显的东西,但我正在尝试调试我的 go 服务器编写的 HTTP 响应。

我看到有 httputil.DumpResponse 可用,但它需要一个 http.Response 对象,而我可用的是 http.ResponseWriter

有没有办法从 http.ResponseWriter 中提取 http.Response 以便我可以检查对控制台或日志的响应内容?

上下文:

我正在使用https://github.com/RangelReale/osin 编写一个简单的服务器端身份验证,它是默认示例,但不明白为什么前端(使用http://ember-simple-auth.com)将失败的身份验证(密码错误)解释为成功。

这是sn-p:

r = mux.NewRouter()
r.HandleFunc("/token", func (w http.ResponseWriter, r *http.Request) {

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

    resp := server.NewResponse()
    defer resp.Close()

    r.ParseForm()

    grantType := r.FormValue("grant_type")
    username := r.FormValue("username")
    password := r.FormValue("password")
    fmt.Printf("/token : grantType=%s  username=%s  password=%s\n", grantType, username, password)

    if ar := server.HandleAccessRequest(resp, r); ar != nil {
        if username == "user" && password == "correct-password" {
            ar.Authorized = true
        } else {
            ar.Authorized = false
        }
        server.FinishAccessRequest(resp, r, ar)
    }

    osin.OutputJSON(resp, w, r)

    // Debug - doesn't work yet
    dump, err := httputil.DumpResponse(w, true)
    if err != nil {
        fmt.Printf("%s\n", dump)
    }
});
http.Handle("/token", r)

【问题讨论】:

    标签: http go


    【解决方案1】:

    写入*httptest.ResponseRecorder(实现http.ResponseWriter)并检查它。

    包中的示例:

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
        "net/http/httptest"
    )
    
    func main() {
        handler := func(w http.ResponseWriter, r *http.Request) {
            http.Error(w, "something failed", http.StatusInternalServerError)
        }
    
        req, err := http.NewRequest("GET", "http://example.com/foo", nil)
        if err != nil {
            log.Fatal(err)
        }
    
        w := httptest.NewRecorder()
        handler(w, req)
    
        fmt.Printf("%d - %s", w.Code, w.Body.String())
    }
    

    编辑以回答 cmets 中的问题:

    如果我正确理解您的问题,那么是的,您可以为此使用闭包。

    考虑以下作为您的处理程序:

    func MyHandler(w http.ResponseWriter, r *http.Request) {
        // do useful stuff...
    }
    

    然后您可以使用您的servemux注册以下闭包以获得所需的效果:

    http.HandleFunc("/my/url", func(w http.ResponseWriter, r *http.Request) {
        // first call MyHandler
        MyHandler(w, r)
    
        // then log whatever you need
        log.Printf("%#v\n", w)
    })
    

    如果这种模式证明对您有用,那么您可以编写一个高阶方法,将任何func(http.ResponseWriter, *http.Request) 包装在这样的闭包中。不过,这本身就是一个话题。

    【讨论】:

    • 感谢 sn-p。使用该示例以及重构我的代码,我能够将现有的处理程序挂钩到 httptest.Recorder 。但是,是否可以在 func(w http.ResponseWriter, r *http.Request) 处理程序本身的末尾简单地插入一条日志语句?这样我就可以在浏览器上与它交互时跟踪响应。
    • @zaichang 我已经修改了我的答案来解决你的问题。
    • 感谢 thwd,我得到的输出类似于 &http.response{conn:(*http.conn)(0xc208048000), req:(*http.Request)(0xc2080268f0), wroteHeader:true, wroteContinue:false, w:(*bufio.Writer)(0xc208044580), cw:http.chunkWriter{res:(*http.response)(0xc20804ab40), .......... dateBuf:[29]uint8{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, clenBuf:[10]uint8{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},这似乎是一个对象转储,我不知道如何获取 json 消息正文。
    • @zaichang:请为此打开一个新问题。
    • 我在这里添加了后续问题:stackoverflow.com/questions/29319783/…
    猜你喜欢
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    • 2018-12-16
    • 2020-07-15
    • 2021-10-12
    • 1970-01-01
    • 2014-04-18
    相关资源
    最近更新 更多