[英]Golang parse raw HTTP/2 response
I have a specific case where I need to parse HTTP/2 response output into Go's http.Response
.我有一个特定的情况,我需要将 HTTP/2 响应 output 解析为 Go 的
http.Response
。 Response itself has default structure:响应本身具有默认结构:
$ curl --include https://google.com
HTTP/2 301
location: https://www.google.com/
content-type: text/html; charset=UTF-8
date: Mon, 15 Jun 2020 11:08:39 GMT
expires: Wed, 15 Jul 2020 11:08:39 GMT
cache-control: public, max-age=2592000
server: gws
content-length: 220
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://www.google.com/">here</A>.
</BODY></HTML>
Status and body itself doesn't matter, it's just an example.地位和身体本身并不重要,这只是一个例子。
http
library has function ReadResponse(r *bufio.Reader, req *Request) (*Response, error)
which does exactly what I need, but it fails parsing HTTP/2 with malformed HTTP version HTTP/2
, however it works fine for HTTP/1.1 and HTTP/1.0. http
library has function ReadResponse(r *bufio.Reader, req *Request) (*Response, error)
which does exactly what I need, but it fails parsing HTTP/2 with malformed HTTP version HTTP/2
, however it works fine for HTTP /1.1 和 HTTP/1.0。 Also, after doing request with http.DefaultClient.Do()
you can see that response's field Proto
contains HTTP/2.0
, which means that there is no problem with HTTP/2.另外,在使用
http.DefaultClient.Do()
进行请求后,您可以看到响应的字段Proto
包含HTTP/2.0
,这意味着 HTTP/2 没有问题。
Any ideas how to parse this response?任何想法如何解析此响应?
To summarize the discussion, the reason for the parse error is http.ParseHTTPVersion
not parse HTTP/2
, replace the prefix 7 bytes into HTTP/2.0
to fix it, or provide pr support for net/http
to parse HTTP/2
.总结讨论,解析错误的原因是
http.ParseHTTPVersion
not parse HTTP/2
,将前缀 7 个字节替换为HTTP/2.0
来修复它,或者为net/http
提供 pr 支持来解析HTTP/2
。
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
fmt.Println("Hello, playground")
req, _ := http.NewRequest("GET", "https://google.com", nil)
{
resp, err := http.ReadResponse(bufio.NewReader(bytes.NewBuffer(httpbody)), req)
fmt.Println(resp, err)
// err is malformed HTTP version "HTTP/2", because http.ParseHTTPVersion not parse "HTTP/2"
}
{
body := bytes.NewBuffer(httpbody)
prefix := make([]byte, 7)
n, err := io.ReadFull(body, prefix)
if err != nil {
panic("handler err")
}
fmt.Println(n, err, string(prefix))
if string(prefix[:n]) == "HTTP/2 " {
// fix HTTP/2 proto
resp, err := http.ReadResponse(bufio.NewReader(io.MultiReader(bytes.NewBufferString("HTTP/2.0 "), body)), req)
fmt.Println(resp, err)
} else {
// other proto
resp, err := http.ReadResponse(bufio.NewReader(io.MultiReader(bytes.NewBuffer(prefix[:n]), body)), req)
fmt.Println(resp, err)
}
}
}
var httpbody = []byte(`HTTP/2 301
location: https://www.google.com/
content-type: text/html; charset=UTF-8
date: Mon, 15 Jun 2020 11:08:39 GMT
expires: Wed, 15 Jul 2020 11:08:39 GMT
cache-control: public, max-age=2592000
server: gws
content-length: 220
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://www.google.com/">here</A>.
</BODY></HTML>`)
output: output:
Hello, playground
<nil> malformed HTTP version "HTTP/2"
7 <nil> HTTP/2
&{301 301 HTTP/2.0 2 0 map[Cache-Control:[public, max-age=2592000] Content-Length:[220] Content-Type:[text/html; charset=UTF-8] Date:[Mon, 15 Jun 2020 11:08:39 GMT] Expires:[Wed, 15 Jul 2020 11:08:39 GMT] Location:[https://www.google.com/] Server:[gws]] 0xc0000902c0 220 [] false false map[] 0xc0000f2000 <nil>} <nil>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.