Skip to content

Commit

Permalink
feat(client): Make client an optional feature
Browse files Browse the repository at this point in the history
cc #2223

BREAKING CHANGE: The HTTP client of hyper is now an optional feature. To
  enable the client, add `features = ["client"]` to the dependency in
  your `Cargo.toml`.
  • Loading branch information
seanmonstar committed Nov 18, 2020
1 parent eb092a7 commit 4e55583
Show file tree
Hide file tree
Showing 19 changed files with 238 additions and 164 deletions.
5 changes: 4 additions & 1 deletion Cargo.toml
Expand Up @@ -74,11 +74,12 @@ pnet = "0.25.0"
default = [
"runtime",
"stream",

"client",
"http1",
"http2",
]
full = [
"client",
"http1",
"http2",
"stream",
Expand All @@ -99,6 +100,8 @@ tcp = [
http1 = []
http2 = ["h2"]

client = []

# `impl Stream` for things
stream = []

Expand Down
13 changes: 12 additions & 1 deletion src/body/body.rs
Expand Up @@ -6,6 +6,7 @@ use std::fmt;
use bytes::Bytes;
use futures_channel::mpsc;
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
use futures_channel::oneshot;
use futures_core::Stream; // for mpsc::Receiver
#[cfg(feature = "stream")]
Expand All @@ -18,6 +19,7 @@ use super::DecodedLength;
use crate::common::sync_wrapper::SyncWrapper;
use crate::common::{task, watch, Pin, Poll};
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
use crate::common::{Future, Never};
#[cfg(feature = "http2")]
use crate::proto::h2::ping;
Expand Down Expand Up @@ -72,16 +74,19 @@ struct Extra {
}

#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
type DelayEofUntil = oneshot::Receiver<Never>;

enum DelayEof {
/// Initial state, stream hasn't seen EOF yet.
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
NotEof(DelayEofUntil),
/// Transitions to this state once we've seen `poll` try to
/// return EOF (`None`). This future is then polled, and
/// when it completes, the Body finally returns EOF (`None`).
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
Eof(DelayEofUntil),
}

Expand Down Expand Up @@ -219,6 +224,7 @@ impl Body {
}

#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
pub(crate) fn delayed_eof(&mut self, fut: DelayEofUntil) {
self.extra_mut().delayed_eof = Some(DelayEof::NotEof(fut));
}
Expand All @@ -242,6 +248,7 @@ impl Body {
fn poll_eof(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<crate::Result<Bytes>>> {
match self.take_delayed_eof() {
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
Some(DelayEof::NotEof(mut delay)) => match self.poll_inner(cx) {
ok @ Poll::Ready(Some(Ok(..))) | ok @ Poll::Pending => {
self.extra_mut().delayed_eof = Some(DelayEof::NotEof(delay));
Expand All @@ -258,6 +265,7 @@ impl Body {
Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
},
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
Some(DelayEof::Eof(mut delay)) => match Pin::new(&mut delay).poll(cx) {
Poll::Ready(Ok(never)) => match never {},
Poll::Pending => {
Expand All @@ -266,7 +274,10 @@ impl Body {
}
Poll::Ready(Err(_done)) => Poll::Ready(None),
},
#[cfg(not(any(feature = "http1", feature = "http2")))]
#[cfg(any(
not(any(feature = "http1", feature = "http2")),
not(feature = "client")
))]
Some(delay_eof) => match delay_eof {},
None => self.poll_inner(cx),
}
Expand Down
53 changes: 33 additions & 20 deletions src/cfg.rs
@@ -1,37 +1,50 @@
macro_rules! cfg_any_http {
($($item:item)*) => {
macro_rules! cfg_feature {
(
#![$meta:meta]
$($item:item)*
) => {
$(
#[cfg(any(
feature = "http1",
feature = "http2",
))]
#[cfg_attr(docsrs, doc(cfg(any(
feature = "http1",
feature = "http2",
))))]
#[cfg($meta)]
#[cfg_attr(docsrs, doc(cfg($meta)))]
$item
)*
}
}

