refactor(server): simplify server cfgs

`server.rs` is currently littered with `cfg`s for `http1` or `http2`,
since the majority of server behaviour is only available with either one
of those feature flags active. This is hard to maintain and confusing to
read, so this commit extracts the two implementations into their own
files, since there is very little benefit in sharing code between the
two.
This commit is contained in:
SabrinaJewson
2022-03-12 13:12:34 +00:00
committed by Sean McArthur
parent 0fec1c8737
commit dd08d9c3e5
4 changed files with 80 additions and 77 deletions

View File

@@ -48,6 +48,7 @@
not(all(feature = "http1", feature = "http2")) not(all(feature = "http1", feature = "http2"))
))] ))]
use std::marker::PhantomData; use std::marker::PhantomData;
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "runtime"))]
use std::time::Duration; use std::time::Duration;
#[cfg(feature = "http2")] #[cfg(feature = "http2")]

View File

@@ -149,7 +149,6 @@
pub mod accept; pub mod accept;
pub mod conn; pub mod conn;
pub(crate) mod server;
#[cfg(feature = "tcp")] #[cfg(feature = "tcp")]
mod tcp; mod tcp;
@@ -158,7 +157,15 @@ pub use self::server::Server;
cfg_feature! { cfg_feature! {
#![any(feature = "http1", feature = "http2")] #![any(feature = "http1", feature = "http2")]
pub(crate) mod server;
pub use self::server::Builder; pub use self::server::Builder;
mod shutdown; mod shutdown;
} }
cfg_feature! {
#![not(any(feature = "http1", feature = "http2"))]
mod server_stub;
use server_stub as server;
}

View File

