sozu icon indicating copy to clipboard operation
sozu copied to clipboard

Initial H2 thought by geal

Open Geal opened this issue 8 years ago • 6 comments

In gitlab by @Geal on Jan 11, 2017, 11:15

right now, the proxy supports HTTP, HTTPS, TCP, and Websockets. It can upgrade a connection between protocols, but the condition is always that the protocol is the same for client<->proxy and proxy<->backend connections.

With HTTP/2, we want to support different use cases, like:

  • client <- HTTP/2 -> proxy and proxy <- HTTP 1.1 -> backend, with possibly multiple connections to the backend that will be multiplexed for the frontend
  • client <- HTTP 1.1 -> proxy and proxy <- HTTP/2 -> backend to support HTTP 1.1 for web frameworks that will only support HTTP/2

And this should be working with protocol upgrades as well.

First thoughts:

  • will this only affect HTTP 1.1 and HTTP/2? The proxy does not support many protocols yet, but there might be other cases we can take inspiration from, and plan for
  • this means having separate protocols for readable/writable and back_readable/back_writable functions, and a way to transform state back and forth
  • the HTTP proxy tries to keep the data unparsed as much as possible. Transforming headers between HTTP 1.1 and HTTP/2 means parsing the buffer, returning a header, make it a HTTP/2 header, and write it to the output buffer if necessary
  • while both protocols will probably supported by the frontend, backend servers may not support both. So we have to decide if we keep the data in the buffer for a HTTP 1.1<->HTTP 1.1 connection, or if we transform it to HTTP/2
  • one HTTP/2 connection with the client, multiple HTTP 1.1 connections on the backend: this will be annoying to implement

Plan (for now):

  • [ ] refactor the event loop #257
  • [ ] Add protocol info to backends #258
  • [ ] support ALPN extension and upgrade to a placeholder HTTP/2 implementation
  • [ ] implement frame parser and serializer. nom and cookie factory should be ok
  • [ ] start working on the initial messages
  • [ ] integrate a HPACK implementation. It's probably not useful to write a new one from scratch
  • [ ] implement the stream state machine
  • [ ] implement the flow control policy (as a separate struct with lots of unit tests)
  • [ ] implement the frame priority and dependency calculation (as a separate struct with lots of unit tests)
  • [ ] find a new buffer abstraction, since the one currently in use will probably not be adapted to a multiplexed protocol
  • [ ] end to end patterns:
    • [ ] first, assume there's only one backend, and it supports HTTP/2 (needs TLS on the backend)
    • [ ] then, make sure we can still connect with HTTP 1.* over TLS to that backend
    • [ ] associate HTTP/2 streams to backends. We need a configurable limit for the number of streams in a connection
    • [ ] check the behaviour of load balancing streams with buffer borrows
  • [ ] investigate routing for protocols like gRPC

Geal avatar Jan 18 '17 14:01 Geal

depends on #257 and #258

Geal avatar Oct 18 '17 09:10 Geal

RFC 7540 for HTTP/2: http://httpwg.org/specs/rfc7540.html RFC 7541 for HPACK (header compression): http://httpwg.org/specs/rfc7541.html

Parsing and generating the different frames should not be too hard. Handling the ALPN dance will be ok too. The stream state machine is well defined (there are still lots of details and failure cases to handle correctly). The complex part appears to be in flow control and stream priorities. About half the mentions of proxy specific behaviour are around the CONNECT HTTP method, which may not be really interesting to handle for now.

Geal avatar Oct 18 '17 10:10 Geal

Parts of https://github.com/carllerche/h2 might be reusable. https://github.com/mlalic/hpack-rs is not really maintained. https://github.com/carllerche/bytes would be interesting for buffer handling, since it can work correctly with multiple subsets of the data: https://carllerche.github.io/bytes/bytes/struct.Bytes.html

Geal avatar Oct 18 '17 10:10 Geal

development has started in the h2 branch. It is only plugged into the HTTPS Openssl proxy for now.

How to test

cf https://blog.cloudflare.com/tools-for-debugging-testing-and-using-http-2/

curl

curl --http2 -kv http://lolcatho.st:8443/

h2c

~/.go/bin/h2c connect lolcatho.st:8443
~/.go/bin/h2c get /

Compliance

We will need to test with h2spec

Current version is using the hpack crate, we might need to write a new one at some point

Related issues:

  • half protocol implementations #540
  • Move away from BufferQueue as basic element for everything #541
  • functions concerning back sockets should take a token as argument #542
  • HTTP 1 client implementation #543

Geal avatar Oct 11 '18 16:10 Geal

some things to keep in mind for this implementation: https://github.com/Netflix/security-bulletins/blob/master/advisories/third-party/2019-002.md

Geal avatar Sep 14 '19 13:09 Geal

With HTTP/3 coming, it’s high time to support http/2, isn’t it? Any idea when this support will be available?

dlecan avatar Dec 27 '20 17:12 dlecan