On Wed, Dec 9, 2015 at 1:57 PM, Jacob Champion <champio...@gmail.com> wrote:
> On 12/09/2015 09:17 AM, William A Rowe Jr wrote: > >> On Tue, Dec 8, 2015 at 9:10 PM, Roy T. Fielding <field...@gbiv.com >> <mailto:field...@gbiv.com>> wrote: >> >> This should be easily handled by adding a filter that translates the >> HTTP/1 >> incoming body (if any) to a single channel of the new protocol. >> Just fake it. >> There is no need to wait or set aside the bytes, unless that is >> desired for >> other reasons (e.g., denial of denial of service attacks). >> >> However, we must read the request body complete before the input handler >> is toggled to the h2c state, or before we switch to any bidirectional >> protocol, e.g. TLS or otherwise. >> > > For my own clarification: this is a protocol-specific limitation, right? > As in, you can't begin a TLS handshake without first draining the incoming > request body off the connection. Because the request body is inbound already at some state of completion or incomplete transmission, it is competing with the TLS handshake, which is a bidirectional engagement with the same socket between the user agent and server. Unlike h2c and websocket, where Roy suggests we leave the http/1 input filter in place and inject the http/2 output filter for the duration of the initial Upgrade: request, we must pass TLS traffic in both directions at once during Upgrade: TLS. Also, the results of the TLS handshake are interesting to authnz configuration and need to be available throughout those request phases. This means that for any Upgrade: TLS request must be satisfied (101 switching protocols) prior to those auth phases. In the case of h2c and websocket, the http/1.1 request headers are sufficient to begin processing the request. At the end of the first request, the input filter is also toggled into the new protocol to resume processing of all subsequent requests. So this Upgrade: handling must occur before the request handler is invoked, even a simple handler like 'OPTIONS *', Please remember that a request handler is based on a method and location, while Upgrade is not the request itself, but a proposal to switch protocols. In the case of TLS and h2c, that request is satisfied over the corresponding HTTP/1 or HTTP/2 output filter, but I'm not clear whether websocket has any equivalence in terms of a content handler phase. > 3. When to do the upgrade dance: >> > a post_read_request: upgrade precedes authentication >> > b handler: upgrade only honored on authenticated and otherwise ok >> requests >> > c both: introduce separate hooks? have an additional parameter? >> more complexity >> >> (a). We do want to upgrade non-ok responses. If the "new" protocol >> wants to >> send a canned HTTP/1.1 error, it can do so without our help. >> >> +1 in the case of h2c, TLS. I understand that websocket upgrades are >> going to be conditional on authentication. As long as we give websocket >> the chance to upgrade in the fixups or similar phase, after auth, then >> websocket can ignore the Upgrade: websocket offer after inspecting authnz. >> > > Sounds reasonable. Unfortunate in the sense that it's possible for a > module implementing the Upgrade API to screw up and accidentally ignore > authnz, but since most protocols we're talking about can safely upgrade > first and respond with 401/3 on the new protocol, I don't see much of an > alternative. > Howso? Any module can have any bug, I don't see your objection. I think we agree that TLS upgrades happen early, h2c/websocket upgrades happen late (before the content handler is invoked), and if either the protocol module or an auth module has a bug, we fix the bugs as with any other code in the server. Right? > 4. status code of protocol switch handler: if we move the task of 101 >> sending, the switch handler might not do it and keep the connection on the >> "old" protocol. Then a connection close is not necessary. So, we would do >> the close only when the switch handler returns APR_EOF. >> >> Eh? >> >> I'm wondering the same, the new protocol loop can do all of the >> connection handling, no need for the protocol switch to do anything but >> continue, if the connection is ended in the protocol handler, it's gone. >> > > Why leave it up to the protocol handler (to potentially get wrong)? Are > there any cases where, after a successful upgrade, we would not want to > close the connection upon returning from the protocol handler? Why are you focused on such bugs? It isn't making any sense. If the module sends a response or indicates the connection is closed, there is nothing more that happens in the request processing loop anyways. This isn't for the core Protocol API to solve, IMHO.