The original `Connect` trait had some limitations:
- There was no way to provide more details to the connector about how to
connect, other than the `Uri`.
- There was no way for the connector to return any extra information
about the connected transport.
- The `Error` was forced to be an `std::io::Error`.
- The transport and future had `'static` requirements.
As hyper gains HTTP/2 support, some of these things needed to be
changed. We want to allow the user to configure whether they hope to
us ALPN to start an HTTP/2 connection, and the connector needs to be
able to return back to hyper if it did so.
The new `Connect` trait is meant to solve this.
- The `connect` method now receives a `Destination` type, instead of a
`Uri`. This allows us to include additional data about how to connect.
- The `Future` returned from `connect` now must be a tuple of the
transport, and a `Connected` metadata value. The `Connected` includes
possibly extra data about what happened when connecting.
BREAKING CHANGE: Custom connectors should now implement `Connect`
directly, instead of `Service`.
Calls to `connect` no longer take `Uri`s, but `Destination`. There
are `scheme`, `host`, and `port` methods to query relevant
information.
The returned future must be a tuple of the transport and `Connected`.
If no relevant extra information is needed, simply return
`Connected::new()`.
Closes#1428
This dedicated `Entity` trait replaces the previous `Stream<Item=impl
AsRef<[u8]>, Error=hyper::Error>`. This allows for several improvements
immediately, and prepares for HTTP2 support.
- The `Entity::is_end_stream` makes up for change away from
`Option<Body>`, which was previously used to know if the body should be
empty. Since `Request` and `Response` now require a body to be set,
this method can be used to tell hyper that the body is actually empty.
It also provides the possibility of slight optimizations when polling
for data, by allowing to check `is_end_stream` before polling again.
This can allow a consumer to know that a body stream has ended without
polling for `None` afterwards.
- The `Entity::content_length` method allows a body to automatically
declare a size, in case a user doesn't set a `Content-Length` or
`Transfer-Encoding` header.
- It's now possible to send and receive trailers, though this will be
for HTTP2 connections only.
By being a trait owned by hyper, new methods can be added later as new
features are wanted (with default implementations).
The `hyper::Body` type now implements `Entity` instead of `Stream`,
provides a better channel option, and is easier to use with custom
streams via `Body::wrap_stream`.
BREAKING CHANGE: All code that was assuming the body was a `Stream` must
be adjusted to use an `Entity` instead.
Using `hyper::Body` as a `Stream` can call `Body::into_stream`
to get a stream wrapper.
Passing a custom `impl Stream` will need to either implement
`Entity`, or as an easier option, switch to `Body::wrap_stream`.
`Body::pair` has been replaced with `Body::channel`, which returns a
`hyper::body::Sender` instead of a `futures::sync::mpsc::Sender`.
Closes#1438
BREAKING CHANGE: `Method`, `Request`, `Response`, `StatusCode`,
`Version`, and `Uri` have been replaced with types from the `http`
crate. The `hyper::header` module is gone for now.
Removed `Client::get`, since it needed to construct a `Request<B>`
with an empty body. Just use `Client::request` instead.
Removed `compat` cargo feature, and `compat` related API.
The higher-level `Client` has never supported `CONNECT` requests,
but it used to send them, and then handle the responses incorrectly.
Now, it will return an error immediately instead of misbehaving.
The HttpConnector's connect future was lazy, but if any custom connector
did not use a lazy future, then a connect would always be started, even
if an idle connection was available.
I couldn't figure out why my "username:password" strings kept failing to parse
into a Basic auth header, until I realized that the implementation expects
it to be base-64 encoded, which would be the case if it was coming from HTTP.
I'm not sure if this is the best place to document it, but hopefully it will
make it more clear for other people / me when I forget.
Perhaps a better approach would be to document somewhere that all `FromStr` impls for
headers are there for parsing request headers, and not really for creating them.
If a request sees an error on a pooled connection before ever writing
any bytes, it will now retry with a new connection.
This can be configured with `Config::retry_canceled_requests(bool)`.