New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net/http: ParseHTTPVersion does not parse versions without a minor subversion #48766
Comments
Change https://golang.org/cl/353792 mentions this issue: |
Sorry, but this isn't safe at this point. We'd explicitly documented a form of invalid input that we don't accept. People might be relying on that. We can't just start parsing it and treating it as valid. |
/cc @neild |
The current code in the main branch parses values like |
Permitting more inputs doesn't mean it's "safer". https://datatracker.ietf.org/doc/html/rfc7230#appendix-B says:
That's the syntax that's supported. Semantic rejections for things like HTTP/0.0 or HTTP/00.00 are handled at e.g. https://github.com/golang/go/blob/go1.17.1/src/net/http/server.go#L1037:
I see that it does incorrectly accept a request like:
So if you want something to fix, you could modify ParseHTTPVersion to strictly accept |
If you look at my code, you'll see that it is actually stricter, except the two scenarios that implicitly set the minor version to The reason why I added support for this, because it seems that requests made by multiple tools do support this: e.g. Furthermore, quoting from the
At the same time looking at the RFC7540
This indeed does have an implicit minor version, but this is related to the connection. |
It seems like a mistake that Perhaps the best thing to do is deprecate it. |
@neild @bradfitz I am willing to change my code, but first I'd like to make sure that it is not good as is, taking into account the points from my previous comment. |
It isn't possible to read an HTTP/2 response in a similar fashion. HTTP/2 interleaves multiple streams (request/response interactions) on a single TCP connection, reading an HTTP/2 streams requires bidirectional communication to negotiate flow control, and HTTP/2 request and response headers are encoded using a stateful compression algorithm. The output of Possibly it makes sense for |
There is #46587 for which the fix https://go-review.googlesource.com/c/go/+/325874/ was proposed |
Yes indeed, and this is the case for other tools as well.
The closes match to an official specification probably would be/have been the HAR (HTTP archive format), but it wasn't officially published and has been abandoned since by the W3C. Although major browsers (Firefox, Chrome, Edge, Safari) and a number of other tools do support this and you can export HTTP2 requests in this format. "response": {
"status": 200,
"statusText": "OK",
"httpVersion": "HTTP/2",
"headers": [
{
"name": "server",
"value": "AkamaiNetStorage"
},
{
"name": "content-length",
"value": "10747"
},
{
"name": "content-type",
"value": "text/html;charset=UTF-8"
},
{
"name": "accept-ch",
"value": "DPR, Width, Viewport-Width, Downlink, Save-Data"
},
{
"name": "X-Firefox-Spdy",
"value": "h2"
}
],
"cookies": [],
"content": {
"mimeType": "text/html; charset=UTF-8",
"size": 10747,
"text": "<!DOCTYPE html>\r\n<html>\r\n<head>\r\n
<meta content=\"width=device-width,initial-scale=1\" name=\"viewport\">\r\n
<meta name=\"Keywords\" content=\"HTTP/2, HTTP/2.0, H2, Akamai, Cloud Computing, CDN, Mobile Experience, Content Delivery, Application Acceleration, Application Performance Management\">\r\n
<title>HTTP/2: the Future of the Internet | Akamai</title> ..." Dumping HTTP2 requests with
func TestDumpHttp2(t *testing.T) {
resp, err := http.Get("http://http2.akamai.com")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
dump, err := httputil.DumpResponse(resp, false)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%q", dump)
} Result:
Other tools (the ones that I've interacted with) do not include the minor, probably because:
For this reason, it would have been convenient to be slightly more permissive, but I can also understand if you want to follow the RFC strictly, although in this case, the proposed code should only accept the following HTTP versions: 0.9, 1.0, 1.1, 2.0 and maybe 3.0 (which is not the case). TL;DR I don't think that there is an official specification around this (at least for now), hence we can close this issue. |
@forgedhallpass |
@AlexanderYastrebov yes, I know, but my use case was about parsing dumped HTTP/2 responses. func ParseHTTPVersion(version string) (major, minor int, ok bool) {
switch version {
case "HTTP/1.1":
return 1, 1, true
case "HTTP/1.0":
return 1, 0, true
case "HTTP/0.9":
return 0, 9, true
default:
return 0, 0, false
}
} because otherwise this logic is not used for HTTP/2 requests at all. |
Quote from:
src/net/http/request.go#ParseHTTPVersion
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What did you expect to see?
What did you see instead?
The text was updated successfully, but these errors were encountered: