go: x/net/http2: Transport hangs on malformed response headers

Please answer these questions before submitting your issue. Thanks!

  1. What version of Go are you using (go version)? go1.7rc4
  2. What operating system and processor architecture are you using (go env)? OS X ( 15.6.0 Darwin Kernel Version 15.6.0: Thu Jun 23 18:25:34 PDT 2016; root:xnu-3248.60.10~1/RELEASE_X86_64 x86_64)
  3. What did you do? Tested the http2 implementation of go against Apache mod_h2, using a simple GET on a python CGI.
  4. What did you expect to see? The output from the CGI.
  5. What did you see instead? Go did hang and did not produce any results. The difference between a stuck GET and a successful one seems to be the EOF handling. On most responses Apache sets the EOF flag on the last DATA frame. However with CGI processes, the EOF is only encountered when the last DATA has already been written. In this case, Apache send a last DATA frame with length 0 and EOF=1. This seems to be ignored by the go implemenation, keeping it waiting.

Additionally to that, Apache will close the connection after a timeout, but the go client still will not return although the connection was properly closed.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 35 (10 by maintainers)

Commits related to this issue

Most upvoted comments

Well, let’s stay constructive.

Sorry, I didn’t mean to be come across as adversarial or disparage either @tatsuhiro-t or nghttp2. I was just trying to argue the point that if a protocol is new and is trying to be strict (as HTTP/2 is, especially compared to super-sloppy HTTP/1), implementations of the protocol must also be super strict, especially in the early days, otherwise all the strict wording in the spec is useless and a de-facto reality emerges and all of our implementations will forever have to deal with everybody’s corner cases. And I don’t think we would enjoy that.

I haven’t looked at the nghttp2 or Apache APIs and where the responsibility boundaries are, but I’m just very anxious about the idea of a library deciding to hide garbage from upper layers, when the garbage is specified in the specs as illegal.

Go’s http2 package is strict by default, but the Framer has AllowIllegalReads and AllowIllegalWrites (https://godoc.org/golang.org/x/net/http2#Framer) specifically to allow people to write testing tools to generate and accept garbage. But we never hide garbage from the user. We just return errors instead, hoping that causes push-back to the other side to be stricter.