Skip to content

Commit 0a4b56a

Browse files
jplatteseanmonstar
authored andcommittedAug 31, 2021
feat(lib): Export more things with Cargo features [server, !http1, !http2]
* 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.
1 parent cf6f62c commit 0a4b56a

File tree

7 files changed

+127
-66
lines changed

7 files changed

+127
-66
lines changed
 

‎src/common/exec.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,24 @@ use std::future::Future;
33
use std::pin::Pin;
44
use std::sync::Arc;
55

6+
#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
7+
use crate::body::Body;
68
#[cfg(feature = "server")]
7-
use crate::body::{Body, HttpBody};
9+
use crate::body::HttpBody;
810
#[cfg(all(feature = "http2", feature = "server"))]
911
use crate::proto::h2::server::H2Stream;
1012
use crate::rt::Executor;
11-
#[cfg(feature = "server")]
13+
#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
1214
use crate::server::conn::spawn_all::{NewSvcTask, Watcher};
13-
#[cfg(feature = "server")]
15+
#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
1416
use crate::service::HttpService;
1517

1618
#[cfg(feature = "server")]
1719
pub trait ConnStreamExec<F, B: HttpBody>: Clone {
1820
fn execute_h2stream(&mut self, fut: H2Stream<F, B>);
1921
}
2022

21-
#[cfg(feature = "server")]
23+
#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
2224
pub trait NewSvcExec<I, N, S: HttpService<Body>, E, W: Watcher<I, S, E>>: Clone {
2325
fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>);
2426
}
@@ -76,7 +78,7 @@ where
7678
}
7779
}
7880

79-
#[cfg(feature = "server")]
81+
#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
8082
impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for Exec
8183
where
8284
NewSvcTask<I, N, S, E, W>: Future<Output = ()> + Send + 'static,
@@ -102,7 +104,7 @@ where
102104
}
103105
}
104106

105-
#[cfg(feature = "server")]
107+
#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
106108
impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for E
107109
where
108110
E: Executor<NewSvcTask<I, N, S, E, W>> + Clone,

‎src/common/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub(crate) mod buf;
1212
pub(crate) mod date;
1313
#[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
1414
pub(crate) mod drain;
15-
#[cfg(any(feature = "http1", feature = "http2"))]
15+
#[cfg(any(feature = "http1", feature = "http2", feature = "server"))]
1616
pub(crate) mod exec;
1717
pub(crate) mod io;
1818
#[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))]

‎src/error.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,7 @@ pub(super) enum Kind {
3838
#[allow(unused)]
3939
Connect,
4040
/// Error creating a TcpListener.
41-
#[cfg(all(
42-
any(feature = "http1", feature = "http2"),
43-
feature = "tcp",
44-
feature = "server"
45-
))]
41+
#[cfg(all(feature = "tcp", feature = "server"))]
4642
Listen,
4743
/// Error accepting on an Incoming stream.
4844
#[cfg(any(feature = "http1", feature = "http2"))]
@@ -265,8 +261,7 @@ impl Error {
265261
Error::new(Kind::Io).with(cause)
266262
}
267263

268-
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))]
269-
#[cfg(feature = "server")]
264+
#[cfg(all(feature = "server", feature = "tcp"))]
270265
pub(super) fn new_listen<E: Into<Cause>>(cause: E) -> Error {
271266
Error::new(Kind::Listen).with(cause)
272267
}
@@ -410,8 +405,7 @@ impl Error {
410405
Kind::ChannelClosed => "channel closed",
411406
Kind::Connect => "error trying to connect",
412407
Kind::Canceled => "operation was canceled",
413-
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "tcp"))]
414-
#[cfg(feature = "server")]
408+
#[cfg(all(feature = "server", feature = "tcp"))]
415409
Kind::Listen => "error creating server listener",
416410
#[cfg(any(feature = "http1", feature = "http2"))]
417411
#[cfg(feature = "server")]

‎src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ cfg_feature! {
104104
#![feature = "server"]
105105

106106
pub mod server;
107-
#[cfg(any(feature = "http1", feature = "http2"))]
108107
#[doc(no_inline)]
109108
pub use crate::server::Server;
110109
}

‎src/server/conn.rs