macro_rules! cfg_any_http {
($($item:item)*) => {
cfg_feature! {
#![any(feature = "http1", feature = "http2")]
$($item)*
}
}
}

cfg_any_http! {
macro_rules! cfg_http1 {
($($item:item)*) => {
$(
#[cfg(feature = "http1")]
#[cfg_attr(docsrs, doc(cfg(feature = "http1")))]
$item
)*
cfg_feature! {
#![feature = "http1"]
$($item)*
}
}
}

macro_rules! cfg_http2 {
($($item:item)*) => {
$(
#[cfg(feature = "http2")]
#[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
$item
)*
cfg_feature! {
#![feature = "http2"]
$($item)*
}
}
}

macro_rules! cfg_client {
($($item:item)*) => {
cfg_feature! {
#![feature = "client"]
$($item)*
}
}
}
}
2 changes: 1 addition & 1 deletion src/client/conn.rs
Expand Up @@ -25,7 +25,7 @@ use tower_service::Service;

use super::dispatch;
use crate::body::HttpBody;
use crate::common::{task, BoxSendFuture, Exec, Future, Pin, Poll};
use crate::common::{task, exec::{BoxSendFuture, Exec}, Future, Pin, Poll};
use crate::proto;
use crate::rt::Executor;
#[cfg(feature = "http1")]
Expand Down
2 changes: 1 addition & 1 deletion src/client/mod.rs
Expand Up @@ -62,7 +62,7 @@ use http::{Method, Request, Response, Uri, Version};
use self::connect::{sealed::Connect, Alpn, Connected, Connection};
use self::pool::{Key as PoolKey, Pool, Poolable, Pooled, Reservation};
use crate::body::{Body, HttpBody};
use crate::common::{lazy as hyper_lazy, task, BoxSendFuture, Future, Lazy, Pin, Poll};
use crate::common::{lazy as hyper_lazy, task, exec::BoxSendFuture, Future, Lazy, Pin, Poll};
use crate::rt::Executor;

#[cfg(feature = "tcp")]
Expand Down
4 changes: 2 additions & 2 deletions src/client/pool.rs
Expand Up @@ -11,7 +11,7 @@ use futures_channel::oneshot;
use tokio::time::{Duration, Instant, Interval};

use super::Ver;
use crate::common::{task, Exec, Future, Pin, Poll, Unpin};
use crate::common::{task, exec::Exec, Future, Pin, Poll, Unpin};

