crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.37k stars 1.62k forks source link

HTTP/2 support #2125

Open TheLonelyGhost opened 8 years ago

TheLonelyGhost commented 8 years ago

This is a feature request, tag it as you will. Since the specs have been clearly defined and do not appear to waver, I feel HTTP/2 should be supported in addition to HTTP/1.x.

Resources:

asterite commented 8 years ago

Thanks for adding this, we'll eventually need to support HTTP/2.

I'm not sure how it works, though. Will it integrate automagically with the current server? Because in Ilya Grigorik's implementation it doesn't look like it integrates with Rack. There's also this long thread which supports my guessing. And this Go talk which says that if you are using HTTPS and Go 1.6 you are using HTTP/2, so I guess it should be transparent.

Maybe @igrigorik could chime in and at least let us know if the current client/server implementation is easily upgradable to HTTP/2? :grin:

igrigorik commented 8 years ago

@asterite you can definitely abstract h2 behind the same API. That said, I do think you want to think carefully about the API to enable developers take advantage of h2: persistent connections, multiplexing, server push, etc. "Rack API", at least as it was defined for http/1.1, doesn't do a good job of this.

FWIW, check out the demo client/server examples in the ruby gem: https://github.com/igrigorik/http-2/tree/master/example

asterite commented 8 years ago

@igrigorik Thank you for replying, I'll take a look at the examples and see if I can port something to Crystal.

ysbaddaden commented 8 years ago

@asterite recently changed HTTP::Server from a Rack-like interface (get a request, return a response) to instead pass a Context object with the Request and Response objects that middlewares will change, each context being evaluated in its own coroutine.

I have a feeling that HTTP::Server could handle the HTTP/2 protocol, creating a Context object for each incoming Streams, using an intermediate IO to write to the Stream instead of the Socket —like deflate middleware currently does. The Context object could have additional methods for server push (among other HTTP/2 features), and either raise or silently skip when HTTP/2 isn't supported by the client.

Hopefully this wouldn't affect the current middleware API but enhance it.

ysbaddaden commented 8 years ago

An initial implementation is available: https://github.com/ysbaddaden/http2

If someone could point me to great HTTP2 compliance test suites, that would be very much appreciated.

The client part is untested. It should be capable to use HTTP2::Connection, but it may require some tweaks. It's integration into HTTP::Client may be tricky, especially since we can have many requests in parallel (yay, fibers!) and the API needs a callback to handle server-push promises (accept/refuse then receive data). We can prevent server-push by default, too. We also need to configure local HTTP2 settings (frame size, max concurrent streams, etc).

The server part is almost complete, except for flow control (required) and applying priorities to send frames (nice to have). It's capable to talk with nghttp (with or without TLS) and browsers (ie. Firefox and Chrome, TLS only) and it supports server-push.

Now we should start planning to integrate this into HTTP::Server. For example:

igrigorik commented 8 years ago

@ysbaddaden take a look at https://github.com/summerwind/h2spec

ysbaddaden commented 8 years ago

Thank you @igrigorik! I was able to reduce a bunch of corner cases in the protocol, down to 4 failures, most related to the unimplemented flow-control.

sdogruyol commented 7 years ago

Hey @ysbaddaden i remember you implementing HTTP/2 for Crystal. What's the status on that 😄

samueleaton commented 7 years ago

I too am very interested in the speed improvements that HTTP2 offers. I didn't know it had such wide support.

@ysbaddaden should the work you're doing for http2 be moved into a crystal branch? I wouldn't mind writing a bunch of specs for it.

MrSorcus commented 7 years ago

Up. Any progress?

spalladino commented 7 years ago

@DebugReport not that we are aware of. @samueleaton, if you are interested in contributing, I'd advise to do so in @ysbaddaden's repo, and as it's finished and tested, we can then include it into the stdlib.

jeromegn commented 6 years ago

As far as I can tell @ysbaddaden's http2 shard is feature-complete and passes all h2spec tests. Awesome work.

It doesn't look like there are any plans for integrating it back into Crystal though. I was planning on using it in my own project, a shard is fine, but I think it'd be nice to have in the std lib. I don't think http2 is going away.

luislavena commented 5 years ago