+61-23
Original file line numberDiff line numberDiff line change
@@ -43,38 +43,47 @@
4343
//! # }
4444
//! ```
4545
46-
use std::error::Error as StdError;
47-
use std::fmt;
48-
#[cfg(not(all(feature = "http1", feature = "http2")))]
46+
#[cfg(all(
47+
any(feature = "http1", feature = "http2"),
48+
not(all(feature = "http1", feature = "http2"))
49+
))]
4950
use std::marker::PhantomData;
5051
#[cfg(feature = "tcp")]
5152
use std::net::SocketAddr;
5253
#[cfg(all(feature = "runtime", feature = "http2"))]
5354
use std::time::Duration;
5455

55-
use bytes::Bytes;
56-
use pin_project_lite::pin_project;
57-
use tokio::io::{AsyncRead, AsyncWrite};
58-
use tracing::trace;
59-
60-
use super::accept::Accept;
61-
use crate::body::{Body, HttpBody};
62-
use crate::common::exec::{ConnStreamExec, Exec, NewSvcExec};
6356
#[cfg(feature = "http2")]
6457
use crate::common::io::Rewind;
65-
#[cfg(not(all(feature = "http1", feature = "http2")))]
66-
use crate::common::Never;
67-
use crate::common::{task, Future, Pin, Poll, Unpin};
6858
#[cfg(all(feature = "http1", feature = "http2"))]
6959
use crate::error::{Kind, Parse};
70-
use crate::proto;
71-
use crate::service::{HttpService, MakeServiceRef};
7260
#[cfg(feature = "http1")]
7361
use crate::upgrade::Upgraded;
7462

75-
use self::spawn_all::NewSvcTask;
76-
pub(super) use self::spawn_all::{NoopWatcher, Watcher};
77-
pub(super) use self::upgrades::UpgradeableConnection;
63+
cfg_feature! {
64+
#![any(feature = "http1", feature = "http2")]
65+
66+
use std::error::Error as StdError;
67+
use std::fmt;
68+
69+
use bytes::Bytes;
70+
use pin_project_lite::pin_project;
71+
use tokio::io::{AsyncRead, AsyncWrite};
72+
use tracing::trace;
73+
74+
use super::accept::Accept;
75+
use crate::body::{Body, HttpBody};
76+
use crate::common::{task, Future, Pin, Poll, Unpin};
77+
#[cfg(not(all(feature = "http1", feature = "http2")))]
78+
use crate::common::Never;
79+
use crate::common::exec::{ConnStreamExec, Exec, NewSvcExec};
80+
use crate::proto;
81+
use crate::service::{HttpService, MakeServiceRef};
82+
use self::spawn_all::NewSvcTask;
83+
84+
pub(super) use self::spawn_all::{NoopWatcher, Watcher};
85+
pub(super) use self::upgrades::UpgradeableConnection;
86+
}
7887

