Serve HTTP/2 and HTTP/1.1 on one TLS port by ALPN - #82
Merged
Conversation
Livery owns the listen socket for this one rather than delegating it to h1 or h2, because only the process that ran the handshake knows which protocol the client asked for. A client that offered no ALPN is served HTTP/1.1: ALPN is what makes h2 over TLS possible, so its absence is HTTP/1.1, not an error. which_listeners/1 maps each protocol to a list of ports. One port can serve two protocols and one protocol can sit on two ports, neither of which the old one-port-per-protocol shape could express. The H1/H2 stream handle carries the negotiated ALPN as a third element. peer_info/1 returned a constant before, and the connection process is the only one that ever sees the real value. Also forwards h1's parser size limits, which h1 accepted but livery never passed on, and uses the service host to qualify the advertised Alt-Svc authority, which was documented but read by nothing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
https => #{..., alpn => [h2, http1]}, one TLS port serving both protocols, picked per connection. Livery owns the listen socket (livery_h1h2), handshakes off the accept path so a stalled client costs a process rather than an acceptor slot, reads the negotiated protocol, and hands the socket toh2:serve_socket/2orh1:serve_socket/2. A client that offered no ALPN goes to HTTP/1.1 rather than being dropped. The list is server preference order, so[h2, http1]means h2 wins when a client offers both. It defaults to[h2], which is the current h2-only behaviour, so existing users see no change.Two breaking changes come with it.
which_listeners/1now maps each protocol to a list of ports, because one port can serve two protocols and one protocol can sit on two ports;maps:get(h1, L)becomeshd(maps:get(h1, L)). And the H1/H2 stream handle is{Conn, StreamId, Alpn}, sopeer_info/1can report what ALPN actually settled on instead of a constant,undefinedon a cleartext listener or for a TLS client that offered none. H2 requests also carrytls => #{}on a TLS listener, as H1 requests already did.Separately, the H1 listener now forwards h1's parser size limits (
max_line_length,max_request_line_size,max_empty_lines, the header caps,pipeline), which h1 accepted all along but livery never passed on, andverifyfor mutual TLS now that h1 0.9.0 honours it. The servicehostis finally read: with it set,alt_svc => advertiseemits an authority-qualifiedAlt-Svc.livery_service:listener_opts()declares the options that worked but went undeclared, and says the rest of the map is forwarded to the adapter's ownlisten_opts().Deps: h1 0.9.0 and h2 0.12.0 for
serve_socket/2, webtransport 0.4.5 so it agrees with us on h2, hackney 4.7.4 for the pool fixes underlivery_client.Ships as 0.8.0.