[ruby-core:78168] [Ruby trunk Bug#12946] net-http is breaking valid http headers like HTTP2-Settings
From:
matthew@...
Date:
2016-11-16 08:28:17 UTC
List:
ruby-core #78168
Issue #12946 has been updated by Matthew Kerwin.
Tiago Cardoso wrote:
> It breaks because it sends the wrong-cased http header over the wire. From plaintext upgrade-to-http2:
>
> https://hpbn.co/http2/#upgrading-to-http2
>
> If you tcpdump the sent payload from a net-http client, it is sending "Http2-Settings". HTTP2 servers will reject that.
No they won't. From [RFC 7231](https://tools.ietf.org/html/rfc7230#section-3.2) (i.e. HTTP/1.1):
> Each header field consists of a case-insensitive field name followed
> by a colon (":"), optional leading whitespace, the field value, and
> optional trailing whitespace.
In HTTP/1.1 header field names are case-insensitive.
(In HTTP/2 they must be lower-case: https://tools.ietf.org/html/rfc7540#section-8.1.2 ; but that only applies after the upgrade dance has completed and you're encoding into HEADERS frames using HPACK.)
----------------------------------------
Bug #12946: net-http is breaking valid http headers like HTTP2-Settings
https://bugs.ruby-lang.org/issues/12946#change-61531
* Author: Tiago Cardoso
* Status: Open
* Priority: Normal
* Assignee:
* ruby -v:
* Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN
----------------------------------------
The Net::HTTPHeader can't process the `HTTP2-Settings` header, which is a valid header destined to pass base64-encoded settings to a soon-to-be-upgraded-to-http2 connection.
~~~ruby
req=Net::HTTP::Get.new
req["Upgrade"] = "h2c"
req["HTTP2-Settings] = "base64encoded=="
req.to_hash #=> "... Http2-Settings => ..."
~~~
Although one could say that net-http doesn't support to-http2-upgraded connections and even doesn't provide access to the raw socket, it's still a valid HTTP1.1 header, and the headers current MO "force to downcase and store; capitalize on fetch" works against custom Upgrade headers.
As of now, net-http can't upgrade. I'd suggest an API for such things, in that after a successful Upgrade request (101 switch protocols), the http connection "gives up" the socket to something else.
I had to monkey-patch my way out of this to make my code work: https://github.com/TiagoCardoso1983/jaguar/blob/master/test/test_helper.rb#L16-L25 .
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>