7988
#[cfg(feature = "tcp")]
8089
pub use super::tcp::{AddrIncoming, AddrStream};
@@ -86,6 +95,8 @@ pub use super::tcp::{AddrIncoming, AddrStream};
8695
/// If you don't have need to manage connections yourself, consider using the
8796
/// higher-level [Server](super) API.
8897
#[derive(Clone, Debug)]
98+
#[cfg(any(feature = "http1", feature = "http2"))]
99+
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
89100
pub struct Http<E = Exec> {
90101
exec: E,
91102
h1_half_close: bool,
@@ -100,6 +111,7 @@ pub struct Http<E = Exec> {
100111
}
101112

102113
/// The internal mode of HTTP protocol which indicates the behavior when a parse error occurs.
114+
#[cfg(any(feature = "http1", feature = "http2"))]
103115
#[derive(Clone, Debug, PartialEq)]
104116
enum ConnectionMode {
105117
/// Always use HTTP/1 and do not upgrade when a parse error occurs.
@@ -113,6 +125,7 @@ enum ConnectionMode {
113125
Fallback,
114126
}
115127

128+
#[cfg(any(feature = "http1", feature = "http2"))]
116129
pin_project! {
117130
/// A stream mapping incoming IOs to new services.
118131
///
@@ -127,13 +140,15 @@ pin_project! {
127140
}
128141
}
129142

143+
#[cfg(any(feature = "http1", feature = "http2"))]
130144
pin_project! {
131145
/// A future building a new `Service` to a `Connection`.
132146
///
133147
/// Wraps the future returned from `MakeService` into one that returns
134148
/// a `Connection`.
135149
#[must_use = "futures do nothing unless polled"]
136150
#[derive(Debug)]
151+
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
137152
pub struct Connecting<I, F, E = Exec> {
138153
#[pin]
139154
future: F,
@@ -142,6 +157,7 @@ pin_project! {
142157
}
143158
}
144159

160+
#[cfg(any(feature = "http1", feature = "http2"))]
145161
pin_project! {
146162
#[must_use = "futures do nothing unless polled"]
147163
#[derive(Debug)]
@@ -154,11 +170,13 @@ pin_project! {
154170
}
155171
}
156172

173+
#[cfg(any(feature = "http1", feature = "http2"))]
157174
pin_project! {
158175
/// A future binding a connection with a Service.
159176
///
160177
/// Polling this future will drive HTTP forward.
161178
#[must_use = "futures do nothing unless polled"]
179+
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
162180
pub struct Connection<T, S, E = Exec>
163181
where
164182
S: HttpService<Body>,
@@ -172,18 +190,19 @@ pin_project! {
172190
type Http1Dispatcher<T, B, S> =
173191
proto::h1::Dispatcher<proto::h1::dispatch::Server<S, Body>, B, T, proto::ServerTransaction>;
174192

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

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

181-
#[cfg(not(feature = "http2"))]
199+
#[cfg(all(not(feature = "http2"), feature = "http1"))]
182200
type Http2Server<T, B, S, E> = (
183201
Never,
184202
PhantomData<(T, Box<Pin<S>>, Box<Pin<B>>, Box<Pin<E>>)>,
185203
);
186204

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

212-
#[cfg(not(all(feature = "http1", feature = "http2")))]
231+
#[cfg(all(
232+
any(feature = "http1", feature = "http2"),
233+
not(all(feature = "http1", feature = "http2"))
234+
))]
213235
type Fallback<E> = PhantomData<E>;
214236

215237
#[cfg(all(feature = "http1", feature = "http2"))]
@@ -230,6 +252,8 @@ impl<E> Unpin for Fallback<E> {}
230252
/// This allows taking apart a `Connection` at a later time, in order to
231253
/// reclaim the IO object, and additional related pieces.
232254
#[derive(Debug)]
255+
#[cfg(any(feature = "http1", feature = "http2"))]
256+
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
233257
pub struct Parts<T, S> {
234258
/// The original IO object used in the handshake.
235259
pub io: T,
@@ -249,6 +273,7 @@ pub struct Parts<T, S> {
249273

250274
// ===== impl Http =====
251275

276+
#[cfg(any(feature = "http1", feature = "http2"))]
252277
impl Http {
253278
/// Creates a new instance of the HTTP protocol, ready to spawn a server or
254279
/// start accepting connections.
@@ -268,6 +293,7 @@ impl Http {
268293
}
269294
}
270295

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

634660
// ===== impl Connection =====
635661

662+
#[cfg(any(feature = "http1", feature = "http2"))]
636663
impl<I, B, S, E> Connection<I, S, E>
637664
where
638665
S: HttpService<Body, ResBody = B>,
@@ -802,6 +829,7 @@ where
802829
}
803830
}
804831

832+
#[cfg(any(feature = "http1", feature = "http2"))]
805833
impl<I, B, S, E> Future for Connection<I, S, E>
806834
where
807835
S: HttpService<Body, ResBody = B>,
@@ -848,6 +876,7 @@ where
848876
}
849877
}
850878

879+
#[cfg(any(feature = "http1", feature = "http2"))]
851880
impl<I, S> fmt::Debug for Connection<I, S>
852881
where
853882
S: HttpService<Body>,
@@ -859,6 +888,7 @@ where
859888

860889
// ===== impl ConnectionMode =====
861890

