Skip to content

HTTP/2 and HTTP/3 #423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
kraih opened this issue Dec 2, 2012 · 45 comments
Open

HTTP/2 and HTTP/3 #423

kraih opened this issue Dec 2, 2012 · 45 comments

Comments

@kraih
Copy link
Member

kraih commented Dec 2, 2012

The final HTTP/2 spec is still at least 1-2 years away, but now that the first draft (based on SPDY) has been released, i believe we can at least start planning our implementation.

http://tools.ietf.org/html/draft-ietf-httpbis-http2-00

While details like the upgrade mechanism from HTTP/1.1 and mandatory TLS encryption are very likely to change, major features like multiplexing are pretty much a given, and will require some refactoring in Mojolicious.

@kraih
Copy link
Member Author

kraih commented Dec 2, 2012

I've been thinking about this a bit, and i believe a new layer (Mojo::Channel?) between connection management and high level transactions would make adding new protocols and dealing with multiplexing a lot easier.

Mojo::UserAgent      -> Mojo::Channel::HTTP::Client      -> Mojo::Transaction::HTTP
                     -> Mojo::Channel::WebSocket::Client -> Mojo::Transaction::WebSocket

Mojo::Server::Daemon -> Mojo::Channel::HTTP::Server      -> Mojo::Transaction::HTTP
                     -> Mojo::Channel::WebSocket::Server -> Mojo::Transaction::WebSocket

Channels could combine all client_* and server_* methods from the transaction classes with the transaction management code of the user agent and daemon.

@kraih
Copy link
Member Author

kraih commented Dec 16, 2012

A good first step might be to move the transaction management code from Mojo::UserAgent to Mojo::Channel::HTTP::Client and Mojo::Channel::WebSocket::Client, that should be enough to figure out the right API and cause no backwards compatibility issues.

@ChinaXing
Copy link

+1

1 similar comment
@derbrown
Copy link

derbrown commented Apr 2, 2014

👍

@kraih
Copy link
Member Author

kraih commented May 30, 2014

The current version of the HTTP/2 spec terrifies me, think we'll wait with this as long as we can.

@kraih
Copy link
Member Author

kraih commented Jul 6, 2014

I believe the original Mojo::Channel plan might also have also been a bit too ambitious, better start with something that fits into the current architecture, and work on abstraction once we have more experience.

@kraih
Copy link
Member Author

kraih commented Jul 7, 2014

The HTTP/1 upgrade mechanism can be ignored completely, browser vendors are not going to implement that (Firefox and Chrome have confirmed this in the working group), only valid handshake for negotiating HTTP/2 will be TLS with ALPN/NPN. So IO::Socket::SSL and a modern version of OpenSSL will be hard requirements.

@kraih
Copy link
Member Author

kraih commented Aug 1, 2014

@kraih
Copy link
Member Author

kraih commented Dec 8, 2014

We need more volunteers to work on this.

@dvinciguerra
Copy link

I can help!

@kraih
Copy link
Member Author

kraih commented Dec 8, 2014

The plans i've outlined above were a bit too ambitious, that extra layer of abstraction is not really necessary. I think a good first step would be to start with a prototype, using an existing implementation of the HTTP/2 protocol (perhaps Protocol::HTTP2). Then the focus can be on getting protocol negotiation right, with NPN/ALPN in Mojo::IOLoop::Client/Mojo::IOLoop::Server, and HTTP1/HTTP2 in Mojo::UserAgent/Mojo::Server::Daemon.

I'm actually not too concerned about the actual protocol implementation, that seems pretty straight forward, and more about the integration into our existing architecture.

@kraih
Copy link
Member Author

kraih commented Dec 8, 2014

Since browsers like Chrome already support HTTP/2, i think a good first milestone would be to add NPN/ALPN support to Mojo::IOLoop::Server with IO::Socket::SSL, and then just enough Protocol::HTTP2 glue code to Mojo::Server::Daemon for basic request/response handling.

@kraih kraih changed the title HTTP/2.0 support HTTP/2 support Jan 7, 2015
@kraih
Copy link
Member Author

kraih commented Feb 19, 2015

The HTTP/2 spec was just finalized, and OpenSSL 1.0.2 with ALPN support has been released too. So theoretically nothing is stopping this feature anymore.

@kberov
Copy link
Contributor

kberov commented Feb 19, 2015

👍

@vlet
Copy link

vlet commented Apr 1, 2015

I don't familiar with Mojo internals, but i tried to implement glue code https://github.com/vlet/mojo/tree/vlet/http2-hacks
Protocol::HTTP2 API is not stable yet, so there is a opportunity to change it in a way, that will be convenient for Mojo

@kraih
Copy link
Member Author

