diff --git a/Cargo.toml b/Cargo.toml index 860b2a8dca..9a41922bf6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,6 @@ futures-util = { version = "0.3", default-features = false } http = "0.2" http-body = "=1.0.0-rc.2" pin-project-lite = "0.2.4" -tokio = { version = "1.13", features = ["sync"] } # Optional @@ -36,6 +35,7 @@ httparse = { version = "1.8", optional = true } httpdate = { version = "1.0", optional = true } itoa = { version = "1", optional = true } libc = { version = "0.2", optional = true } +tokio = { version = "1", features = ["sync"], optional = true } tracing = { version = "0.1", default-features = false, features = ["std"], optional = true } want = { version = "0.3", optional = true } @@ -74,13 +74,16 @@ full = [ ] # HTTP versions -http1 = ["dep:httparse", "dep:itoa"] -http2 = ["dep:h2"] +http1 = ["upgrade", "dep:httparse", "dep:itoa"] +http2 = ["upgrade", "dep:h2"] # Client/Server client = ["dep:want"] server = ["dep:httpdate"] +# HTTP Upgrades +upgrade = ["dep:tokio"] + # C-API support (currently unstable (no semver)) ffi = ["dep:libc", "dep:http-body-util"] diff --git a/src/common/io/mod.rs b/src/common/io/mod.rs index 92f71c4ee6..3b886d4b99 100644 --- a/src/common/io/mod.rs +++ b/src/common/io/mod.rs @@ -1,7 +1,9 @@ #[cfg(all(any(feature = "client", feature = "server"), feature = "http2"))] mod compat; +#[cfg(feature = "upgrade")] mod rewind; #[cfg(all(any(feature = "client", feature = "server"), feature = "http2"))] pub(crate) use self::compat::{compat, Compat}; +#[cfg(feature = "upgrade")] pub(crate) use self::rewind::Rewind; diff --git a/src/error.rs b/src/error.rs index 719bd2a304..d9e08d0cce 100644 --- a/src/error.rs +++ b/src/error.rs @@ -48,6 +48,7 @@ pub(super) enum Kind { #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))] UnexpectedMessage, /// A pending item was dropped before ever being processed. + #[cfg(feature = "upgrade")] Canceled, /// Indicates a channel (client or body sender) is closed. ChannelClosed, @@ -140,6 +141,7 @@ pub(super) enum User { UnsupportedStatusCode, /// User tried polling for an upgrade that doesn't exist. + #[cfg(feature = "upgrade")] NoUpgrade, /// User polled for an upgrade, but low-level API is not using upgrades. @@ -186,6 +188,7 @@ impl Error { } /// Returns true if this was about a `Request` that was canceled. + #[cfg(feature = "upgrade")] pub fn is_canceled(&self) -> bool { matches!(self.inner.kind, Kind::Canceled) } @@ -216,6 +219,7 @@ impl Error { } } + #[cfg(feature = "upgrade")] pub(super) fn with>(mut self, cause: C) -> Error { self.inner.cause = Some(cause.into()); self @@ -248,6 +252,7 @@ impl Error { .unwrap_or(h2::Reason::INTERNAL_ERROR) } + #[cfg(feature = "upgrade")] pub(super) fn new_canceled() -> Error { Error::new(Kind::Canceled) } @@ -304,6 +309,7 @@ impl Error { Error::new(Kind::User(User::BodyWriteAborted)) } + #[cfg(feature = "upgrade")] fn new_user(user: User) -> Error { Error::new(Kind::User(user)) } @@ -325,6 +331,7 @@ impl Error { Error::new_user(User::UnsupportedStatusCode) } + #[cfg(feature = "upgrade")] pub(super) fn new_user_no_upgrade() -> Error { Error::new_user(User::NoUpgrade) } @@ -408,6 +415,7 @@ impl Error { #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))] Kind::UnexpectedMessage => "received unexpected message from connection", Kind::ChannelClosed => "channel closed", + #[cfg(feature = "upgrade")] Kind::Canceled => "operation was canceled", #[cfg(all(feature = "http1", feature = "server"))] Kind::HeaderTimeout => "read header from client timeout", @@ -450,6 +458,7 @@ impl Error { Kind::User(User::UnsupportedStatusCode) => { "response has 1xx status code, not supported by server" } + #[cfg(feature = "upgrade")] Kind::User(User::NoUpgrade) => "no upgrade available", #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))] Kind::User(User::ManualUpgrade) => "upgrade expected but low level API in use", diff --git a/src/lib.rs b/src/lib.rs index 0d1db8320a..c0ee66be35 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,8 +49,10 @@ //! - `http2`: Enables HTTP/2 support. //! - `client`: Enables the HTTP `client`. //! - `server`: Enables the HTTP `server`. +//! - `upgrade`: Enables [HTTP Upgrades]. //! //! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section +//! [Http Upgrades]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism //! //! # Unstable Features //! hyper includes a set of unstable optional features that can be enabled through the use of a @@ -93,7 +95,6 @@ pub mod ext; mod mock; pub mod rt; pub mod service; -pub mod upgrade; #[cfg(feature = "ffi")] #[cfg_attr(docsrs, doc(cfg(all(feature = "ffi", hyper_unstable_ffi))))] @@ -115,3 +116,9 @@ cfg_feature! { pub mod server; } + +cfg_feature! { + #![feature = "upgrade"] + + pub mod upgrade; +} diff --git a/src/rt/io.rs b/src/rt/io.rs index bf045c3714..059841b5cd 100644 --- a/src/rt/io.rs +++ b/src/rt/io.rs @@ -200,6 +200,7 @@ impl<'data> ReadBuf<'data> { } #[inline] + #[cfg(feature = "upgrade")] fn remaining(&self) -> usize { self.capacity() - self.filled } @@ -244,11 +245,13 @@ impl<'data> ReadBufCursor<'data> { } #[inline] + #[cfg(feature = "upgrade")] pub(crate) fn remaining(&self) -> usize { self.buf.remaining() } #[inline] + #[cfg(feature = "upgrade")] pub(crate) fn put_slice(&mut self, buf: &[u8]) { assert!( self.buf.remaining() >= buf.len(),