-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
feat(client): initial support for HTTP/2 #448
Conversation
So excite. |
@@ -25,6 +25,8 @@ url = "*" | |||
traitobject = "*" | |||
typeable = "*" | |||
|
|||
[dependencies.solicit] | |||
git = "https://github.com/mlalic/solicit" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not on crates.io yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, not yet... I wanted to maintain some flexibility, without pushing multiple versions out to crates.io, if it turned out that I needed to do some changes there to make things work better in hyper
(so far it turned out that I didn't).
Of course it's something to do before finally landing this to make sure hyper
is pinned to a proper version.
+1, been waiting for this ever since HTTP2 came out :) |
@mlalic might be worth rewriting commits now just to get gitcop to shut up (I just deleted its comments since it's noise right now). |
/// `new()` call. This, however, means that all particular | ||
/// `HttpRequestFactory` implementations must have a set of default | ||
/// parameters with which they can be created. | ||
fn new() -> Self; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could get rid of this and just have HttpRequestFactory
inherit from Default
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice one.
Thanks for contributing! Unfortunately, I'm here to tell you there were the following style issues with your Pull Request:
Guidelines are available at https://github.com/hyperium/hyper/blob/master/CONTRIBUTING.md This message was auto-generated by https://gitcop.com |
Thanks for contributing! Unfortunately, I'm here to tell you there were the following style issues with your Pull Request:
Guidelines are available at https://github.com/hyperium/hyper/blob/master/CONTRIBUTING.md This message was auto-generated by https://gitcop.com |
So I've updated the PR based on the discussion so far: rebased the fixes that were made along the way to the corresponding commits and adapted the commit messages to the style guidelines (except the one that needs to be rebased out of the tree anyway!). The status is that with this, the public API of the client seems to be very nearly unaffected. The return type is now For now I also removed the |
So, what do you guys (@seanmonstar, @reem) think: should we go down this route? If so, I can bang this into shape with proper test coverage, documentation, error handling, etc. |
@mlalic sorry, been busy. I'll look it over again today. |
@mlalic I know Servo uses I have a Pool implementation in #486. That would allow keeping the requests around, and having h1 -> h2 upgrade functionality. What did you think of my previous suggestion of keeping Client, Request, and Response as opaque structs, and having the trait be a |
Indeed, currently the establishment of the underlying TCP connection that the HTTP/2 connection would use is somewhat hidden away, but letting it use the
The way the pool is implemented right now doesn't lend itself at all to reusing connections for HTTP/2. What is currently pooled are the tcp connections, not HTTP connections. This is virtually the same for h1, but it is not so for h2. This is because in h1, you can simply send the raw request bytes on one of the established tcp streams and you're good; no previously sent requests on that particular stream matter for the raw payload that you transmit over the wire, nor for the parsing of the response payload. In h2, however, the payload you send for a request does depend on previously sent requests - you need to assign a new stream id, hpack encoding/decoding the headers is stateful, flow control windows depend on previously sent data, etc. Therefore, simply pooling the TCP connections does nothing to allow "keep alive"-like usage of an HTTP/2 connection. Of course, it's doable to pool the actual HTTP 2 connections, by doing what you've done on the connector level within (what is currently named in this pr) the
I don’t think I fully understood what you were aiming at with the The way it looks like it would be used would to implement the request's So, I don’t see the benefit of this alternate approach. It seems it would only shift the actual protocol logic a level lower... Is it that you hope to reuse this Originally, when you wrote that comment, I thought the suggestion was so that we avoid having type parameters on the Perhaps you could flesh out your proposal more because I just might not be fully getting the idea from the previous short description. |
I'll expore in a branch to show what I mean. |
@seanmonstar I have an experiment over on this branch (forked off the current master HEAD, not this PR) refactoring the HTTP/1.1-specific parts of Is this sort of what you had in mind for the |
Pretty much exactly. As long as such a trait could work for http2, of On Mon, May 25, 2015, 3:56 PM Marko Lalic [email protected] wrote:
|
The trait does work out quite nicely for HTTP/2 too. So, here's an attempt at landing the PR, this time with everything polished up with proper docs and tests for the new features. Feedback of course appreciated. (Side note: the |
Sorry, I was camping this weekend (so no Internet), but this looks exciting! |
@@ -108,6 +114,12 @@ impl From<httparse::Error> for Error { | |||
} | |||
} | |||
|
|||
impl From<Http2Error> for Error { | |||
fn from(err: Http2Error) -> Error { | |||
Error::Http2(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a from_and_cause!
case to the tests below, to keep the coverage happy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
BREAKING CHANGE: `hyper::client::request::Response` is no longer generic over `NetworkStream` types. It no longer requires a generic type parameter at all.
Automatic conversion from the `solicit::http::HttpError` is also provided. BREAKING CHANGE: A new variant `Http2` added to a public enum `hyper::Error`.
Just curious, from the example: |
feat(client): initial support for HTTP/2
@mlalic woo! thanks for this herculean effort! |
Happy to do it! Glad we've worked out the initial integration; we can take it from here and tweak/improve things incrementally, of course... Should be less of a big-bang than this :) |
|
This PR adds initial support for HTTP/2 requests.
It introduces a new pair of traits:
HttpMessage
andProtocol
.The
HttpMessage
trait provides an API that abstracts the sending and receiving of HTTP messages away from the concrete implementation of the underlying protocol.The
Protocol
trait provides an API for constructing newHttpMessage
s.The
Request
andResponse
structs are refactored to internally use aBox<HttpMessage>
for their HTTP communication requirements.The
Client
has a new public method:with_protocol
. This provides an API for plugging in a particularProtocol
implementation that will then be used for constructing theHttpMessage
instances that are passed to theRequest
struct constructor.The implementation of this API (i.e. the two traits) for HTTP/2 is provided in the
hyper::http2
module.Therefore, now it is possible to inject an
Http2Protocol
instance when constructing ahyper::Client
which seamlessly makes it switch to using HTTP/2.The
Http2Protocol
can use the existingNetworkConnector
API for constructing the network connection for the underlying communication. However, do note that the current TLS connector does not honor the requirements that the HTTP/2 spec additionally makes for TLS connections (particular cipher suits are banned, applications must use ALPN -- or at least NPN -- for protocol negotiation), so if such a connector is provided, it won't be possible to establish an HTTP/2 connection. The cleartext TCP connectors work as expected.An example is included in
examples/client_http2.rs
showing how the client can be configured to use HTTP/2.Breaking Changes
The PR introduces only a few minor, however still breaking changes:
hyper::client::Response
struct no longer requires any type parameters.hyper::Error
public enum has gained a new variantHttp2