kraih commented Apr 1, 2015

@vlet Thanks, that's a pretty decent proof of concept. The PSGI step should be avoided though, and the response might not be available right after the request event has been emitted (non-blocking operations in progress).

@rwx-zwx-awx
Copy link

Up ;) Would be great to have this implemented :)

@kraih
Copy link
Member Author

kraih commented Nov 21, 2015

This feature depends on #876.

@kraih
Copy link
Member Author

kraih commented Dec 15, 2015

This feature also depends on #888.

@s1037989
Copy link
Contributor

s1037989 commented Jan 7, 2016

Perhaps I'm naive, but I feel like if Mojolicious was first or among the first to release HTTP/2 support that it might help it to gain some attention and even many more new users.

@kraih
Copy link
Member Author

kraih commented Jan 7, 2016

Sadly we are already pretty far behind with this.

@kraih
Copy link
Member Author

kraih commented Jan 7, 2016

Honestly, i think unless we find a sponsor for this feature, it will take a very long time to get it production ready.

@kraih
Copy link
Member Author

kraih commented Jan 7, 2016

I imagine this might become a bigger topic once there are HTTP/2 only servers on the web, and folks want to access them with Mojo::UserAgent.

@s1037989
Copy link
Contributor

s1037989 commented Jan 7, 2016

What is needed from a sponsor? I don't have a ton of connections but I'd be happy to spread the word as best I can, as I already do for Mojolicious. Everyone in St. Louis, MO, USA is at least now aware that Mojolicious exists and is the greatest thing since sliced bread. :D

I'd also like to get my employer involved, so there's that...

Is there anything more that a sponsor can do than provide money? How much money? What is the process for this? Is there perhaps a not-for-profit entity for the purpose of tax deductible contributions (in the USA and/or otherwise)? I could look into establishing a not-for-profit organization in the USA if interested, I'm unaware at this point what the requirements of it are.

What would be the timeline to release a first version of this branch?

@kraih
Copy link
Member Author

kraih commented Jan 7, 2016

Realistically, i think it would take a good full-time programmer between 6 and 12 months to finish this feature. Currently there is no formal process, but if one or more interested companies step up, i'm sure we can change that pretty quickly.