Hello @asterite, @bcardiff, @ysbaddaden, @waj and other core-team members,

Would like to bring to your attention this issue, hoping if possible to introduce the changes required to support HTTP/2 into the stdlib.

Not necessarily suggesting introduce HTTP/2 itself to the stdlib, but perhaps tweak HTTP::Server and friends to avoid the differences currently required to support it, in that way, someone can load the http2 shard and use when required.

Given that we are still in pre-1.0, perhaps is a good time to do some final breaking changes to the related API in preparation for that.

HTTP/2 support will also open the door to gRPC, which can increase interoperability of Crystal for certain teams and projects. Also worth to mention HTTP/3 is around the corner :wink:

Thank you for your hard and continuous work both Crystal core and other contributors, every new release gets better and better and you can feel how much sweat and hard work has been pour into it. Thank you! ❤️ ❤️ ❤️

Cheers.

RX14 commented 5 years ago

I think that HTTP needs a ground-up clean API redesign (without looking at the current API, the implementation is fine). It has collected a lot of issues which need to be collated into a requirements list for a HTTP module which is ready to be marked 1.0.

bcardiff commented 5 years ago

Regarding HTTP (Client/Server) we wanted a way to decouple the protocol implementation from the socket tls wrapper. That will allow simple http over unix socket and other use cases where a simple http api is needed. (And would actually remove the need for the without_openssl flag).

pyrsmk commented 3 years ago

As a side note about WebSockets working with HTTP/2, I'm dropping these articles here, for those who are interested :

https://hpbn.co/websocket/#websocket-multiplexing-and-head-of-line-blocking https://medium.com/@pgjones/http-2-websockets-81ae3aab36dd

And the related RFC :

https://tools.ietf.org/html/rfc8441

eliasjpr commented 3 years ago

Another take at Crystal HTTP2 implementation https://github.com/azutoolkit/duo

straight-shoota commented 10 months ago

I suppose at this point HTTP/2 support isn't that useful compared to HTTP/3 (which is basically the same, just based on QUIC instead of TCP). Recently released OpenSSL 3.2 has QUIC client support (server is expected to follow in the following release(s)), so this could serve for an easy integration into HTTP::Client. That would be more approachable than an additional QUIC library (which https://github.com/iv-org/lsquic.cr is using).

luislavena commented 3 months ago

Recently Ilya Grigorik released a pure-Ruby implementation of HTTP/2: https://github.com/igrigorik/http-2 that decouples the transport from the HTTP/2 processing.

dentarg commented 3 months ago

@luislavena that gem has been around since 2013 with the last release in 2021 before this recent flurry of activity that seems to be led by AWS (https://github.com/mullermp)

EDIT: Looks like http-2 1.0.0 is this fork https://gitlab.com/os85/http-2-next by https://github.com/HoneyryderChuck

There is also https://github.com/socketry/protocol-http2 by Samuel Williams

HCLarsen commented 3 months ago

I suppose at this point HTTP/2 support isn't that useful compared to HTTP/3 (which is basically the same, just based on QUIC instead of TCP).

I would say that it is just as useful, as it's possible that some clients/servers could support HTTP/2, but not HTTP/3. We should be going for all options that developers may be using.

In any case, is anyone working on a PR yet? If not, I may tackle this myself over the summer.

straight-shoota commented 3 months ago

You're right. I didn't realize at the time I wrote this, that there are still good reasons for HTTP/2.

I'm not aware of anyone working on this. Your help would be appreciated 👍

ryanprior commented 2 months ago

I had a conversation the other day about how I wish I had the background knowledge & time to take this on. A lot of tooling in the K8s/cluster orchestration space is based on HTTP2, and support for that stack in the core library would make crystal a much easier sell in the cloud ops space.

If somebody else wants to take point, I'd be happy to try and pitch in! I definitely don't have the right background to lead the effort, nor do I currently have the time to skill-up and read the relevant RFCs & existing implementations.

HCLarsen commented 2 months ago

Another thought about this. When making requests with HTTP::Client, it's entirely possible that someone may want to specify which HTTP protocol they want to use. Unless I'm missing it, there's currently no mechanism for that.

My first thought for a solution includes an enum for versions, and a constant that points to the newest version (Yes, I'm thinking forward compatibility).