Skip to content

Commit d6bea3e

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

File tree

4 files changed

+116
-4
lines changed

4 files changed

+116
-4
lines changed

Cargo.toml

Lines changed: 1 addition & 0 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"]

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: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,35 @@ 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::{rt::bounds::Http2ServerConnExec, server::conn::http2};
25+
2026
use pin_project_lite::pin_project;
2127

2228
use crate::common::rewind::Rewind;
2329

24-
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
30+
type Error = Box<dyn std::error::Error + Send + Sync>;
31+
32+
type Result<T> = std::result::Result<T, Error>;
2533

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

2836
/// Http1 or Http2 connection builder.
2937
#[derive(Clone, Debug)]
3038
pub struct Builder<E> {
39+
#[cfg(feature = "http1")]
3140
http1: http1::Builder,
41+
#[cfg(feature = "http2")]
3242
http2: http2::Builder<E>,
43+
#[cfg(not(feature = "http2"))]
44+
_executor: E,
3345
}
3446

3547
impl<E> Builder<E> {
@@ -50,22 +62,29 @@ impl<E> Builder<E> {
5062
/// ```
5163
pub fn new(executor: E) -> Self {
5264
Self {
65+
#[cfg(feature = "http1")]
5366
http1: http1::Builder::new(),
67+
#[cfg(feature = "http2")]
5468
http2: http2::Builder::new(executor),
69+
#[cfg(not(feature = "http2"))]
70+
_executor: executor,
5571
}
5672
}
5773

5874
/// Http1 configuration.
75+
#[cfg(feature = "http1")]
5976
pub fn http1(&mut self) -> Http1Builder<'_, E> {
6077
Http1Builder { inner: self }
6178
}
6279

6380
/// Http2 configuration.
81+
#[cfg(feature = "http2")]
6482
pub fn http2(&mut self) -> Http2Builder<'_, E> {
6583
Http2Builder { inner: self }
6684
}
6785

