feat(http1): Make HTTP/1 support an optional feature
cc #2251 BREAKING CHANGE: This puts all HTTP/1 methods and support behind an `http1` cargo feature, which will not be enabled by default. To use HTTP/1, add `features = ["http1"]` to the hyper dependency in your `Cargo.toml`.
This commit is contained in:
		| @@ -10,7 +10,8 @@ | ||||
|  | ||||
| use std::error::Error as StdError; | ||||
| use std::fmt; | ||||
| use std::mem; | ||||
| #[cfg(feature = "http2")] | ||||
| use std::marker::PhantomData; | ||||
| use std::sync::Arc; | ||||
| #[cfg(feature = "runtime")] | ||||
| #[cfg(feature = "http2")] | ||||
| @@ -24,11 +25,14 @@ use tower_service::Service; | ||||
|  | ||||
| use super::dispatch; | ||||
| use crate::body::HttpBody; | ||||
| use crate::common::{task, BoxSendFuture, Exec, Executor, Future, Pin, Poll}; | ||||
| use crate::common::{task, BoxSendFuture, Exec, Future, Pin, Poll}; | ||||
| use crate::proto; | ||||
| use crate::rt::Executor; | ||||
| #[cfg(feature = "http1")] | ||||
| use crate::upgrade::Upgraded; | ||||
| use crate::{Body, Request, Response}; | ||||
|  | ||||
| #[cfg(feature = "http1")] | ||||
| type Http1Dispatcher<T, B, R> = proto::dispatch::Dispatcher<proto::dispatch::Client<B>, B, T, R>; | ||||
|  | ||||
| #[pin_project(project = ProtoClientProj)] | ||||
| @@ -36,9 +40,10 @@ enum ProtoClient<T, B> | ||||
| where | ||||
|     B: HttpBody, | ||||
| { | ||||
|     #[cfg(feature = "http1")] | ||||
|     H1(#[pin] Http1Dispatcher<T, B, proto::h1::ClientTransaction>), | ||||
|     #[cfg(feature = "http2")] | ||||
|     H2(#[pin] proto::h2::ClientTask<B>), | ||||
|     H2(#[pin] proto::h2::ClientTask<B>, PhantomData<fn(T)>), | ||||
| } | ||||
|  | ||||
| /// Returns a handshake future over some IO. | ||||
| @@ -88,6 +93,7 @@ pub struct Builder { | ||||
|  | ||||
| #[derive(Clone, Debug)] | ||||
| enum Proto { | ||||
|     #[cfg(feature = "http1")] | ||||
|     Http1, | ||||
|     #[cfg(feature = "http2")] | ||||
|     Http2, | ||||
| @@ -353,18 +359,20 @@ where | ||||
|     /// | ||||
|     /// Only works for HTTP/1 connections. HTTP/2 connections will panic. | ||||
|     pub fn into_parts(self) -> Parts<T> { | ||||
|         let (io, read_buf, _) = match self.inner.expect("already upgraded") { | ||||
|             ProtoClient::H1(h1) => h1.into_inner(), | ||||
|         match self.inner.expect("already upgraded") { | ||||
|             #[cfg(feature = "http1")] | ||||
|             ProtoClient::H1(h1) => { | ||||
|                 let (io, read_buf, _) = h1.into_inner(); | ||||
|                 Parts { | ||||
|                     io, | ||||
|                     read_buf, | ||||
|                     _inner: (), | ||||
|                 } | ||||
|             } | ||||
|             #[cfg(feature = "http2")] | ||||
|             ProtoClient::H2(_h2) => { | ||||
|             ProtoClient::H2(..) => { | ||||
|                 panic!("http2 cannot into_inner"); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         Parts { | ||||
|             io, | ||||
|             read_buf, | ||||
|             _inner: (), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -381,9 +389,10 @@ where | ||||
|     /// to work with this function; or use the `without_shutdown` wrapper. | ||||
|     pub fn poll_without_shutdown(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> { | ||||
|         match *self.inner.as_mut().expect("already upgraded") { | ||||
|             #[cfg(feature = "http1")] | ||||
|             ProtoClient::H1(ref mut h1) => h1.poll_without_shutdown(cx), | ||||
|             #[cfg(feature = "http2")] | ||||
|             ProtoClient::H2(ref mut h2) => Pin::new(h2).poll(cx).map_ok(|_| ()), | ||||
|             ProtoClient::H2(ref mut h2, _) => Pin::new(h2).poll(cx).map_ok(|_| ()), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -410,16 +419,18 @@ where | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         match ready!(Pin::new(self.inner.as_mut().unwrap()).poll(cx))? { | ||||
|             proto::Dispatched::Shutdown => Poll::Ready(Ok(())), | ||||
|             proto::Dispatched::Upgrade(pending) => { | ||||
|                 let h1 = match mem::replace(&mut self.inner, None) { | ||||
|                     Some(ProtoClient::H1(h1)) => h1, | ||||
|                     _ => unreachable!("Upgrade expects h1"), | ||||
|                 }; | ||||
|  | ||||
|                 let (io, buf, _) = h1.into_inner(); | ||||
|                 pending.fulfill(Upgraded::new(io, buf)); | ||||
|                 Poll::Ready(Ok(())) | ||||
|             } | ||||
|             #[cfg(feature = "http1")] | ||||
|             proto::Dispatched::Upgrade(pending) => match self.inner.take() { | ||||
|                 Some(ProtoClient::H1(h1)) => { | ||||
|                     let (io, buf, _) = h1.into_inner(); | ||||
|                     pending.fulfill(Upgraded::new(io, buf)); | ||||
|                     Poll::Ready(Ok(())) | ||||
|                 } | ||||
|                 _ => { | ||||
|                     drop(pending); | ||||
|                     unreachable!("Upgrade expects h1"); | ||||
|                 } | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -448,7 +459,10 @@ impl Builder { | ||||
|             h1_max_buf_size: None, | ||||
|             #[cfg(feature = "http2")] | ||||
|             h2_builder: Default::default(), | ||||
|             #[cfg(feature = "http1")] | ||||
|             version: Proto::Http1, | ||||
|             #[cfg(not(feature = "http1"))] | ||||
|             version: Proto::Http2, | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -477,6 +491,7 @@ impl Builder { | ||||
|         self | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "http1")] | ||||
|     pub(super) fn h1_max_buf_size(&mut self, max: usize) -> &mut Self { | ||||
|         assert!( | ||||
|             max >= proto::h1::MINIMUM_MAX_BUFFER_SIZE, | ||||
| @@ -494,7 +509,9 @@ impl Builder { | ||||
|     #[cfg(feature = "http2")] | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] | ||||
|     pub fn http2_only(&mut self, enabled: bool) -> &mut Builder { | ||||
|         self.version = if enabled { Proto::Http2 } else { Proto::Http1 }; | ||||
|         if enabled { | ||||
|             self.version = Proto::Http2 | ||||
|         } | ||||
|         self | ||||
|     } | ||||
|  | ||||
| @@ -643,6 +660,7 @@ impl Builder { | ||||
|  | ||||
|             let (tx, rx) = dispatch::channel(); | ||||
|             let proto = match opts.version { | ||||
|                 #[cfg(feature = "http1")] | ||||
|                 Proto::Http1 => { | ||||
|                     let mut conn = proto::Conn::new(io); | ||||
|                     if let Some(writev) = opts.h1_writev { | ||||
| @@ -670,7 +688,7 @@ impl Builder { | ||||
|                     let h2 = | ||||
|                         proto::h2::client::handshake(io, rx, &opts.h2_builder, opts.exec.clone()) | ||||
|                             .await?; | ||||
|                     ProtoClient::H2(h2) | ||||
|                     ProtoClient::H2(h2, PhantomData) | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
| @@ -723,9 +741,10 @@ where | ||||
|  | ||||
|     fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         match self.project() { | ||||
|             #[cfg(feature = "http1")] | ||||
|             ProtoClientProj::H1(c) => c.poll(cx), | ||||
|             #[cfg(feature = "http2")] | ||||
|             ProtoClientProj::H2(c) => c.poll(cx), | ||||
|             ProtoClientProj::H2(c, _) => c.poll(cx), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -162,11 +162,13 @@ impl<T, U> Receiver<T, U> { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "http1")] | ||||
|     pub(crate) fn close(&mut self) { | ||||
|         self.taker.cancel(); | ||||
|         self.inner.close(); | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "http1")] | ||||
|     pub(crate) fn try_recv(&mut self) -> Option<(T, Callback<T, U>)> { | ||||
|         match self.inner.try_recv() { | ||||
|             Ok(mut env) => env.0.take(), | ||||
|   | ||||
| @@ -62,7 +62,8 @@ use http::{Method, Request, Response, Uri, Version}; | ||||
| use self::connect::{sealed::Connect, Alpn, Connected, Connection}; | ||||
| use self::pool::{Key as PoolKey, Pool, Poolable, Pooled, Reservation}; | ||||
| use crate::body::{Body, HttpBody}; | ||||
| use crate::common::{lazy as hyper_lazy, task, BoxSendFuture, Executor, Future, Lazy, Pin, Poll}; | ||||
| use crate::common::{lazy as hyper_lazy, task, BoxSendFuture, Future, Lazy, Pin, Poll}; | ||||
| use crate::rt::Executor; | ||||
|  | ||||
| #[cfg(feature = "tcp")] | ||||
| pub use self::connect::HttpConnector; | ||||
| @@ -1022,6 +1023,8 @@ impl Builder { | ||||
|     /// # Panics | ||||
|     /// | ||||
|     /// The minimum value allowed is 8192. This method panics if the passed `max` is less than the minimum. | ||||
|     #[cfg(feature = "http1")] | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "http1")))] | ||||
|     pub fn http1_max_buf_size(&mut self, max: usize) -> &mut Self { | ||||
|         self.conn_builder.h1_max_buf_size(max); | ||||
|         self | ||||
|   | ||||
		Reference in New Issue
	
	Block a user