Skip to content

Commit

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

BREAKING CHANGE: The HTTP server code is now an optional feature. To
  enable the server, add `features = ["server"]` to the dependency in
  your `Cargo.toml`.
  • Loading branch information
seanmonstar committed Nov 18, 2020
1 parent 4e55583 commit bdb5e5d
Show file tree
Hide file tree
Showing 18 changed files with 182 additions and 99 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Expand Up @@ -75,13 +75,15 @@ default = [
"runtime",
"stream",
"client",
"server",
"http1",
"http2",
]
full = [
"client",
"http1",
"http2",
"server",
"stream",
"runtime",
]
Expand All @@ -100,7 +102,9 @@ tcp = [
http1 = []
http2 = ["h2"]

# Client/Server
client = []
server = []

# `impl Stream` for things
stream = []
Expand Down
14 changes: 7 additions & 7 deletions src/body/body.rs
Expand Up @@ -21,7 +21,7 @@ use crate::common::{task, watch, Pin, Poll};
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
use crate::common::{Future, Never};
#[cfg(feature = "http2")]
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
use crate::proto::h2::ping;
use crate::upgrade::OnUpgrade;

Expand All @@ -46,7 +46,7 @@ enum Kind {
want_tx: watch::Sender,
rx: mpsc::Receiver<Result<Bytes, crate::Error>>,
},
#[cfg(feature = "http2")]
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
H2 {
ping: ping::Recorder,
content_length: DecodedLength,
Expand Down Expand Up @@ -200,7 +200,7 @@ impl Body {
Body { kind, extra: None }
}

#[cfg(feature = "http2")]
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
pub(crate) fn h2(
recv: h2::RecvStream,
content_length: DecodedLength,
Expand Down Expand Up @@ -301,7 +301,7 @@ impl Body {
None => Poll::Ready(None),
}
}
#[cfg(feature = "http2")]
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
Kind::H2 {
ref ping,
recv: ref mut h2,
Expand Down Expand Up @@ -359,7 +359,7 @@ impl HttpBody for Body {
#[cfg_attr(not(feature = "http2"), allow(unused))] cx: &mut task::Context<'_>,
) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
match self.kind {
#[cfg(feature = "http2")]
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
Kind::H2 {
recv: ref mut h2,
ref ping,
Expand All @@ -379,7 +379,7 @@ impl HttpBody for Body {
match self.kind {
Kind::Once(ref val) => val.is_none(),
Kind::Chan { content_length, .. } => content_length == DecodedLength::ZERO,
#[cfg(feature = "http2")]
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
Kind::H2 { recv: ref h2, .. } => h2.is_end_stream(),
#[cfg(feature = "stream")]
Kind::Wrapped(..) => false,
Expand All @@ -405,7 +405,7 @@ impl HttpBody for Body {
#[cfg(feature = "stream")]
Kind::Wrapped(..) => SizeHint::default(),
Kind::Chan { content_length, .. } => opt_len!(content_length),
#[cfg(feature = "http2")]
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
Kind::H2 { content_length, .. } => opt_len!(content_length),
}
}
Expand Down
18 changes: 15 additions & 3 deletions src/cfg.rs
Expand Up @@ -11,16 +11,19 @@ macro_rules! cfg_feature {
}
}

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

cfg_any_http! {
cfg_proto! {
macro_rules! cfg_http1 {
($($item:item)*) => {
cfg_feature! {
Expand All @@ -47,4 +50,13 @@ cfg_any_http! {
}
}
}

macro_rules! cfg_server {
($($item:item)*) => {
cfg_feature! {
#![feature = "server"]
$($item)*
}
}
}
}
12 changes: 11 additions & 1 deletion src/common/exec.rs
Expand Up @@ -3,17 +3,23 @@ use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;

#[cfg(feature = "server")]
use crate::body::{Body, HttpBody};
#[cfg(feature = "http2")]
#[cfg(feature = "server")]
use crate::proto::h2::server::H2Stream;
use crate::rt::Executor;
#[cfg(feature = "server")]
use crate::server::conn::spawn_all::{NewSvcTask, Watcher};
#[cfg(feature = "server")]
use crate::service::HttpService;

#[cfg(feature = "server")]
pub trait ConnStreamExec<F, B: HttpBody>: Clone {
fn execute_h2stream(&mut self, fut: H2Stream<F, B>);
}

#[cfg(feature = "server")]
pub trait NewSvcExec<I, N, S: HttpService<Body>, E, W: Watcher<I, S, E>>: Clone {
fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>);
}
Expand Down Expand Up @@ -60,6 +66,7 @@ impl fmt::Debug for Exec {
}
}

#[cfg(feature = "server")]
impl<F, B> ConnStreamExec<F, B> for Exec
where
H2Stream<F, B>: Future<Output = ()> + Send + 'static,
Expand All @@ -70,6 +77,7 @@ where
}
}

#[cfg(feature = "server")]
impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for Exec
where
NewSvcTask<I, N, S, E, W>: Future<Output = ()> + Send + 'static,
Expand All @@ -83,6 +91,7 @@ where

// ==== impl Executor =====

#[cfg(feature = "server")]
impl<E, F, B> ConnStreamExec<F, B> for E
where
E: Executor<H2Stream<F, B>> + Clone,
Expand All @@ -94,6 +103,7 @@ where
}
}

#[cfg(feature = "server")]
impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for E
where
E: Executor<NewSvcTask<I, N, S, E, W>> + Clone,
Expand All @@ -119,7 +129,7 @@ pub struct H2Stream<F, B>(std::marker::PhantomData<(F, B)>);
impl<F, B, E> Future for H2Stream<F, B>
where
F: Future<Output = Result<http::Response<B>, E>>,
B: HttpBody,
B: crate::body::HttpBody,
B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
Expand Down
3 changes: 2 additions & 1 deletion src/common/io/rewind.rs
Expand Up @@ -15,6 +15,7 @@ pub(crate) struct Rewind<T> {

impl<T> Rewind<T> {
#[cfg(any(feature = "http2", test))]
#[cfg(feature = "server")]
pub(crate) fn new(io: T) -> Self {
Rewind {
pre: None,
Expand All @@ -29,7 +30,7 @@ impl<T> Rewind<T> {
}
}

#[cfg(any(all(feature = "http1", feature = "http2"), test))]
#[cfg(any(all(feature = "http1", feature = "http2", feature = "server"), test))]
pub(crate) fn rewind(&mut self, bs: Bytes) {
debug_assert!(self.pre.is_none());
self.pre = Some(bs);
Expand Down
9 changes: 5 additions & 4 deletions src/common/mod.rs
Expand Up @@ -9,8 +9,10 @@ macro_rules! ready {

pub(crate) mod buf;
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "server")]
pub(crate) mod date;
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "server")]
pub(crate) mod drain;
#[cfg(any(feature = "http1", feature = "http2"))]
pub(crate) mod exec;
Expand All @@ -24,15 +26,14 @@ 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"))]
#[cfg(feature = "client")]
pub(crate) use self::lazy::{lazy, Started as Lazy};
pub use self::never::Never;
pub(crate) use self::task::Poll;

// group up types normally needed for `Future`
#[cfg(any(feature = "http1", feature = "http2"))]
pub(crate) use std::marker::Unpin;
cfg_proto! {
pub(crate) use std::marker::Unpin;
}
pub(crate) use std::{future::Future, pin::Pin};
21 changes: 20 additions & 1 deletion src/error.rs
Expand Up @@ -36,10 +36,15 @@ pub(crate) enum Kind {
/// Error occurred while connecting.
Connect,
/// Error creating a TcpListener.
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))]
#[cfg(all(
any(feature = "http1", feature = "http2"),
feature = "tcp",
feature = "server"
))]
Listen,
/// Error accepting on an Incoming stream.
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "server")]
Accept,
/// Error while reading a body from connection.
#[cfg(any(feature = "http1", feature = "http2", feature = "stream"))]
Expand Down Expand Up @@ -77,6 +82,7 @@ pub(crate) enum User {
Body,
/// Error calling user's MakeService.
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "server")]
MakeService,
/// Error from future of user's Service.
#[cfg(any(feature = "http1", feature = "http2"))]
Expand All @@ -85,6 +91,7 @@ pub(crate) enum User {
///
/// For example, sending both `content-length` and `transfer-encoding`.
#[cfg(feature = "http1")]
#[cfg(feature = "server")]
UnexpectedHeader,
/// User tried to create a Request with bad version.
#[cfg(any(feature = "http1", feature = "http2"))]
Expand All @@ -96,6 +103,7 @@ pub(crate) enum User {
UnsupportedRequestMethod,
/// User tried to respond with a 1xx (not 101) response code.
#[cfg(feature = "http1")]
#[cfg(feature = "server")]
UnsupportedStatusCode,
/// User tried to send a Request with Client with non-absolute URI.
#[cfg(any(feature = "http1", feature = "http2"))]
Expand Down Expand Up @@ -178,6 +186,7 @@ impl Error {
}

#[cfg(feature = "http1")]
#[cfg(feature = "server")]
pub(crate) fn kind(&self) -> &Kind {
&self.inner.kind
}
Expand Down Expand Up @@ -234,11 +243,13 @@ impl Error {
}

#[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))]
#[cfg(feature = "server")]
pub(crate) fn new_listen<E: Into<Cause>>(cause: E) -> Error {
Error::new(Kind::Listen).with(cause)
}

#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "server")]
pub(crate) fn new_accept<E: Into<Cause>>(cause: E) -> Error {
Error::new(Kind::Accept).with(cause)
}
Expand Down Expand Up @@ -272,6 +283,7 @@ impl Error {
}

#[cfg(feature = "http1")]
#[cfg(feature = "server")]
pub(crate) fn new_user_header() -> Error {
Error::new_user(User::UnexpectedHeader)
}
Expand All @@ -289,6 +301,7 @@ impl Error {
}

#[cfg(feature = "http1")]
#[cfg(feature = "server")]
pub(crate) fn new_user_unsupported_status_code() -> Error {
Error::new_user(User::UnsupportedStatusCode)
}
Expand All @@ -309,6 +322,7 @@ impl Error {
}

#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "server")]
pub(crate) fn new_user_make_service<E: Into<Cause>>(cause: E) -> Error {
Error::new_user(User::MakeService).with(cause)
}
Expand Down Expand Up @@ -354,8 +368,10 @@ impl Error {
Kind::Connect => "error trying to connect",
Kind::Canceled => "operation was canceled",
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))]
#[cfg(feature = "server")]
Kind::Listen => "error creating server listener",
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "server")]
Kind::Accept => "error accepting connection",
#[cfg(any(feature = "http1", feature = "http2", feature = "stream"))]
Kind::Body => "error reading a body from connection",
Expand All @@ -372,10 +388,12 @@ impl Error {
#[cfg(any(feature = "http1", feature = "http2"))]
Kind::User(User::Body) => "error from user's HttpBody stream",
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "server")]
Kind::User(User::MakeService) => "error from user's MakeService",
#[cfg(any(feature = "http1", feature = "http2"))]
Kind::User(User::Service) => "error from user's Service",
#[cfg(feature = "http1")]
#[cfg(feature = "server")]
Kind::User(User::UnexpectedHeader) => "user sent unexpected header",
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg(feature = "client")]
Expand All @@ -384,6 +402,7 @@ impl Error {
#[cfg(feature = "client")]
Kind::User(User::UnsupportedRequestMethod) => "request has unsupported HTTP method",
#[cfg(feature = "http1")]
#[cfg(feature = "server")]
Kind::User(User::UnsupportedStatusCode) => {
"response has 1xx status code, not supported by server"
}
Expand Down
1 change: 1 addition & 0 deletions src/headers.rs
Expand Up @@ -30,6 +30,7 @@ fn connection_has(value: &HeaderValue, needle: &str) -> bool {
}

#[cfg(feature = "http1")]
#[cfg(feature = "server")]
pub fn content_length_parse(value: &HeaderValue) -> Option<u64> {
value.to_str().ok().and_then(|s| s.parse().ok())
}
Expand Down
12 changes: 8 additions & 4 deletions src/lib.rs
Expand Up @@ -68,12 +68,9 @@ pub mod rt;
pub mod service;
pub mod upgrade;

cfg_any_http! {
cfg_proto! {
mod headers;
mod proto;
pub mod server;

pub use crate::server::Server;
}

cfg_feature! {
Expand All @@ -82,3 +79,10 @@ cfg_feature! {
pub mod client;
pub use crate::client::Client;
}

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

pub mod server;
pub use crate::server::Server;
}

0 comments on commit bdb5e5d

Please sign in to comment.