6886
/// Bind a connection together with a [`Service`].
87+
#[cfg(feature = "http2")]
6988
pub async fn serve_connection<I, S, B>(&self, io: I, service: S) -> Result<()>
7089
where
7190
S: Service<Request<Incoming>, Response = Response<B>>,
@@ -78,8 +97,32 @@ impl<E> Builder<E> {
7897
{
7998
let (version, io) = read_version(io).await?;
8099
match version {
100+
#[cfg(feature = "http1")]
81101
Version::H1 => self.http1.serve_connection(io, service).await?,
82102
Version::H2 => self.http2.serve_connection(io, service).await?,
103+
#[cfg(any(not(feature = "http2"), not(feature = "http1")))]
104+
version => return Err(version.unsupported()),
105+
}
106+
107+
Ok(())
108+
}
109+
110+
/// Bind a connection together with a [`Service`].
111+
#[cfg(not(feature = "http2"))]
112+
pub async fn serve_connection<I, S, B>(&self, io: I, service: S) -> Result<()>
113+
where
114+
S: Service<Request<Incoming>, Response = Response<B>>,
115+
S::Future: 'static,
116+
S::Error: Into<Box<dyn StdError + Send + Sync>>,
117+
B: Body + 'static,
118+
B::Error: Into<Box<dyn StdError + Send + Sync>>,
119+
I: Read + Write + Unpin + 'static,
120+
{
121+
let (version, io) = read_version(io).await?;
122+
match version {
123+
#[cfg(feature = "http1")]
124+
Version::H1 => self.http1.serve_connection(io, service).await?,
125+
version => return Err(version.unsupported()),
83126
}
84127

85128
Ok(())
@@ -88,6 +131,7 @@ impl<E> Builder<E> {
88131
/// Bind a connection together with a [`Service`], with the ability to
89132
/// handle HTTP upgrades. This requires that the IO object implements
90133
/// `Send`.
134+
#[cfg(feature = "http2")]
91135
pub async fn serve_connection_with_upgrades<I, S, B>(&self, io: I, service: S) -> Result<()>
92136
where
93137
S: Service<Request<Incoming>, Response = Response<B>>,
@@ -100,13 +144,45 @@ impl<E> Builder<E> {
100144
{
101145
let (version, io) = read_version(io).await?;
102146
match version {
147+
#[cfg(feature = "http1")]
103148
Version::H1 => {
104149
self.http1
105150
.serve_connection(io, service)
106151
.with_upgrades()
107152
.await?
108153
}
109154
Version::H2 => self.http2.serve_connection(io, service).await?,
155+
#[cfg(any(not(feature = "http2"), not(feature = "http1")))]
156+
version => return Err(version.unsupported()),
157+
}
158+
159+
Ok(())
160+
}
161+
162+
/// Bind a connection together with a [`Service`], with the ability to
163+
/// handle HTTP upgrades. This requires that the IO object implements
164+
/// `Send`.
165+
#[cfg(not(feature = "http2"))]
166+
pub async fn serve_connection_with_upgrades<I, S, B>(&self, io: I, service: S) -> Result<()>
167+
where
168+
S: Service<Request<Incoming>, Response = Response<B>>,
169+
S::Future: 'static,
170+
S::Error: Into<Box<dyn StdError + Send + Sync>>,
171+
B: Body + 'static,
172+
B::Error: Into<Box<dyn StdError + Send + Sync>>,
173+
I: Read + Write + Unpin + Send + 'static,
174+
{
175+
let (version, io) = read_version(io).await?;
176+
match version {
177+
#[cfg(feature = "http1")]
178+
Version::H1 => {
179+
self.http1
180+
.serve_connection(io, service)
181+
.with_upgrades()
182+
.await?
183+
}
184+
#[cfg(any(not(feature = "http2"), not(feature = "http1")))]
185+
version => return Err(version.unsupported()),
110186
}
111187

112188
Ok(())
@@ -117,6 +193,18 @@ enum Version {
117193
H1,
118194
H2,
119195
}
196+
197+
impl Version {
198+
#[must_use]
199+
#[cfg(any(not(feature = "http2"), not(feature = "http1")))]
200+
pub fn unsupported(self) -> Error {
201+
match self {
202+
Version::H1 => Error::from("HTTP/1 is not supported"),
203+
Version::H2 => Error::from("HTTP/2 is not supported"),
204+
}
205+
}
206+
}
207+
120208
async fn read_version<'a, A>(mut reader: A) -> IoResult<(Version, Rewind<A>)>
121209
where
122210
A: Read + Unpin,
@@ -172,12 +260,15 @@ where
172260
}
173261

174262
/// Http1 part of builder.
263+
#[cfg(feature = "http1")]
175264
pub struct Http1Builder<'a, E> {
176265
inner: &'a mut Builder<E>,
177266
}
178267

268+
#[cfg(feature = "http1")]
179269
impl<E> Http1Builder<'_, E> {
180270
/// Http2 configuration.
271+
#[cfg(feature = "http2")]
181272
pub fn http2(&mut self) -> Http2Builder<'_, E> {
182273
Http2Builder {
183274
inner: &mut self.inner,
@@ -292,6 +383,7 @@ impl<E> Http1Builder<'_, E> {
292383
}
293384

294385
/// Bind a connection together with a [`Service`].
386+
#[cfg(feature = "http2")]
295387
pub async fn serve_connection<I, S, B>(&self, io: I, service: S) -> Result<()>
296388
where
297389
S: Service<Request<Incoming>, Response = Response<B>>,
@@ -304,14 +396,31 @@ impl<E> Http1Builder<'_, E> {
304396
{
305397
self.inner.serve_connection(io, service).await
306398
}
399+
400+
/// Bind a connection together with a [`Service`].
401+
#[cfg(not(feature = "http2"))]
402+
pub async fn serve_connection<I, S, B>(&self, io: I, service: S) -> Result<()>
403+
where
404+
S: Service<Request<Incoming>, Response = Response<B>>,
405+
S::Future: 'static,
406+
S::Error: Into<Box<dyn StdError + Send + Sync>>,
407+
B: Body + 'static,
408+
B::Error: Into<Box<dyn StdError + Send + Sync>>,
409+
I: Read + Write + Unpin + 'static,
410+
{
411+
self.inner.serve_connection(io, service).await
412+
}
307413
}
308414

309415
/// Http2 part of builder.
416+
#[cfg(feature = "http2")]
310417
pub struct Http2Builder<'a, E> {
311418
inner: &'a mut Builder<E>,
312419
}
313420

421+
#[cfg(feature = "http2")]
314422
impl<E> Http2Builder<'_, E> {
423+
#[cfg(feature = "http1")]
315424
/// Http1 configuration.
316425
pub fn http1(&mut self) -> Http1Builder<'_, E> {
317426
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)