On 6/18/20 8:55 PM, Roy T. Fielding wrote:
>> On Jun 18, 2020, at 9:03 AM, Stefan Eissing <[email protected]
>> <mailto:[email protected]>> wrote:
>>> Am 18.06.2020 um 16:51 schrieb William A Rowe Jr <[email protected]
>>> <mailto:[email protected]>>:
>>>
>>>
>>>>>>> On 6/18/20 12:09 AM, Roy T. Fielding wrote:
>>>>>>>>> On Jun 8, 2020, at 12:56 AM, Ruediger Pluem <[email protected]
>>>>>>>>> <mailto:[email protected]>> wrote:
>>>>>>>>>
>>>>>>>>> I came across the question if we should not reject HTTP protocols >=
>>>>>>>>> 2.0 in the request line when we parse it
>>>>>>>>> in ap_parse_request_line.
>>>>>>>>> This does not affect mod_http2 if loaded as HTTP/2.0 connections
>>>>>>>>> itself are not parsed via ap_parse_request_line
>>>>>>>>> and sending a
>>>>>>>>>
>>>>>>>>> GET /something HTTP/2.0
>>>>>>>>>
>>>>>>>>> as request line is not a valid way to start a HTTP 2.0 connection and
>>>>>>>>> I doubt that it will be for future major versions.
>>>
>>> Correct, it starts an HTTP/1.1 connection, and the response should reflect
>>> HTTP/1.1.
>>>
>>>>>>>> That isn't how these things typically work. New protocols are
>>>>>>>> advanced with either deliberate backwards-compat or deliberate
>>>>>>>> backwards-break, with an expectation that it will either do
>>>>>>>> something useful on an older-protocol server or cause a safe
>>>>>>>> error in an expected way.
>>>>>>>>
>>>>>>>> Hence, we might still see an HTTP/4.0 that is designed to be
>>>>>>>> parsed like HTTP/1.1 (by an old server) while at the same time
>>>>>>>> work perfectly for a new server. That would be some hefty magic,
>>>>>>>> but it remains possible. Likewise, we might want to deploy a
>>>>>>>> version of h2 or HTTP/3 that works on unix domain sockets or
>>>>>>>> localhost over non-Internet TCP.
>>>>>>>>
>>>>>>>> This is why the existing code did not error on protocols >= 2.0.
>>>>>>>> Doing so is both unnecessary and counterproductive. If parsing
>>>>>>>> fails for some other reason, we want that other reason to be
>>>>>>>> in the response (because that's what the new protocol will be
>>>>>>>> expecting from an old protocol server). If it doesn't fail, we
>>>>>>>> want to provide the successful response because the request
>>>>>>>> was deliberately crafted that way to save a round trip.
>>>>>>>>
>>>>>>>> Note that the incoming request protocol version should always
>>>>>>>> be distinct from any forwarded request protocol or response
>>>>>>>> protocol versions.
>>>
>>> Precisely. If mod_http2 or quic/mod_http3 can do something with the
>>> connection
>>> based on the request line, it's up to them through the hook facility to
>>> take ownership
>>> of the connection.
What I get out of all of this is the following:
If we get a
METHOD /somepath HTTP/x.y
request line on the wire.
We could return a 505 (Version not supported) if we know that we do not support
that major version x (e.g. HTTP/3
as mentioned below seem to be finished soon, but we do not have support for it
yet). The 505 answer would be a
HTTP/1.1 response.
But we could also accept this request as long as it is a valid HTTP/1.1 request
and just respond with the desired HTTP/1.1 response for this resource as if
this was sent with HTTP/1.1.
If it violates the HTTP/1.1 syntax somehow we would respond with the same
status code we use for this case
on a HTTP/1.1 request. That second approach is IMHO the behavior we had before
r1878708.
Provided that my above understanding is correct I see no real benefit any
longer in returning a 505 and I would
revert r1878708 and all the follow ups (from r1878926 only the changes to
modules/http2/h2_request.c and probably CHANGES as the
remaining changes are no functional changes to my understanding).
The positive thing I get out of this is that it revealed that we probably
should think about splitting some functions
that do some version agnostic HTTP processing and some HTTP/1.1 specific
processing in one place to make this distinction more
clear and the version agnostic HTTP processing code more reusable.
Many thanks to all for this constructive and focused discussion that taught me
new things.
>>
>> That is not issue. That works well.
>>
>>> If they cannot/do not, then the core http1 connection/request processors
>>> remain
>>> in place and in response to "please speak in HTTP/4.0" this server will
>>> respond,
>>> "sure, here is your HTTP/1.1 response" as expected and defined by the RFC.
>>
>> There are now several RFCs and they differentiate between HTTP/1.1 transport
>> and
>> the pure HTTP semantics. This split is not reflected in our code, yet. We
>> have
>> functions that mix both. Not as a mistake, it's historical.
>>
>> ap_parse_request_line() for example, checks the initial HTTP/1.1 request
>> line *and*
>> the method names, uri, header_only and other request_rec fields.
>>
>> We can either copy the latter into mod_http2 and maintain it in two places or
>> have a core function for it to be invoked by mod_http and mod_http2. That
>> seems
>> to be the design decision to make.
>
> I think that is the right way forward, though we have always tried
> to minimize overhead for the common case. I guess the extra cycles
> are irrelevant now.
>
>> I used ap_parse_request_line() from mod_http2 to *not* duplicate the other
>> code,
>> and someone added checks in trunk that imply it only ever gets called for
>> HTTP/1.x.
>> So, now it pukes. Which is good, as it brought up this discussion.
>
> Yep. The new RFCs should be "finished" by next month due to HTTP/3
> being in WGLC this month. If anyone's interested:
>
> https://github.com/httpwg/http-core
> https://github.com/quicwg/base-drafts
>
Regards
Rüdiger