diff --git a/src/common/exec.rs b/src/common/exec.rs index f7560efb..b6da9a27 100644 --- a/src/common/exec.rs +++ b/src/common/exec.rs @@ -3,14 +3,16 @@ use std::future::Future; use std::pin::Pin; use std::sync::Arc; +#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))] +use crate::body::Body; #[cfg(feature = "server")] -use crate::body::{Body, HttpBody}; +use crate::body::HttpBody; #[cfg(all(feature = "http2", feature = "server"))] use crate::proto::h2::server::H2Stream; use crate::rt::Executor; -#[cfg(feature = "server")] +#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))] use crate::server::conn::spawn_all::{NewSvcTask, Watcher}; -#[cfg(feature = "server")] +#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))] use crate::service::HttpService; #[cfg(feature = "server")] @@ -18,7 +20,7 @@ pub trait ConnStreamExec: Clone { fn execute_h2stream(&mut self, fut: H2Stream); } -#[cfg(feature = "server")] +#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))] pub trait NewSvcExec, E, W: Watcher>: Clone { fn execute_new_svc(&mut self, fut: NewSvcTask); } @@ -76,7 +78,7 @@ where } } -#[cfg(feature = "server")] +#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))] impl NewSvcExec for Exec where NewSvcTask: Future + Send + 'static, @@ -102,7 +104,7 @@ where } } -#[cfg(feature = "server")] +#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))] impl NewSvcExec for E where E: Executor> + Clone, diff --git a/src/common/mod.rs b/src/common/mod.rs index c017154a..b9f5907a 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -12,7 +12,7 @@ pub(crate) mod buf; pub(crate) mod date; #[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))] pub(crate) mod drain; -#[cfg(any(feature = "http1", feature = "http2"))] +#[cfg(any(feature = "http1", feature = "http2", feature = "server"))] pub(crate) mod exec; pub(crate) mod io; #[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))] diff --git a/src/error.rs b/src/error.rs index bd798667..5d350278 100644 --- a/src/error.rs +++ b/src/error.rs @@ -38,11 +38,7 @@ pub(super) enum Kind { #[allow(unused)] Connect, /// Error creating a TcpListener. - #[cfg(all( - any(feature = "http1", feature = "http2"), - feature = "tcp", - feature = "server" - ))] + #[cfg(all(feature = "tcp", feature = "server"))] Listen, /// Error accepting on an Incoming stream. #[cfg(any(feature = "http1", feature = "http2"))] @@ -265,8 +261,7 @@ impl Error { Error::new(Kind::Io).with(cause) } - #[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))] - #[cfg(feature = "server")] + #[cfg(all(feature = "server", feature = "tcp"))] pub(super) fn new_listen>(cause: E) -> Error { Error::new(Kind::Listen).with(cause) } @@ -410,8 +405,7 @@ impl Error { Kind::ChannelClosed => "channel closed", Kind::Connect => "error trying to connect", Kind::Canceled => "operation was canceled", - #[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))] - #[cfg(feature = "server")] + #[cfg(all(feature = "server", feature = "tcp"))] Kind::Listen => "error creating server listener", #[cfg(any(feature = "http1", feature = "http2"))] #[cfg(feature = "server")] diff --git a/src/lib.rs b/src/lib.rs index eaf6a143..41a0b375 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,7 +104,6 @@ cfg_feature! { #![feature = "server"] pub mod server; - #[cfg(any(feature = "http1", feature = "http2"))] #[doc(no_inline)] pub use crate::server::Server; } diff --git a/src/server/conn.rs b/src/server/conn.rs index 5783bb24..58720332 100644 --- a/src/server/conn.rs +++ b/src/server/conn.rs @@ -43,38 +43,47 @@ //! # } //! ``` -use std::error::Error as StdError; -use std::fmt; -#[cfg(not(all(feature = "http1", feature = "http2")))] +#[cfg(all( + any(feature = "http1", feature = "http2"), + not(all(feature = "http1", feature = "http2")) +))] use std::marker::PhantomData; #[cfg(feature = "tcp")] use std::net::SocketAddr; #[cfg(all(feature = "runtime", feature = "http2"))] use std::time::Duration; -use bytes::Bytes; -use pin_project_lite::pin_project; -use tokio::io::{AsyncRead, AsyncWrite}; -use tracing::trace; - -use super::accept::Accept; -use crate::body::{Body, HttpBody}; -use crate::common::exec::{ConnStreamExec, Exec, NewSvcExec}; #[cfg(feature = "http2")] use crate::common::io::Rewind; -#[cfg(not(all(feature = "http1", feature = "http2")))] -use crate::common::Never; -use crate::common::{task, Future, Pin, Poll, Unpin}; #[cfg(all(feature = "http1", feature = "http2"))] use crate::error::{Kind, Parse}; -use crate::proto; -use crate::service::{HttpService, MakeServiceRef}; #[cfg(feature = "http1")] use crate::upgrade::Upgraded; -use self::spawn_all::NewSvcTask; -pub(super) use self::spawn_all::{NoopWatcher, Watcher}; -pub(super) use self::upgrades::UpgradeableConnection; +cfg_feature! { + #![any(feature = "http1", feature = "http2")] + + use std::error::Error as StdError; + use std::fmt; + + use bytes::Bytes; + use pin_project_lite::pin_project; + use tokio::io::{AsyncRead, AsyncWrite}; + use tracing::trace; + + use super::accept::Accept; + use crate::body::{Body, HttpBody}; + use crate::common::{task, Future, Pin, Poll, Unpin}; + #[cfg(not(all(feature = "http1", feature = "http2")))] + use crate::common::Never; + use crate::common::exec::{ConnStreamExec, Exec, NewSvcExec}; + use crate::proto; + use crate::service::{HttpService, MakeServiceRef}; + use self::spawn_all::NewSvcTask; + + pub(super) use self::spawn_all::{NoopWatcher, Watcher}; + pub(super) use self::upgrades::UpgradeableConnection; +} #[cfg(feature = "tcp")] pub use super::tcp::{AddrIncoming, AddrStream}; @@ -86,6 +95,8 @@ pub use super::tcp::{AddrIncoming, AddrStream}; /// If you don't have need to manage connections yourself, consider using the /// higher-level [Server](super) API. #[derive(Clone, Debug)] +#[cfg(any(feature = "http1", feature = "http2"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] pub struct Http { exec: E, h1_half_close: bool, @@ -100,6 +111,7 @@ pub struct Http { } /// The internal mode of HTTP protocol which indicates the behavior when a parse error occurs. +#[cfg(any(feature = "http1", feature = "http2"))] #[derive(Clone, Debug, PartialEq)] enum ConnectionMode { /// Always use HTTP/1 and do not upgrade when a parse error occurs. @@ -113,6 +125,7 @@ enum ConnectionMode { Fallback, } +#[cfg(any(feature = "http1", feature = "http2"))] pin_project! { /// A stream mapping incoming IOs to new services. /// @@ -127,6 +140,7 @@ pin_project! { } } +#[cfg(any(feature = "http1", feature = "http2"))] pin_project! { /// A future building a new `Service` to a `Connection`. /// @@ -134,6 +148,7 @@ pin_project! { /// a `Connection`. #[must_use = "futures do nothing unless polled"] #[derive(Debug)] + #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] pub struct Connecting { #[pin] future: F, @@ -142,6 +157,7 @@ pin_project! { } } +#[cfg(any(feature = "http1", feature = "http2"))] pin_project! { #[must_use = "futures do nothing unless polled"] #[derive(Debug)] @@ -154,11 +170,13 @@ pin_project! { } } +#[cfg(any(feature = "http1", feature = "http2"))] pin_project! { /// A future binding a connection with a Service. /// /// Polling this future will drive HTTP forward. #[must_use = "futures do nothing unless polled"] + #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] pub struct Connection where S: HttpService, @@ -172,18 +190,19 @@ pin_project! { type Http1Dispatcher = proto::h1::Dispatcher, B, T, proto::ServerTransaction>; -#[cfg(not(feature = "http1"))] +#[cfg(all(not(feature = "http1"), feature = "http2"))] type Http1Dispatcher = (Never, PhantomData<(T, Box>, Box>)>); #[cfg(feature = "http2")] type Http2Server = proto::h2::Server, S, B, E>; -#[cfg(not(feature = "http2"))] +#[cfg(all(not(feature = "http2"), feature = "http1"))] type Http2Server = ( Never, PhantomData<(T, Box>, Box>, Box>)>, ); +#[cfg(any(feature = "http1", feature = "http2"))] pin_project! { #[project = ProtoServerProj] pub(super) enum ProtoServer @@ -209,7 +228,10 @@ enum Fallback { Http1Only, } -#[cfg(not(all(feature = "http1", feature = "http2")))] +#[cfg(all( + any(feature = "http1", feature = "http2"), + not(all(feature = "http1", feature = "http2")) +))] type Fallback = PhantomData; #[cfg(all(feature = "http1", feature = "http2"))] @@ -230,6 +252,8 @@ impl Unpin for Fallback {} /// This allows taking apart a `Connection` at a later time, in order to /// reclaim the IO object, and additional related pieces. #[derive(Debug)] +#[cfg(any(feature = "http1", feature = "http2"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] pub struct Parts { /// The original IO object used in the handshake. pub io: T, @@ -249,6 +273,7 @@ pub struct Parts { // ===== impl Http ===== +#[cfg(any(feature = "http1", feature = "http2"))] impl Http { /// Creates a new instance of the HTTP protocol, ready to spawn a server or /// start accepting connections. @@ -268,6 +293,7 @@ impl Http { } } +#[cfg(any(feature = "http1", feature = "http2"))] impl Http { /// Sets whether HTTP1 is required. /// @@ -633,6 +659,7 @@ impl Http { // ===== impl Connection ===== +#[cfg(any(feature = "http1", feature = "http2"))] impl Connection where S: HttpService, @@ -802,6 +829,7 @@ where } } +#[cfg(any(feature = "http1", feature = "http2"))] impl Future for Connection where S: HttpService, @@ -848,6 +876,7 @@ where } } +#[cfg(any(feature = "http1", feature = "http2"))] impl fmt::Debug for Connection where S: HttpService, @@ -859,6 +888,7 @@ where // ===== impl ConnectionMode ===== +#[cfg(any(feature = "http1", feature = "http2"))] impl Default for ConnectionMode { #[cfg(all(feature = "http1", feature = "http2"))] fn default() -> ConnectionMode { @@ -878,6 +908,7 @@ impl Default for ConnectionMode { // ===== impl Serve ===== +#[cfg(any(feature = "http1", feature = "http2"))] impl Serve { /// Get a reference to the incoming stream. #[inline] @@ -899,6 +930,7 @@ impl Serve { } } +#[cfg(any(feature = "http1", feature = "http2"))] impl Serve where I: Accept, @@ -937,6 +969,7 @@ where // ===== impl Connecting ===== +#[cfg(any(feature = "http1", feature = "http2"))] impl Future for Connecting where I: AsyncRead + AsyncWrite + Unpin, @@ -958,19 +991,21 @@ where // ===== impl SpawnAll ===== -#[cfg(feature = "tcp")] +#[cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))] impl SpawnAll { pub(super) fn local_addr(&self) -> SocketAddr { self.serve.incoming.local_addr() } } +#[cfg(any(feature = "http1", feature = "http2"))] impl SpawnAll { pub(super) fn incoming_ref(&self) -> &I { self.serve.incoming_ref() } } +#[cfg(any(feature = "http1", feature = "http2"))] impl SpawnAll where I: Accept, @@ -1008,6 +1043,7 @@ where // ===== impl ProtoServer ===== +#[cfg(any(feature = "http1", feature = "http2"))] impl Future for ProtoServer where T: AsyncRead + AsyncWrite + Unpin, @@ -1034,6 +1070,7 @@ where } } +#[cfg(any(feature = "http1", feature = "http2"))] pub(crate) mod spawn_all { use std::error::Error as StdError; use tokio::io::{AsyncRead, AsyncWrite}; @@ -1177,6 +1214,7 @@ pub(crate) mod spawn_all { } } +#[cfg(any(feature = "http1", feature = "http2"))] mod upgrades { use super::*; diff --git a/src/server/mod.rs b/src/server/mod.rs index 6f691f61..a97944f5 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -148,15 +148,17 @@ //! [`tower::make::Shared`]: https://docs.rs/tower/latest/tower/make/struct.Shared.html pub mod accept; +pub mod conn; +mod server; +#[cfg(feature = "tcp")] +mod tcp; + +pub use self::server::Server; cfg_feature! { #![any(feature = "http1", feature = "http2")] - pub use self::server::{Builder, Server}; + pub use self::server::Builder; - pub mod conn; - mod server; mod shutdown; - #[cfg(feature = "tcp")] - mod tcp; } diff --git a/src/server/server.rs b/src/server/server.rs index 810ac712..377f7cb6 100644 --- a/src/server/server.rs +++ b/src/server/server.rs @@ -1,26 +1,33 @@ -use std::error::Error as StdError; use std::fmt; #[cfg(feature = "tcp")] use std::net::{SocketAddr, TcpListener as StdTcpListener}; - #[cfg(feature = "tcp")] use std::time::Duration; -use pin_project_lite::pin_project; -use tokio::io::{AsyncRead, AsyncWrite}; - -use super::accept::Accept; -use crate::body::{Body, HttpBody}; -use crate::common::exec::{ConnStreamExec, Exec, NewSvcExec}; -use crate::common::{task, Future, Pin, Poll, Unpin}; -use crate::service::{HttpService, MakeServiceRef}; -// Renamed `Http` as `Http_` for now so that people upgrading don't see an -// error that `hyper::server::Http` is private... -use super::conn::{Http as Http_, NoopWatcher, SpawnAll}; -use super::shutdown::{Graceful, GracefulWatcher}; -#[cfg(feature = "tcp")] +#[cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))] use super::tcp::AddrIncoming; +use crate::common::exec::Exec; +cfg_feature! { + #![any(feature = "http1", feature = "http2")] + + use std::error::Error as StdError; + + use pin_project_lite::pin_project; + use tokio::io::{AsyncRead, AsyncWrite}; + + use super::accept::Accept; + use crate::body::{Body, HttpBody}; + use crate::common::{task, Future, Pin, Poll, Unpin}; + use crate::common::exec::{ConnStreamExec, NewSvcExec}; + // Renamed `Http` as `Http_` for now so that people upgrading don't see an + // error that `hyper::server::Http` is private... + use super::conn::{Http as Http_, NoopWatcher, SpawnAll}; + use super::shutdown::{Graceful, GracefulWatcher}; + use crate::service::{HttpService, MakeServiceRef}; +} + +#[cfg(any(feature = "http1", feature = "http2"))] pin_project! { /// A listening HTTP server that accepts connections in both HTTP1 and HTTP2 by default. /// @@ -34,8 +41,18 @@ pin_project! { } } +/// A listening HTTP server that accepts connections in both HTTP1 and HTTP2 by default. +/// +/// Needs at least one of the `http1` and `http2` features to be activated to actually be useful. +#[cfg(not(any(feature = "http1", feature = "http2")))] +pub struct Server { + _marker: std::marker::PhantomData<(I, S, E)>, +} + /// A builder for a [`Server`](Server). #[derive(Debug)] +#[cfg(any(feature = "http1", feature = "http2"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] pub struct Builder { incoming: I, protocol: Http_, @@ -43,6 +60,8 @@ pub struct Builder { // ===== impl Server ===== +#[cfg(any(feature = "http1", feature = "http2"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] impl Server { /// Starts a [`Builder`](Builder) with the provided incoming stream. pub fn builder(incoming: I) -> Builder { @@ -54,7 +73,7 @@ impl Server { } cfg_feature! { - #![all(feature = "tcp")] + #![all(feature = "tcp", any(feature = "http1", feature = "http2"))] impl Server { /// Binds to the provided address, and returns a [`Builder`](Builder). @@ -83,7 +102,7 @@ cfg_feature! { } cfg_feature! { - #![all(feature = "tcp")] + #![all(feature = "tcp", any(feature = "http1", feature = "http2"))] impl Server { /// Returns the local address that this server is bound to. @@ -93,6 +112,8 @@ cfg_feature! { } } +#[cfg(any(feature = "http1", feature = "http2"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] impl Server where I: Accept, @@ -149,6 +170,8 @@ where } } +#[cfg(any(feature = "http1", feature = "http2"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] impl Future for Server where I: Accept, @@ -170,14 +193,17 @@ where impl fmt::Debug for Server { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Server") - .field("listener", &self.spawn_all.incoming_ref()) - .finish() + let mut st = f.debug_struct("Server"); + #[cfg(any(feature = "http1", feature = "http2"))] + st.field("listener", &self.spawn_all.incoming_ref()); + st.finish() } } // ===== impl Builder ===== +#[cfg(any(feature = "http1", feature = "http2"))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] impl Builder { /// Start a new builder, wrapping an incoming stream and low-level options. /// @@ -435,7 +461,7 @@ impl Builder { } } -#[cfg(feature = "tcp")] +#[cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))] impl Builder { /// Set whether TCP keepalive messages are enabled on accepted connections. ///