Skip to content

Commit

Permalink
feat(lib): Export more things with Cargo features [server, !http1, !h…
Browse files Browse the repository at this point in the history
…ttp2]

* server::Server
* server::conn::{AddrIncoming, AddrStream}

This allows higher-level libraries to use or re-export more parts of the
API without deciding for the end user which HTTP versions the hyper
server will support.
  • Loading branch information
jplatte authored and seanmonstar committed Aug 31, 2021
1 parent cf6f62c commit 0a4b56a
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 66 deletions.
14 changes: 8 additions & 6 deletions src/common/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@ 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")]
pub trait ConnStreamExec<F, B: HttpBody>: Clone {
fn execute_h2stream(&mut self, fut: H2Stream<F, B>);
}

#[cfg(feature = "server")]
#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
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 @@ -76,7 +78,7 @@ where
}
}

#[cfg(feature = "server")]
#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
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 @@ -102,7 +104,7 @@ where
}
}

#[cfg(feature = "server")]
#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
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 Down
2 changes: 1 addition & 1 deletion src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")))]
Expand Down
12 changes: 3 additions & 9 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
Expand Down Expand Up @@ -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<E: Into<Cause>>(cause: E) -> Error {
Error::new(Kind::Listen).with(cause)
}
Expand Down Expand Up @@ -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")]
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
84 changes: 61 additions & 23 deletions src/server/conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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<E = Exec> {
exec: E,
h1_half_close: bool,
Expand All @@ -100,6 +111,7 @@ pub struct Http<E = Exec> {
}

/// 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.
Expand All @@ -113,6 +125,7 @@ enum ConnectionMode {
Fallback,
}

#[cfg(any(feature = "http1", feature = "http2"))]
pin_project! {
/// A stream mapping incoming IOs to new services.
///
Expand All @@ -127,13 +140,15 @@ pin_project! {
}
}

#[cfg(any(feature = "http1", feature = "http2"))]
pin_project! {
/// A future building a new `Service` to a `Connection`.
///
/// Wraps the future returned from `MakeService` into one that returns
/// a `Connection`.
#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
pub struct Connecting<I, F, E = Exec> {
#[pin]
future: F,
Expand All @@ -142,6 +157,7 @@ pin_project! {
}
}

#[cfg(any(feature = "http1", feature = "http2"))]
pin_project! {
#[must_use = "futures do nothing unless polled"]
#[derive(Debug)]
Expand All @@ -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<T, S, E = Exec>
where
S: HttpService<Body>,
Expand All @@ -172,18 +190,19 @@ pin_project! {
type Http1Dispatcher<T, B, S> =
proto::h1::Dispatcher<proto::h1::dispatch::Server<S, Body>, B, T, proto::ServerTransaction>;

#[cfg(not(feature = "http1"))]
#[cfg(all(not(feature = "http1"), feature = "http2"))]
type Http1Dispatcher<T, B, S> = (Never, PhantomData<(T, Box<Pin<B>>, Box<Pin<S>>)>);

#[cfg(feature = "http2")]
type Http2Server<T, B, S, E> = proto::h2::Server<Rewind<T>, S, B, E>;

#[cfg(not(feature = "http2"))]
#[cfg(all(not(feature = "http2"), feature = "http1"))]
type Http2Server<T, B, S, E> = (
Never,
PhantomData<(T, Box<Pin<S>>, Box<Pin<B>>, Box<Pin<E>>)>,
);

#[cfg(any(feature = "http1", feature = "http2"))]
pin_project! {
#[project = ProtoServerProj]
pub(super) enum ProtoServer<T, B, S, E = Exec>
Expand All @@ -209,7 +228,10 @@ enum Fallback<E> {
Http1Only,
}

#[cfg(not(all(feature = "http1", feature = "http2")))]
#[cfg(all(
any(feature = "http1", feature = "http2"),
not(all(feature = "http1", feature = "http2"))
))]
type Fallback<E> = PhantomData<E>;

#[cfg(all(feature = "http1", feature = "http2"))]
Expand All @@ -230,6 +252,8 @@ impl<E> Unpin for Fallback<E> {}
/// 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<T, S> {
/// The original IO object used in the handshake.
pub io: T,
Expand All @@ -249,6 +273,7 @@ pub struct Parts<T, S> {

// ===== 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.
Expand All @@ -268,6 +293,7 @@ impl Http {
}
}

#[cfg(any(feature = "http1", feature = "http2"))]
impl<E> Http<E> {
/// Sets whether HTTP1 is required.
///
Expand Down Expand Up @@ -633,6 +659,7 @@ impl<E> Http<E> {

// ===== impl Connection =====

#[cfg(any(feature = "http1", feature = "http2"))]
impl<I, B, S, E> Connection<I, S, E>
where
S: HttpService<Body, ResBody = B>,
Expand Down Expand Up @@ -802,6 +829,7 @@ where
}
}

#[cfg(any(feature = "http1", feature = "http2"))]
impl<I, B, S, E> Future for Connection<I, S, E>
where
S: HttpService<Body, ResBody = B>,
Expand Down Expand Up @@ -848,6 +876,7 @@ where
}
}

#[cfg(any(feature = "http1", feature = "http2"))]
impl<I, S> fmt::Debug for Connection<I, S>
where
S: HttpService<Body>,
Expand All @@ -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 {
Expand All @@ -878,6 +908,7 @@ impl Default for ConnectionMode {

// ===== impl Serve =====

#[cfg(any(feature = "http1", feature = "http2"))]
impl<I, S, E> Serve<I, S, E> {
/// Get a reference to the incoming stream.
#[inline]
Expand All @@ -899,6 +930,7 @@ impl<I, S, E> Serve<I, S, E> {
}
}

#[cfg(any(feature = "http1", feature = "http2"))]
impl<I, IO, IE, S, B, E> Serve<I, S, E>
where
I: Accept<Conn = IO, Error = IE>,
Expand Down Expand Up @@ -937,6 +969,7 @@ where

// ===== impl Connecting =====

#[cfg(any(feature = "http1", feature = "http2"))]
impl<I, F, S, FE, E, B> Future for Connecting<I, F, E>
where
I: AsyncRead + AsyncWrite + Unpin,
Expand All @@ -958,19 +991,21 @@ where

// ===== impl SpawnAll =====

#[cfg(feature = "tcp")]
#[cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))]
impl<S, E> SpawnAll<AddrIncoming, S, E> {
pub(super) fn local_addr(&self) -> SocketAddr {
self.serve.incoming.local_addr()
}
}

#[cfg(any(feature = "http1", feature = "http2"))]
impl<I, S, E> SpawnAll<I, S, E> {
pub(super) fn incoming_ref(&self) -> &I {
self.serve.incoming_ref()
}
}

#[cfg(any(feature = "http1", feature = "http2"))]
impl<I, IO, IE, S, B, E> SpawnAll<I, S, E>
where
I: Accept<Conn = IO, Error = IE>,
Expand Down Expand Up @@ -1008,6 +1043,7 @@ where

// ===== impl ProtoServer =====

#[cfg(any(feature = "http1", feature = "http2"))]
impl<T, B, S, E> Future for ProtoServer<T, B, S, E>
where
T: AsyncRead + AsyncWrite + Unpin,
Expand All @@ -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};
Expand Down Expand Up @@ -1177,6 +1214,7 @@ pub(crate) mod spawn_all {
}
}

#[cfg(any(feature = "http1", feature = "http2"))]
mod upgrades {
use super::*;

Expand Down
Loading

0 comments on commit 0a4b56a

Please sign in to comment.