// FIXME: allow() required due to `impl Trait` leaking types to this lint
#[allow(missing_debug_implementations)]
Expand Down Expand Up @@ -777,7 +777,7 @@ mod tests {
use std::time::Duration;

use super::{Connecting, Key, Pool, Poolable, Reservation, WeakOpt};
use crate::common::{task, Exec, Future, Pin};
use crate::common::{task, exec::Exec, Future, Pin};

/// Test unique reservations.
#[derive(Debug, PartialEq, Eq)]
Expand Down
6 changes: 4 additions & 2 deletions src/common/mod.rs
Expand Up @@ -16,16 +16,18 @@ pub(crate) mod drain;
pub(crate) mod exec;
pub(crate) mod io;
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
mod lazy;
mod never;
#[cfg(feature = "stream")]
pub(crate) mod sync_wrapper;
pub(crate) mod task;
pub(crate) mod watch;

//#[cfg(any(feature = "http1", feature = "http2"))]
//pub(crate) use self::exec::{BoxSendFuture, Exec};
#[cfg(any(feature = "http1", feature = "http2"))]
pub(crate) use self::exec::{BoxSendFuture, Exec};
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
pub(crate) use self::lazy::{lazy, Started as Lazy};
pub use self::never::Never;
pub(crate) use self::task::Poll;
Expand Down
10 changes: 10 additions & 0 deletions src/error.rs
Expand Up @@ -88,15 +88,18 @@ pub(crate) enum User {
UnexpectedHeader,
/// User tried to create a Request with bad version.
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
UnsupportedVersion,
/// User tried to create a CONNECT Request with the Client.
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
UnsupportedRequestMethod,
/// User tried to respond with a 1xx (not 101) response code.
#[cfg(feature = "http1")]
UnsupportedStatusCode,
/// User tried to send a Request with Client with non-absolute URI.
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
AbsoluteUriRequired,

/// User tried polling for an upgrade that doesn't exist.
Expand Down Expand Up @@ -241,6 +244,7 @@ impl Error {
}

#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
pub(crate) fn new_connect<E: Into<Cause>>(cause: E) -> Error {
Error::new(Kind::Connect).with(cause)
}
Expand Down Expand Up @@ -273,11 +277,13 @@ impl Error {
}

#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
pub(crate) fn new_user_unsupported_version() -> Error {
Error::new_user(User::UnsupportedVersion)
}

#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
pub(crate) fn new_user_unsupported_request_method() -> Error {
Error::new_user(User::UnsupportedRequestMethod)
}
Expand All @@ -288,6 +294,7 @@ impl Error {
}

#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
pub(crate) fn new_user_absolute_uri_required() -> Error {
Error::new_user(User::AbsoluteUriRequired)
}
Expand Down Expand Up @@ -371,14 +378,17 @@ impl Error {
#[cfg(feature = "http1")]
Kind::User(User::UnexpectedHeader) => "user sent unexpected header",
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
Kind::User(User::UnsupportedVersion) => "request has unsupported HTTP version",
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
Kind::User(User::UnsupportedRequestMethod) => "request has unsupported HTTP method",
#[cfg(feature = "http1")]
Kind::User(User::UnsupportedStatusCode) => {
"response has 1xx status code, not supported by server"
}
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
Kind::User(User::AbsoluteUriRequired) => "client requires absolute-form URIs",
Kind::User(User::NoUpgrade) => "no upgrade available",
#[cfg(feature = "http1")]
Expand Down
4 changes: 3 additions & 1 deletion src/headers.rs
Expand Up @@ -3,7 +3,8 @@ use bytes::BytesMut;
use http::header::CONTENT_LENGTH;
use http::header::{HeaderValue, ValueIter};
#[cfg(feature = "http2")]
use http::method::Method;
#[cfg(feature = "client")]
use http::Method;
use http::HeaderMap;

#[cfg(feature = "http1")]
Expand Down Expand Up @@ -65,6 +66,7 @@ pub fn content_length_parse_all_values(values: ValueIter<'_, HeaderValue>) -> Op
}

#[cfg(feature = "http2")]
#[cfg(feature = "client")]
pub fn method_has_defined_payload_semantics(method: &Method) -> bool {
match *method {
Method::GET | Method::HEAD | Method::DELETE | Method::CONNECT => false,
Expand Down
9 changes: 7 additions & 2 deletions src/lib.rs
Expand Up @@ -71,9 +71,14 @@ pub mod upgrade;
cfg_any_http! {
mod headers;
mod proto;
pub mod client;
pub mod server;

pub use crate::client::Client;
pub use crate::server::Server;
}

cfg_feature! {
#![all(feature = "client", any(feature = "http1", feature = "http2"))]

pub mod client;
pub use crate::client::Client;
}
4 changes: 3 additions & 1 deletion src/proto/h1/conn.rs
@@ -1,5 +1,5 @@
use std::fmt;
use std::io::{self};
use std::io;
use std::marker::PhantomData;

use bytes::{Buf, Bytes};
Expand Down Expand Up @@ -65,6 +65,7 @@ where
self.io.set_max_buf_size(max);
}

#[cfg(feature = "client")]
pub fn set_read_buf_exact_size(&mut self, sz: usize) {
self.io.set_read_buf_exact_size(sz);
}
Expand All @@ -77,6 +78,7 @@ where
self.io.set_write_strategy_queue();
}

#[cfg(feature = "client")]
pub fn set_title_case_headers(&mut self) {
self.state.title_case_headers = true;
}
Expand Down

0 comments on commit 4e55583

Please sign in to comment.