891+
#[cfg(any(feature = "http1", feature = "http2"))]
862892
impl Default for ConnectionMode {
863893
#[cfg(all(feature = "http1", feature = "http2"))]
864894
fn default() -> ConnectionMode {
@@ -878,6 +908,7 @@ impl Default for ConnectionMode {
878908

879909
// ===== impl Serve =====
880910

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

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

938970
// ===== impl Connecting =====
939971

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

959992
// ===== impl SpawnAll =====
960993

961-
#[cfg(feature = "tcp")]
994+
#[cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))]
962995
impl<S, E> SpawnAll<AddrIncoming, S, E> {
963996
pub(super) fn local_addr(&self) -> SocketAddr {
964997
self.serve.incoming.local_addr()
965998
}
966999
}
9671000

1001+
#[cfg(any(feature = "http1", feature = "http2"))]
9681002
impl<I, S, E> SpawnAll<I, S, E> {
9691003
pub(super) fn incoming_ref(&self) -> &I {
9701004
self.serve.incoming_ref()
9711005
}
9721006
}
9731007

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

10091044
// ===== impl ProtoServer =====
10101045

1046+
#[cfg(any(feature = "http1", feature = "http2"))]
10111047
impl<T, B, S, E> Future for ProtoServer<T, B, S, E>
10121048
where
10131049
T: AsyncRead + AsyncWrite + Unpin,
@@ -1034,6 +1070,7 @@ where
10341070
}
10351071
}
10361072

1073+
#[cfg(any(feature = "http1", feature = "http2"))]
10371074
pub(crate) mod spawn_all {
10381075
use std::error::Error as StdError;
10391076
use tokio::io::{AsyncRead, AsyncWrite};
@@ -1177,6 +1214,7 @@ pub(crate) mod spawn_all {
11771214
}
11781215
}
11791216

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

‎src/server/mod.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,17 @@
148148
//! [`tower::make::Shared`]: https://docs.rs/tower/latest/tower/make/struct.Shared.html
149149
150150
pub mod accept;
151+
pub mod conn;
152+
mod server;
153+
#[cfg(feature = "tcp")]
154+
mod tcp;
155+
156+
pub use self::server::Server;
151157

152158
cfg_feature! {
153159
#![any(feature = "http1", feature = "http2")]
154160

155-
pub use self::server::{Builder, Server};
161+
pub use self::server::Builder;
156162

157-
pub mod conn;
158-
mod server;
159163
mod shutdown;
160-
#[cfg(feature = "tcp")]
161-
mod tcp;
162164
}

‎src/server/server.rs

+47-21
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,33 @@
1-
use std::error::Error as StdError;
21
use std::fmt;
32
#[cfg(feature = "tcp")]
43
use std::net::{SocketAddr, TcpListener as StdTcpListener};
5-
64
#[cfg(feature = "tcp")]
75
use std::time::Duration;
86

9-
use pin_project_lite::pin_project;
10-
use tokio::io::{AsyncRead, AsyncWrite};
11-
12-
use super::accept::Accept;
13-
use crate::body::{Body, HttpBody};
14-
use crate::common::exec::{ConnStreamExec, Exec, NewSvcExec};
15-
use crate::common::{task, Future, Pin, Poll, Unpin};
16-
use crate::service::{HttpService, MakeServiceRef};
17-
// Renamed `Http` as `Http_` for now so that people upgrading don't see an
18-
// error that `hyper::server::Http` is private...
19-
use super::conn::{Http as Http_, NoopWatcher, SpawnAll};
20-
use super::shutdown::{Graceful, GracefulWatcher};
21-
#[cfg(feature = "tcp")]
7+
#[cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))]
228
use super::tcp::AddrIncoming;
9+
use crate::common::exec::Exec;
10+
11+
cfg_feature! {
12+
#![any(feature = "http1", feature = "http2")]
13+
14+
use std::error::Error as StdError;
15+
16+
use pin_project_lite::pin_project;
17+
use tokio::io::{AsyncRead, AsyncWrite};
18+
19+
use super::accept::Accept;
20+
use crate::body::{Body, HttpBody};
21+
use crate::common::{task, Future, Pin, Poll, Unpin};
22+
use crate::common::exec::{ConnStreamExec, NewSvcExec};
23+
// Renamed `Http` as `Http_` for now so that people upgrading don't see an
24+
// error that `hyper::server::Http` is private...
25+
use super::conn::{Http as Http_, NoopWatcher, SpawnAll};
26+
use super::shutdown::{Graceful, GracefulWatcher};
27+
use crate::service::{HttpService, MakeServiceRef};
28+
}
2329

30+
#[cfg(any(feature = "http1", feature = "http2"))]
2431
pin_project! {
2532
/// A listening HTTP server that accepts connections in both HTTP1 and HTTP2 by default.
2633
///
@@ -34,15 +41,27 @@ pin_project! {
3441
}
3542
}
3643

44+
/// A listening HTTP server that accepts connections in both HTTP1 and HTTP2 by default.
45+
///
46+
/// Needs at least one of the `http1` and `http2` features to be activated to actually be useful.
47+
#[cfg(not(any(feature = "http1", feature = "http2")))]
48+
pub struct Server<I, S, E = Exec> {
49+
_marker: std::marker::PhantomData<(I, S, E)>,
50+
}
51+
3752
/// A builder for a [`Server`](Server).
3853
#[derive(Debug)]
54+
#[cfg(any(feature = "http1", feature = "http2"))]
55+
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
3956
pub struct Builder<I, E = Exec> {
4057
incoming: I,
4158
protocol: Http_<E>,
4259
}
4360

4461
// ===== impl Server =====
4562

63+
#[cfg(any(feature = "http1", feature = "http2"))]
64+
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
4665
impl<I> Server<I, ()> {
4766
/// Starts a [`Builder`](Builder) with the provided incoming stream.
4867
pub fn builder(incoming: I) -> Builder<I> {
@@ -54,7 +73,7 @@ impl<I> Server<I, ()> {
5473
}
5574

5675
cfg_feature! {
57-
#![all(feature = "tcp")]
76+
#![all(feature = "tcp", any(feature = "http1", feature = "http2"))]
5877

5978
impl Server<AddrIncoming, ()> {
6079
/// Binds to the provided address, and returns a [`Builder`](Builder).
@@ -83,7 +102,7 @@ cfg_feature! {
83102
}
84103

85104
cfg_feature! {
86-
#![all(feature = "tcp")]
105+
#![all(feature = "tcp", any(feature = "http1", feature = "http2"))]
87106

88107
impl<S, E> Server<AddrIncoming, S, E> {
89108
/// Returns the local address that this server is bound to.
@@ -93,6 +112,8 @@ cfg_feature! {
93112
}
94113
}
95114

115+
#[cfg(any(feature = "http1", feature = "http2"))]
116+
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
96117
impl<I, IO, IE, S, E, B> Server<I, S, E>
97118
where
98119
I: Accept<Conn = IO, Error = IE>,
@@ -149,6 +170,8 @@ where
149170
}
150171
}
151172

173+
#[cfg(any(feature = "http1", feature = "http2"))]
174+
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
152175
impl<I, IO, IE, S, B, E> Future for Server<I, S, E>
153176
where
154177
I: Accept<Conn = IO, Error = IE>,
@@ -170,14 +193,17 @@ where
170193

171194
impl<I: fmt::Debug, S: fmt::Debug> fmt::Debug for Server<I, S> {
172195
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173-
f.debug_struct("Server")
174-
.field("listener", &self.spawn_all.incoming_ref())
175-
.finish()
196+
let mut st = f.debug_struct("Server");
197+
#[cfg(any(feature = "http1", feature = "http2"))]
198+
st.field("listener", &self.spawn_all.incoming_ref());
199+
st.finish()
176200
}
177201
}
178202

179203
// ===== impl Builder =====
180204

205+
#[cfg(any(feature = "http1", feature = "http2"))]
206+
#[cfg_attr(docsrs, doc(cfg(any(feature = "http1", feature = "http2"))))]
181207
impl<I, E> Builder<I, E> {
182208
/// Start a new builder, wrapping an incoming stream and low-level options.
183209
///
@@ -435,7 +461,7 @@ impl<I, E> Builder<I, E> {
435461
}
436462
}
437463

438-
#[cfg(feature = "tcp")]
464+
#[cfg(all(feature = "tcp", any(feature = "http1", feature = "http2")))]
439465
impl<E> Builder<AddrIncoming, E> {
440466
/// Set whether TCP keepalive messages are enabled on accepted connections.
441467
///

0 commit comments

Comments
 (0)
Please sign in to comment.