There are a few milestones to reach, 1) protocols like HTTP/1.1 and WebSockets need to become pluggable (#876), 2) we need ALPN protocol negotiation (#888), 3) proof of concept implementation of the HTTP/2 protocol with an existing CPAN module like Protocol::HTTP2, 4) optimized custom implementation of the HTTP/2 protocol, 5) advanced features such as stream prioritization and server push.

@kraih
Copy link
Member Author

kraih commented Jan 12, 2016

After the very successful hackathon last weekend, i think 6 months is a very realistic timeframe.

@kberov
Copy link
Contributor

kberov commented Jan 13, 2016

👍 Thanks for the links!

@evoyy
Copy link

evoyy commented Jan 26, 2016

I would be happy to sponsor some dev time towards this.

@kraih kraih changed the title HTTP/2 support HTTP/2 Feb 17, 2016
@kraih
Copy link
Member Author

kraih commented Mar 1, 2016

ALPN support is done (#888), and pluggable protocols almost finished too (#876). I think a proof of concept HTTP/2 implementation might be possible now.

@kraih
Copy link
Member Author

kraih commented Mar 1, 2016

We do not have anyone from the core team working on this though, and need volunteers. My current estimate for reaching milestone 4 with a full-time programmer would be 2-3 months.

@kraih kraih mentioned this issue Mar 1, 2016
@kraih
Copy link
Member Author

kraih commented Mar 1, 2016

In the meantime, you can of course deploy Mojolicious applications with a reverse proxy that supports HTTP/2, such as NGINX. https://www.nginx.com/blog/nginx-1-9-5/

@kraih
Copy link
Member Author

kraih commented Sep 20, 2016

Good Perl bindings for nghttp2 would also help a lot with this feature.

@nbezzala
Copy link

Is anyone working on the proof of concept implementation? What does it involve? How do I start?

@yoe
Copy link

yoe commented Oct 7, 2017

The RFC8030 "Web Push" protocol (to send notifications to devices even while browsers are not necessarily running) is one of the first that is starting to require HTTP/2 for at least part of its implementation:

  • The client side requires HTTP/2, cannot be implemented with HTTP/1.1
  • The delivery of receipt messages to an application server (mojolicious in this case) is implemented as just another web push message, and therefore requires HTTP/2 from the server, too

If receipt messages are not required, then it should theoretically be possible to implement Web Push using just HTTP/1.1. However, the protocol requires a server known to the user agent, with defaults for those builtin to user agents; at some point it's going to be reasonable to assume for those servers that no application server is ever going to talk to them that doesn't support HTTP/2, and then this becomes a hard dependency.

@kraih
Copy link
Member Author

kraih commented Mar 27, 2018

Been some time since we last updated this issue. I think the approach with channels was wrong, and should be abandoned. Instead it might be better to start from the low level side, and create a few Mojo::IOLoop::Stream subclasses with code extracted from Mojo::Server::Daemon and Mojo::UserAgent.

Mojo::Server::Daemon -> Mojo::IOLoop::Stream::HTTPServer
                        Mojo::IOLoop::Stream::WebSocketServer

Mojo::UserAgent      -> Mojo::IOLoop::Stream::HTTPClient
                        Mojo::IOLoop::Stream::WebSocketClient

Big advantage of that approach is that those classes can be implemented parallel to everything we have now, usable and testable on their own. And once they work we can just reimplement Mojo::Server::Daemon and Mojo::UserAgent using those stream classes (hopefully with a lot less code).

Regarding the API, there are many options and i'm open to all suggestions, but to give you an idea for how it could look here's a Mojo::IOLoop::Stream::HTTPServer example.

Mojo::IOLoop->server({port => 8080, stream_class => 'Mojo::IOLoop::Stream::HTTPServer'} => sub {
  my ($loop, $stream) = @_;
  $stream->on(request => sub {
    my ($steam, $tx) = @_;

    my $method = $tx->req->method;
    my $path   = $tx->req->url->path;

    $tx->res->code(200);
    $tx->res->headers->content_type('text/plain');
    $tx->res->body("$method request for $path!");
    $tx->resume;
  });
});

And one for Mojo::IOLoop::Stream::HTTPClient. Here i'm less sure about the actual API, but you get the idea.

my $tx = Mojo::UserAgent::Transactor->new->tx(GET => 'http://mojolicious.org');
$tx->on(finish => sub {
  my $tx = shift;
  say $tx->res->code;
});
Mojo::IOLoop->client({port => 8080, stream_class => 'Mojo::IOLoop::Stream::HTTPClient'} => sub {
    my ($loop, $err, $stream) = @_;
    $stream->process($tx);
  });

The server is a lot easier than the client, so it would make sense to start there. How exactly the WebSocket upgrade is supposed to work, i'm not sure yet, but that can be added later, once HTTP works.

@CandyAngel
Copy link
Contributor

I've just started work on this :)

@kraih
Copy link
Member Author

kraih commented Jun 3, 2018

Thanks to #1227 we've made a big leap forward. HTTP/2 support can now be developed separately from Mojo::UserAgent and Mojo::Server::Daemon as Mojo::IOLoop::Stream::HTTP2Client and Mojo::IOLoop::Stream::HTTP2Server, which will make testing a lot easier.

@kraih
Copy link
Member Author

kraih commented Jun 3, 2018

ALPN is now also very easy to use with Mojo::IOLoop. c838dd1

@kraih
Copy link
Member Author

kraih commented Jun 3, 2018

And just a quick reminder. If anyone here decides to implement Mojo::IOLoop::Stream::HTTP2Client and/or Mojo::IOLoop::Stream::HTTP2Server with Protocol::HTTP2. Please do not use those names to release it to CPAN, we do want to use them for core Mojolicious.

@kraih
Copy link
Member Author

kraih commented Aug 9, 2018

Unfortunately the addition of stream classes caused big problems and had to be reverted. 61f6cbf Hopefully there will be another attempt with less race conditions and a clearer connection life cycle.

@kraih
Copy link
Member Author

kraih commented Nov 13, 2018

I guess we might as well skip HTTP/2 now and implement HTTP/3 instead. 😆

Edit: Some people did not get that this was a joke. It was.

@kraih kraih changed the title HTTP/2 HTTP/2 and/or HTTP/3 Nov 14, 2018
@kraih kraih changed the title HTTP/2 and/or HTTP/3 HTTP/2 and HTTP/3 Nov 14, 2018
@kraih kraih added difficult and removed difficult labels Jan 2, 2019
@kraih
Copy link
Member Author

kraih commented Jan 25, 2021

Time for an update. The landscape has changed a bit and we now know that HTTP/2 and HTTP/3 are mostly pointless for our web server. So it would make sense to focus on Mojo::UserAgent support. Through an XS binding for nghttp2.

@sergiotarxz
Copy link
Contributor

sergiotarxz commented Feb 14, 2024

Should the http/2 support respect the proxy settings at IO::Socket using nghttp2?

@kraih
Copy link
Member Author

kraih commented Feb 14, 2024

Should the http/2 support respect the proxy settings at IO::Socket using nghttp2?

If there are multiple solutions then i'd always be in favour of the one that results in the simplest code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests