diff --git a/src/server/conn.rs b/src/server/conn.rs index 1e6cb469..3f9eaf9e 100644 --- a/src/server/conn.rs +++ b/src/server/conn.rs @@ -48,6 +48,7 @@ not(all(feature = "http1", feature = "http2")) ))] use std::marker::PhantomData; +#[cfg(all(any(feature = "http1", feature = "http2"), feature = "runtime"))] use std::time::Duration; #[cfg(feature = "http2")] diff --git a/src/server/mod.rs b/src/server/mod.rs index d658f421..b5508aef 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -149,7 +149,6 @@ pub mod accept; pub mod conn; -pub(crate) mod server; #[cfg(feature = "tcp")] mod tcp; @@ -158,7 +157,15 @@ pub use self::server::Server; cfg_feature! { #![any(feature = "http1", feature = "http2")] + pub(crate) mod server; pub use self::server::Builder; mod shutdown; } + +cfg_feature! { + #![not(any(feature = "http1", feature = "http2"))] + + mod server_stub; + use server_stub as server; +} diff --git a/src/server/server.rs b/src/server/server.rs index f2fb8bd8..e3058da4 100644 --- a/src/server/server.rs +++ b/src/server/server.rs @@ -1,36 +1,29 @@ +use std::error::Error as StdError; use std::fmt; #[cfg(feature = "tcp")] use std::net::{SocketAddr, TcpListener as StdTcpListener}; #[cfg(any(feature = "tcp", feature = "http1"))] use std::time::Duration; -#[cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))] +use pin_project_lite::pin_project; +use tokio::io::{AsyncRead, AsyncWrite}; +use tracing::trace; + +use super::accept::Accept; +#[cfg(all(feature = "tcp"))] use super::tcp::AddrIncoming; +use crate::body::{Body, HttpBody}; use crate::common::exec::Exec; +use crate::common::exec::{ConnStreamExec, NewSvcExec}; +use crate::common::{task, Future, Pin, Poll, Unpin}; +// Renamed `Http` as `Http_` for now so that people upgrading don't see an +// error that `hyper::server::Http` is private... +use super::conn::{Connection, Http as Http_, UpgradeableConnection}; +use super::shutdown::{Graceful, GracefulWatcher}; +use crate::service::{HttpService, MakeServiceRef}; -cfg_feature! { - #![any(feature = "http1", feature = "http2")] +use self::new_svc::NewSvcTask; - use std::error::Error as StdError; - - 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}; - 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::{Connection, Http as Http_, UpgradeableConnection}; - use super::shutdown::{Graceful, GracefulWatcher}; - use crate::service::{HttpService, MakeServiceRef}; - - use self::new_svc::NewSvcTask; -} - -#[cfg(any(feature = "http1", feature = "http2"))] pin_project! { /// A listening HTTP server that accepts connections in both HTTP1 and HTTP2 by default. /// @@ -46,17 +39,8 @@ 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, @@ -65,7 +49,6 @@ 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. @@ -77,47 +60,48 @@ impl Server { } } -cfg_feature! { - #![all(feature = "tcp", any(feature = "http1", feature = "http2"))] +#[cfg(feature = "tcp")] +#[cfg_attr( + docsrs, + doc(cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))) +)] +impl Server { + /// Binds to the provided address, and returns a [`Builder`](Builder). + /// + /// # Panics + /// + /// This method will panic if binding to the address fails. For a method + /// to bind to an address and return a `Result`, see `Server::try_bind`. + pub fn bind(addr: &SocketAddr) -> Builder { + let incoming = AddrIncoming::new(addr).unwrap_or_else(|e| { + panic!("error binding to {}: {}", addr, e); + }); + Server::builder(incoming) + } - impl Server { - /// Binds to the provided address, and returns a [`Builder`](Builder). - /// - /// # Panics - /// - /// This method will panic if binding to the address fails. For a method - /// to bind to an address and return a `Result`, see `Server::try_bind`. - pub fn bind(addr: &SocketAddr) -> Builder { - let incoming = AddrIncoming::new(addr).unwrap_or_else(|e| { - panic!("error binding to {}: {}", addr, e); - }); - Server::builder(incoming) - } + /// Tries to bind to the provided address, and returns a [`Builder`](Builder). + pub fn try_bind(addr: &SocketAddr) -> crate::Result> { + AddrIncoming::new(addr).map(Server::builder) + } - /// Tries to bind to the provided address, and returns a [`Builder`](Builder). - pub fn try_bind(addr: &SocketAddr) -> crate::Result> { - AddrIncoming::new(addr).map(Server::builder) - } - - /// Create a new instance from a `std::net::TcpListener` instance. - pub fn from_tcp(listener: StdTcpListener) -> Result, crate::Error> { - AddrIncoming::from_std(listener).map(Server::builder) - } + /// Create a new instance from a `std::net::TcpListener` instance. + pub fn from_tcp(listener: StdTcpListener) -> Result, crate::Error> { + AddrIncoming::from_std(listener).map(Server::builder) } } -cfg_feature! { - #![all(feature = "tcp", any(feature = "http1", feature = "http2"))] - - impl Server { - /// Returns the local address that this server is bound to. - pub fn local_addr(&self) -> SocketAddr { - self.incoming.local_addr() - } +#[cfg(feature = "tcp")] +#[cfg_attr( + docsrs, + doc(cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))) +)] +impl Server { + /// Returns the local address that this server is bound to. + pub fn local_addr(&self) -> SocketAddr { + self.incoming.local_addr() } } -#[cfg(any(feature = "http1", feature = "http2"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] impl Server where @@ -220,7 +204,6 @@ where } } -#[cfg(any(feature = "http1", feature = "http2"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] impl Future for Server where @@ -244,7 +227,6 @@ where impl fmt::Debug for Server { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut st = f.debug_struct("Server"); - #[cfg(any(feature = "http1", feature = "http2"))] st.field("listener", &self.incoming); st.finish() } @@ -252,7 +234,6 @@ impl fmt::Debug for Server { // ===== 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. @@ -572,7 +553,11 @@ impl Builder { } } -#[cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))] +#[cfg(feature = "tcp")] +#[cfg_attr( + docsrs, + doc(cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))) +)] impl Builder { /// Set whether TCP keepalive messages are enabled on accepted connections. /// @@ -619,7 +604,6 @@ impl Builder { // The `Server::with_graceful_shutdown` needs to keep track of all active // connections, and signal that they start to shutdown when prompted, so // it has a `GracefulWatcher` implementation to do that. -#[cfg(any(feature = "http1", feature = "http2"))] pub trait Watcher, E>: Clone { type Future: Future>; @@ -628,10 +612,8 @@ pub trait Watcher, E>: Clone { #[allow(missing_debug_implementations)] #[derive(Copy, Clone)] -#[cfg(any(feature = "http1", feature = "http2"))] pub struct NoopWatcher; -#[cfg(any(feature = "http1", feature = "http2"))] impl Watcher for NoopWatcher where I: AsyncRead + AsyncWrite + Unpin + Send + 'static, @@ -647,7 +629,6 @@ where } } -#[cfg(any(feature = "http1", feature = "http2"))] // used by exec.rs pub(crate) mod new_svc { use std::error::Error as StdError; @@ -759,7 +740,6 @@ pub(crate) mod new_svc { } } -#[cfg(any(feature = "http1", feature = "http2"))] pin_project! { /// A future building a new `Service` to a `Connection`. /// @@ -776,7 +756,6 @@ pin_project! { } } -#[cfg(any(feature = "http1", feature = "http2"))] impl Future for Connecting where I: AsyncRead + AsyncWrite + Unpin, diff --git a/src/server/server_stub.rs b/src/server/server_stub.rs new file mode 100644 index 00000000..87b1f513 --- /dev/null +++ b/src/server/server_stub.rs @@ -0,0 +1,16 @@ +use std::fmt; + +use crate::common::exec::Exec; + +/// 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. +pub struct Server { + _marker: std::marker::PhantomData<(I, S, E)>, +} + +impl fmt::Debug for Server { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Server").finish() + } +}