@@ -1,36 +1,29 @@
use std::error::Error as StdError;
use std::fmt; use std::fmt;
#[cfg(feature = "tcp")] #[cfg(feature = "tcp")]
use std::net::{SocketAddr, TcpListener as StdTcpListener}; use std::net::{SocketAddr, TcpListener as StdTcpListener};
#[cfg(any(feature = "tcp", feature = "http1"))] #[cfg(any(feature = "tcp", feature = "http1"))]
use std::time::Duration; 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 super::tcp::AddrIncoming;
use crate::body::{Body, HttpBody};
use crate::common::exec::Exec; 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! { use self::new_svc::NewSvcTask;
#![any(feature = "http1", feature = "http2")]
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! { pin_project! {
/// A listening HTTP server that accepts connections in both HTTP1 and HTTP2 by default. /// 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<I, S, E = Exec> {
_marker: std::marker::PhantomData<(I, S, E)>,
}
/// A builder for a [`Server`](Server). /// A builder for a [`Server`](Server).
#[derive(Debug)] #[derive(Debug)]
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
pub struct Builder<I, E = Exec> { pub struct Builder<I, E = Exec> {
incoming: I, incoming: I,
@@ -65,7 +49,6 @@ pub struct Builder<I, E = Exec> {
// ===== impl Server ===== // ===== impl Server =====
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
impl<I> Server<I, ()> { impl<I> Server<I, ()> {
/// Starts a [`Builder`](Builder) with the provided incoming stream. /// Starts a [`Builder`](Builder) with the provided incoming stream.
@@ -77,10 +60,12 @@ impl<I> Server<I, ()> {
} }
} }
cfg_feature! { #[cfg(feature = "tcp")]
#![all(feature = "tcp", any(feature = "http1", feature = "http2"))] #[cfg_attr(
docsrs,
impl Server<AddrIncoming, ()> { doc(cfg(all(feature = "tcp", any(feature = "http1", feature = "http2"))))
)]
impl Server<AddrIncoming, ()> {
/// Binds to the provided address, and returns a [`Builder`](Builder). /// Binds to the provided address, and returns a [`Builder`](Builder).
/// ///
/// # Panics /// # Panics
@@ -103,21 +88,20 @@ cfg_feature! {
pub fn from_tcp(listener: StdTcpListener) -> Result<Builder<AddrIncoming>, crate::Error> { pub fn from_tcp(listener: StdTcpListener) -> Result<Builder<AddrIncoming>, crate::Error> {
AddrIncoming::from_std(listener).map(Server::builder) AddrIncoming::from_std(listener).map(Server::builder)
} }
}
} }
cfg_feature! { #[cfg(feature = "tcp")]
#![all(feature = "tcp", any(feature = "http1", feature = "http2"))] #[cfg_attr(
docsrs,
impl<S, E> Server<AddrIncoming, S, E> { doc(cfg(all(feature = "tcp", any(feature = "http1", feature = "http2"))))
)]
impl<S, E> Server<AddrIncoming, S, E> {
/// Returns the local address that this server is bound to. /// Returns the local address that this server is bound to.
pub fn local_addr(&self) -> SocketAddr { pub fn local_addr(&self) -> SocketAddr {
self.incoming.local_addr() self.incoming.local_addr()
} }
}
} }
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
impl<I, IO, IE, S, E, B> Server<I, S, E> impl<I, IO, IE, S, E, B> Server<I, S, E>
where where
@@ -220,7 +204,6 @@ where
} }
} }
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
impl<I, IO, IE, S, B, E> Future for Server<I, S, E> impl<I, IO, IE, S, B, E> Future for Server<I, S, E>
where where
@@ -244,7 +227,6 @@ where
impl<I: fmt::Debug, S: fmt::Debug> fmt::Debug for Server<I, S> { impl<I: fmt::Debug, S: fmt::Debug> fmt::Debug for Server<I, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut st = f.debug_struct("Server"); let mut st = f.debug_struct("Server");
#[cfg(any(feature = "http1", feature = "http2"))]
st.field("listener", &self.incoming); st.field("listener", &self.incoming);
st.finish() st.finish()
} }
@@ -252,7 +234,6 @@ impl<I: fmt::Debug, S: fmt::Debug> fmt::Debug for Server<I, S> {
// ===== impl Builder ===== // ===== impl Builder =====
#[cfg(any(feature = "http1", feature = "http2"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))] #[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
impl<I, E> Builder<I, E> { impl<I, E> Builder<I, E> {
/// Start a new builder, wrapping an incoming stream and low-level options. /// Start a new builder, wrapping an incoming stream and low-level options.
@@ -572,7 +553,11 @@ impl<I, E> Builder<I, E> {
} }
} }
#[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<E> Builder<AddrIncoming, E> { impl<E> Builder<AddrIncoming, E> {
/// Set whether TCP keepalive messages are enabled on accepted connections. /// Set whether TCP keepalive messages are enabled on accepted connections.
/// ///
@@ -619,7 +604,6 @@ impl<E> Builder<AddrIncoming, E> {
// The `Server::with_graceful_shutdown` needs to keep track of all active // The `Server::with_graceful_shutdown` needs to keep track of all active
// connections, and signal that they start to shutdown when prompted, so // connections, and signal that they start to shutdown when prompted, so
// it has a `GracefulWatcher` implementation to do that. // it has a `GracefulWatcher` implementation to do that.
#[cfg(any(feature = "http1", feature = "http2"))]
pub trait Watcher<I, S: HttpService<Body>, E>: Clone { pub trait Watcher<I, S: HttpService<Body>, E>: Clone {
type Future: Future<Output = crate::Result<()>>; type Future: Future<Output = crate::Result<()>>;
@@ -628,10 +612,8 @@ pub trait Watcher<I, S: HttpService<Body>, E>: Clone {
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[cfg(any(feature = "http1", feature = "http2"))]
pub struct NoopWatcher; pub struct NoopWatcher;
#[cfg(any(feature = "http1", feature = "http2"))]
impl<I, S, E> Watcher<I, S, E> for NoopWatcher impl<I, S, E> Watcher<I, S, E> for NoopWatcher
where where
I: AsyncRead + AsyncWrite + Unpin + Send + 'static, I: AsyncRead + AsyncWrite + Unpin + Send + 'static,
@@ -647,7 +629,6 @@ where
} }
} }
#[cfg(any(feature = "http1", feature = "http2"))]
// used by exec.rs // used by exec.rs
pub(crate) mod new_svc { pub(crate) mod new_svc {
use std::error::Error as StdError; use std::error::Error as StdError;
@@ -759,7 +740,6 @@ pub(crate) mod new_svc {
} }
} }
#[cfg(any(feature = "http1", feature = "http2"))]
pin_project! { pin_project! {
/// A future building a new `Service` to a `Connection`. /// A future building a new `Service` to a `Connection`.
/// ///
@@ -776,7 +756,6 @@ pin_project! {
} }
} }
#[cfg(any(feature = "http1", feature = "http2"))]
impl<I, F, S, FE, E, B> Future for Connecting<I, F, E> impl<I, F, S, FE, E, B> Future for Connecting<I, F, E>
where where
I: AsyncRead + AsyncWrite + Unpin, I: AsyncRead + AsyncWrite + Unpin,

16
src/server/server_stub.rs Normal file
View File

@@ -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<I, S, E = Exec> {
_marker: std::marker::PhantomData<(I, S, E)>,
}
impl<I: fmt::Debug, S: fmt::Debug> fmt::Debug for Server<I, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Server").finish()
}
}