Skip to content

Commit 08a5dd5

Browse files
committed
feat: allow enabling http1/http2 individually
1 parent 61724d1 commit 08a5dd5

File tree

4 files changed

+119
-6
lines changed

4 files changed

+119
-6
lines changed

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ authors = ["Sean McArthur <sean@seanmonstar.com>"]
1111
keywords = ["http", "hyper", "hyperium"]
1212
categories = ["network-programming", "web-programming::http-client", "web-programming::http-server"]
1313
edition = "2018"
14+
resolver = "2"
1415

1516
[package.metadata.docs.rs]
1617
features = ["full"]
@@ -48,7 +49,6 @@ full = [
4849
"client",
4950
"client-legacy",
5051
"server",
51-
"server-auto",
5252
"service",
5353
"http1",
5454
"http2",
@@ -59,7 +59,6 @@ client = ["hyper/client", "dep:tower", "dep:tower-service"]
5959
client-legacy = ["client"]
6060

6161
server = ["hyper/server"]
62-
server-auto = ["server", "http1", "http2"]
6362

6463
service = ["dep:tower", "dep:tower-service"]
6564

src/common/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![allow(missing_docs)]
22

3+
#[allow(unused)]
34
macro_rules! ready {
45
($e:expr) => {
56
match $e {
@@ -9,6 +10,7 @@ macro_rules! ready {
910
};
1011
}
1112

13+
#[allow(unused)]
1214
pub(crate) use ready;
1315
pub(crate) mod exec;
1416
#[cfg(feature = "client")]

src/server/conn/auto.rs

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,38 @@ use http::{Request, Response};
1313
use http_body::Body;
1414
use hyper::{
1515
body::Incoming,
16-
rt::{bounds::Http2ServerConnExec, Read, ReadBuf, Timer, Write},
17-
server::conn::{http1, http2},
16+
rt::{Read, ReadBuf, Timer, Write},
1817
service::Service,
1918
};
19+
20+
#[cfg(feature = "http1")]
21+
use hyper::server::conn::http1;
22+
23+
#[cfg(feature = "http2")]
24+
use hyper::{
25+
rt::bounds::Http2ServerConnExec,
26+
server::conn::http2,
27+
};
28+
2029
use pin_project_lite::pin_project;
2130

2231
use crate::common::rewind::Rewind;
2332

24-
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
33+
type Error = Box<dyn std::error::Error + Send + Sync>;
34+
35+
type Result<T> = std::result::Result<T, Error>;
2536

2637
const H2_PREFACE: &[u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
2738

2839
/// Http1 or Http2 connection builder.
2940
#[derive(Clone, Debug)]
3041
pub struct Builder<E> {
42+
#[cfg(feature = "http1")]
3143
http1: http1::Builder,
44+
#[cfg(feature = "http2")]
3245
http2: http2::Builder<E>,
46+
#[cfg(not(feature = "http2"))]
47+
_executor: E,
3348
}
3449

3550
impl<E> Builder<E> {
@@ -50,22 +65,29 @@ impl<E> Builder<E> {
5065
/// ```
5166
pub fn new(executor: E) -> Self {
5267
Self {
68+
#[cfg(feature = "http1")]
5369
http1: http1::Builder::new(),
70+
#[cfg(feature = "http2")]
5471
http2: http2::Builder::new(executor),
72+
#[cfg(not(feature = "http2"))]
73+
_executor: executor,
5574
}
5675
}
5776

5877
/// Http1 configuration.
78+
#[cfg(feature = "http1")]
5979
pub fn http1(&mut self) -> Http1Builder<'_, E> {
6080
Http1Builder { inner: self }
6181
}
6282

6383
/// Http2 configuration.
84+
#[cfg(feature = "http2")]
6485
pub fn http2(&mut self) -> Http2Builder<'_, E> {
6586
Http2Builder { inner: self }
6687
}
6788

6889
/// Bind a connection together with a [`Service`].
90+
#[cfg(feature = "http2")]
6991
pub async fn serve_connection<I, S, B>(&self, io: I, service: S) -> Result<()>
7092
where
7193
S: Service<Request<Incoming>, Response = Response<B>>,
@@ -78,8 +100,32 @@ impl<E> Builder<E> {
78100
{
79101
let (version, io) = read_version(io).await?;
80102
match version {
103+
#[cfg(feature = "http1")]
81104
Version::H1 => self.http1.serve_connection(io, service).await?,
82105
Version::H2 => self.http2.serve_connection(io, service).await?,
106+
#[cfg(any(not(feature = "http2"), not(feature = "http1")))]
107+
version => return Err(version.unsupported()),
108+
}
109+
110+
Ok(())
111+
}
112+
113+
/// Bind a connection together with a [`Service`].
114+
#[cfg(not(feature = "http2"))]
115+
pub async fn serve_connection<I, S, B>(&self, io: I, service: S) -> Result<()>
116+
where
117+
S: Service<Request<Incoming>, Response = Response<B>>,
118+
S::Future: 'static,
119+
S::Error: Into<Box<dyn StdError + Send + Sync>>,
120+
B: Body + 'static,
121+
B::Error: Into<Box<dyn StdError + Send + Sync>>,
122+
I: Read + Write + Unpin + 'static,
123+
{
124+
let (version, io) = read_version(io).await?;
125+
match version {
126+
#[cfg(feature = "http1")]
127+
Version::H1 => self.http1.serve_connection(io, service).await?,
128+
version => return Err(version.unsupported()),
83129
}
84130

85131
Ok(())
@@ -88,6 +134,7 @@ impl<E> Builder<E> {
88134
/// Bind a connection together with a [`Service`], with the ability to
89135
/// handle HTTP upgrades. This requires that the IO object implements
90136
/// `Send`.
137+
#[cfg(feature = "http2")]
91138
pub async fn serve_connection_with_upgrades<I, S, B>(&self, io: I, service: S) -> Result<()>
92139
where
93140
S: Service<Request<Incoming>, Response = Response<B>>,
@@ -100,13 +147,45 @@ impl<E> Builder<E> {
100147
{
101148
let (version, io) = read_version(io).await?;
102149
match version {
150+
#[cfg(feature = "http1")]
103151
Version::H1 => {
104152
self.http1
105153
.serve_connection(io, service)
106154
.with_upgrades()
107155
.await?
108156
}
109157
Version::H2 => self.http2.serve_connection(io, service).await?,
158+
#[cfg(any(not(feature = "http2"), not(feature = "http1")))]
159+
version => return Err(version.unsupported()),
160+
}
161+
162+
Ok(())
163+
}
164+
165+
/// Bind a connection together with a [`Service`], with the ability to
166+
/// handle HTTP upgrades. This requires that the IO object implements
167+
/// `Send`.
168+
#[cfg(not(feature = "http2"))]
169+
pub async fn serve_connection_with_upgrades<I, S, B>(&self, io: I, service: S) -> Result<()>
170+
where
171+
S: Service<Request<Incoming>, Response = Response<B>>,
172+
S::Future: 'static,
173+
S::Error: Into<Box<dyn StdError + Send + Sync>>,
174+
B: Body + 'static,
175+
B::Error: Into<Box<dyn StdError + Send + Sync>>,
176+
I: Read + Write + Unpin + Send + 'static,
177+
{
178+
let (version, io) = read_version(io).await?;
179+
match version {
180+
#[cfg(feature = "http1")]
181+
Version::H1 => {
182+
self.http1
183+
.serve_connection(io, service)
184+
.with_upgrades()
185+
.await?
186+
}
187+
#[cfg(any(not(feature = "http2"), not(feature = "http1")))]
188+
version => return Err(version.unsupported()),
110189
}
111190

112191
Ok(())
@@ -117,6 +196,18 @@ enum Version {
117196
H1,
118197
H2,
119198
}
199+
200+
impl Version {
201+
#[must_use]
202+
#[cfg(any(not(feature = "http2"), not(feature = "http1")))]
203+
pub fn unsupported(self) -> Error {
204+
match self {
205+
Version::H1 => Error::from("HTTP/1 is not supported"),
206+
Version::H2 => Error::from("HTTP/2 is not supported"),
207+
}
208+
}
209+
}
210+
120211
async fn read_version<'a, A>(mut reader: A) -> IoResult<(Version, Rewind<A>)>
121212
where
122213
A: Read + Unpin,
@@ -172,12 +263,15 @@ where
172263
}
173264

174265
/// Http1 part of builder.
266+
#[cfg(feature = "http1")]
175267
pub struct Http1Builder<'a, E> {
176268
inner: &'a mut Builder<E>,
177269
}
178270

271+
#[cfg(feature = "http1")]
179272
impl<E> Http1Builder<'_, E> {
180273
/// Http2 configuration.
274+
#[cfg(feature = "http2")]
181275
pub fn http2(&mut self) -> Http2Builder<'_, E> {
182276
Http2Builder {
183277
inner: &mut self.inner,
@@ -292,6 +386,7 @@ impl<E> Http1Builder<'_, E> {
292386
}
293387

294388
/// Bind a connection together with a [`Service`].
389+
#[cfg(feature = "http2")]
295390
pub async fn serve_connection<I, S, B>(&self, io: I, service: S) -> Result<()>
296391
where
297392
S: Service<Request<Incoming>, Response = Response<B>>,
@@ -304,14 +399,31 @@ impl<E> Http1Builder<'_, E> {
304399
{
305400
self.inner.serve_connection(io, service).await
306401
}
402+
403+
/// Bind a connection together with a [`Service`].
404+
#[cfg(not(feature = "http2"))]
405+
pub async fn serve_connection<I, S, B>(&self, io: I, service: S) -> Result<()>
406+
where
407+
S: Service<Request<Incoming>, Response = Response<B>>,
408+
S::Future: 'static,
409+
S::Error: Into<Box<dyn StdError + Send + Sync>>,
410+
B: Body + 'static,
411+
B::Error: Into<Box<dyn StdError + Send + Sync>>,
412+
I: Read + Write + Unpin + 'static,
413+
{
414+
self.inner.serve_connection(io, service).await
415+
}
307416
}
308417

309418
/// Http2 part of builder.
419+
#[cfg(feature = "http2")]
310420
pub struct Http2Builder<'a, E> {
311421
inner: &'a mut Builder<E>,
312422
}
313423

424+
#[cfg(feature = "http2")]
314425
impl<E> Http2Builder<'_, E> {
426+
#[cfg(feature = "http1")]
315427
/// Http1 configuration.
316428
pub fn http1(&mut self) -> Http1Builder<'_, E> {
317429
Http1Builder {

src/server/conn/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
//! Connection utilities.
22
3-
#[cfg(feature = "server-auto")]
3+
#[cfg(any(feature = "http1", feature = "http2"))]
44
pub mod auto;

0 commit comments

Comments
 (0)