feat(lib): replace types with those from http crate

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.
This commit is contained in:
Sean McArthur
2018-02-28 16:37:17 -08:00
parent a37e6b59e6
commit 3cd48b45fb
109 changed files with 1004 additions and 14411 deletions

View File

@@ -9,21 +9,14 @@ use std::time::Duration;
use futures::{Async, Future, Poll, Stream};
use futures::future::{self, Executor};
#[cfg(feature = "compat")]
use http;
use http::{Method, Request, Response, Uri, Version};
use http::header::{Entry, HeaderValue, HOST};
use tokio::reactor::Handle;
pub use tokio_service::Service;
use header::{Host};
use proto;
use proto::request;
use method::Method;
use proto::{self, Body};
use self::pool::Pool;
use uri::{self, Uri};
use version::HttpVersion;
pub use proto::response::Response;
pub use proto::request::Request;
pub use self::connect::{HttpConnector, Connect};
use self::background::{bg, Background};
@@ -34,8 +27,6 @@ mod connect;
pub(crate) mod dispatch;
mod dns;
mod pool;
#[cfg(feature = "compat")]
pub mod compat;
mod signal;
#[cfg(test)]
mod tests;
@@ -113,14 +104,29 @@ where C: Connect,
B: Stream<Error=::Error> + 'static,
B::Item: AsRef<[u8]>,
{
/// Send a GET Request using this Client.
#[inline]
pub fn get(&self, url: Uri) -> FutureResponse {
self.request(Request::new(Method::Get, url))
/// Send a `GET` request to the supplied `Uri`.
///
/// # Note
///
/// This requires that the `Entity` type have a `Default` implementation.
/// It *should* return an "empty" version of itself, such that
/// `Entity::is_end_stream` is `true`.
pub fn get(&self, uri: Uri) -> FutureResponse
where
B: Default,
{
let body = B::default();
if !body.is_end_stream() {
warn!("default Entity used for get() does not return true for is_end_stream");
}
let mut req = Request::new(body);
*req.uri_mut() = uri;
self.request(req)
}
/// Send a constructed Request using this Client.
#[inline]
pub fn request(&self, mut req: Request<B>) -> FutureResponse {
// TODO(0.12): do this at construction time.
//
@@ -131,23 +137,25 @@ where C: Connect,
self.schedule_pool_timer();
match req.version() {
HttpVersion::Http10 |
HttpVersion::Http11 => (),
Version::HTTP_10 |
Version::HTTP_11 => (),
other => {
error!("Request has unsupported version \"{}\"", other);
error!("Request has unsupported version \"{:?}\"", other);
return FutureResponse(Box::new(future::err(::Error::Version)));
}
}
if req.method() == &Method::Connect {
if req.method() == &Method::CONNECT {
debug!("Client does not support CONNECT requests");
return FutureResponse(Box::new(future::err(::Error::Method)));
}
let domain = match uri::scheme_and_authority(req.uri()) {
Some(uri) => uri,
None => {
debug!("request uri does not include scheme and authority");
let uri = req.uri().clone();
let domain = match (uri.scheme_part(), uri.authority_part()) {
(Some(scheme), Some(auth)) => {
format!("{}://{}", scheme, auth)
}
_ => {
return FutureResponse(Box::new(future::err(::Error::Io(
io::Error::new(
io::ErrorKind::InvalidInput,
@@ -156,45 +164,51 @@ where C: Connect,
))));
}
};
if self.set_host && !req.headers().has::<Host>() {
let host = Host::new(
domain.host().expect("authority implies host").to_owned(),
domain.port(),
);
req.headers_mut().set_pos(0, host);
if self.set_host {
if let Entry::Vacant(entry) = req.headers_mut().entry(HOST).expect("HOST is always valid header name") {
let hostname = uri.host().expect("authority implies host");
let host = if let Some(port) = uri.port() {
let s = format!("{}:{}", hostname, port);
HeaderValue::from_str(&s)
} else {
HeaderValue::from_str(hostname)
}.expect("uri host is valid header value");
entry.insert(host);
}
}
let client = self.clone();
let is_proxy = req.is_proxy();
let uri = req.uri().clone();
//TODO: let is_proxy = req.is_proxy();
//let uri = req.uri().clone();
let fut = RetryableSendRequest {
client: client,
future: self.send_request(req, &domain),
domain: domain,
is_proxy: is_proxy,
uri: uri,
//is_proxy: is_proxy,
//uri: uri,
};
FutureResponse(Box::new(fut))
}
/// Send an `http::Request` using this Client.
#[inline]
#[cfg(feature = "compat")]
pub fn request_compat(&self, req: http::Request<B>) -> compat::CompatFutureResponse {
self::compat::future(self.call(req.into()))
}
/// Convert into a client accepting `http::Request`.
#[cfg(feature = "compat")]
pub fn into_compat(self) -> compat::CompatClient<C, B> {
self::compat::client(self)
}
//TODO: replace with `impl Future` when stable
fn send_request(&self, req: Request<B>, domain: &Uri) -> Box<Future<Item=Response, Error=ClientError<B>>> {
//fn send_request(&self, req: Request<B>, domain: &Uri) -> Box<Future<Item=Response, Error=::Error>> {
fn send_request(&self, mut req: Request<B>, domain: &str) -> Box<Future<Item=Response<Body>, Error=ClientError<B>>> {
let url = req.uri().clone();
let checkout = self.pool.checkout(domain.as_ref());
let path = match url.path_and_query() {
Some(path) => {
let mut parts = ::http::uri::Parts::default();
parts.path_and_query = Some(path.clone());
Uri::from_parts(parts).expect("path is valid uri")
},
None => {
"/".parse().expect("/ is valid path")
}
};
*req.uri_mut() = path;
let checkout = self.pool.checkout(domain);
let connect = {
let executor = self.executor.clone();
let pool = self.pool.clone();
@@ -228,7 +242,6 @@ where C: Connect,
ClientError::Normal(e)
});
let executor = self.executor.clone();
let resp = race.and_then(move |mut pooled| {
let conn_reused = pooled.is_reused();
@@ -284,7 +297,7 @@ where C: Connect,
B::Item: AsRef<[u8]>,
{
type Request = Request<B>;
type Response = Response;
type Response = Response<Body>;
type Error = ::Error;
type Future = FutureResponse;
@@ -315,7 +328,7 @@ impl<C, B> fmt::Debug for Client<C, B> {
/// A `Future` that will resolve to an HTTP Response.
#[must_use = "futures do nothing unless polled"]
pub struct FutureResponse(Box<Future<Item=Response, Error=::Error> + 'static>);
pub struct FutureResponse(Box<Future<Item=Response<Body>, Error=::Error> + 'static>);
impl fmt::Debug for FutureResponse {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -324,7 +337,7 @@ impl fmt::Debug for FutureResponse {
}
impl Future for FutureResponse {
type Item = Response;
type Item = Response<Body>;
type Error = ::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
@@ -334,10 +347,10 @@ impl Future for FutureResponse {
struct RetryableSendRequest<C, B> {
client: Client<C, B>,
domain: Uri,
future: Box<Future<Item=Response, Error=ClientError<B>>>,
is_proxy: bool,
uri: Uri,
domain: String,
future: Box<Future<Item=Response<Body>, Error=ClientError<B>>>,
//is_proxy: bool,
//uri: Uri,
}
impl<C, B> Future for RetryableSendRequest<C, B>
@@ -346,7 +359,7 @@ where
B: Stream<Error=::Error> + 'static,
B::Item: AsRef<[u8]>,
{
type Item = Response;
type Item = Response<Body>;
type Error = ::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
@@ -367,9 +380,6 @@ where
}
trace!("unstarted request canceled, trying again (reason={:?})", reason);
let mut req = request::join(req);
req.set_proxy(self.is_proxy);
req.set_uri(self.uri.clone());
self.future = self.client.send_request(req, &self.domain);
}
}
@@ -394,7 +404,7 @@ pub(crate) enum ClientError<B> {
Normal(::Error),
Canceled {
connection_reused: bool,
req: (::proto::RequestHead, Option<B>),
req: Request<B>,
reason: ::Error,
}
}