http2: make Transport not reuse conns after a stream protocol error

If a server sends a stream error of type "protocol error" to a client,
that's the server saying "you're speaking http2 wrong". At that point,
regardless of whether we're in the right or not (that is, regardless of
whether the Transport is bug-free), clearly there's some confusion and
one of the two parties is either wrong or confused. There's no point
pushing on and trying to use the connection and potentially exacerbating
the confusion (as we saw in golang/go#47635).

Instead, make the client "poison" the connection by setting a new "do
not reuse" bit on it. Existing streams can finish up but new requests
won't pick that connection.

Also, make those requests as retryable without the caller getting an
error.

Given that golang/go#42777 existed, there are HTTP/2 servers in the
wild that incorrectly set RST_STREAM PROTOCOL_ERROR codes. But even
once those go away, this is still a reasonable fix for preventing
a broken connection from being stuck in the connection pool that fails
all future requests if a similar bug happens in another HTTP/2 server.

Updates golang/go#47635

Change-Id: I3f89ecd1d3710e49f7219ccb846e016eb269515b
Reviewed-on: https://go-review.googlesource.com/c/net/+/347033
Trust: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
3 files changed
tree: 0cad27ef3c8dd1f930899720d43f861d88c76c9c
  1. .gitattributes
  2. .gitignore
  3. AUTHORS
  4. CONTRIBUTING.md
  5. CONTRIBUTORS
  6. LICENSE
  7. PATENTS
  8. README.md
  9. bpf/
  10. codereview.cfg
  11. context/
  12. dict/
  13. dns/
  14. go.mod
  15. go.sum
  16. html/
  17. http/
  18. http2/
  19. icmp/
  20. idna/
  21. internal/
  22. ipv4/
  23. ipv6/
  24. lif/
  25. nettest/
  26. netutil/
  27. proxy/
  28. publicsuffix/
  29. route/
  30. trace/
  31. webdav/
  32. websocket/
  33. xsrftoken/
README.md

Go Networking

Go Reference

This repository holds supplementary Go networking libraries.

Download/Install

The easiest way to install is to run go get -u golang.org/x/net. You can also manually git clone the repository to $GOPATH/src/golang.org/x/net.

Report Issues / Send Patches

This repository uses Gerrit for code changes. To learn how to submit changes to this repository, see https://golang.org/doc/contribute.html. The main issue tracker for the net repository is located at https://github.com/golang/go/issues. Prefix your issue with “x/net:” in the subject line, so it is easy to find.