如何在Go中使用net/http解析分块编码?

huangapple go评论93阅读模式
英文:

How to break a chunked in go using net/http?

问题

我有一个带有端点的HTTP服务器,该端点从数据库中返回大量数据流。响应是分块的(< Transfer-Encoding: chunked)。如果遇到错误,比如数据库崩溃,我可以使用 panic,curl 会警告我有问题:

curl: (18) transfer closed with outstanding read data remaining

但我不想要 panic,我只想要一个简单的日志消息。如果我使用 recover(),curl 中就不会显示错误,所以没有任何指示有东西出错。

有没有一种方法可以在不使用 panic 的情况下中断分块的 HTTP 响应?

英文:

I have an http server with an endpoint that returns lots of data streamed from a db. The response is chunked (&lt; Transfer-Encoding: chunked). And if I run into an error, like the DB crashing, I can use a panic & curl will warn me of an issue:

curl: (18) transfer closed with outstanding read data remaining

I don't want a panic though - I just want a simple log message. And if I recover() I don't get the error in curl so there's no indication of something breaking.

Is there a way to break an chunked http response without a panic?

答案1

得分: 3

你在curl中看到的错误是因为当HTTP服务器看到panic时,立即关闭了连接。为了在没有panic的情况下强制关闭连接,你需要劫持它:

// 在http处理程序内部
// func(w http.ResponseWriter, r *http.Request) {

// 中止HTTP/1.1响应
if w, ok := w.(http.Hijacker); ok {
c, _, err := w.Hijack()
if err != nil {
log.Println("无法关闭连接:", err)
return
}
c.Close()
return
}

英文:

That error you see from curl is because the connection was immediately closed by the http server when it saw the panic. In order to force the connection closed without a panic, you will have to hijack it:

// inside the http handler
// func(w http.ResponseWriter, r *http.Request) {

// to abort an HTTP/1.1 response
if w, ok := w.(http.Hijacker); ok {
    c, _, err := w.Hijack()
    if err != nil {
        log.Println(&quot;cannot close connection:&quot;, err)
        return
    }
    c.Close()
    return
}

答案2

得分: 1

在Go 1.7中,劫持(如JimB的回答中提出的)可能是最好的解决方案。不幸的是,它只适用于HTTP/1.1 - 在HTTP/2中它不会有任何有用的效果。

Go 1.8引入了一个新的值ErrAbortHandler,中断HTTP响应流的官方方法是panic(http.ErrAbortHandler),它适用于HTTP/1.1和HTTP/2。这在issue 17790中有描述。

英文:

In Go 1.7, hijacking (as proposed in JimB's answer) is probably the best solution. Unfortunately, it only works in HTTP/1.1 — it will not do anything useful in HTTP/2.

Go 1.8 introduces a new value ErrAbortHandler, and the official way of interrupting an HTTP reply mid-stream is panic(http.ErrAbortHandler), which works for both HTTP/1.1 and HTTP/2. This is described in issue 17790.

huangapple
  • 本文由 发表于 2016年10月28日 02:36:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/40291861.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定