Skip to content

Commit b10c479

Browse files
authored
feat(conn): Generic over executor and update docs (#257)
1 parent c5594c1 commit b10c479

File tree

2 files changed

+126
-22
lines changed

2 files changed

+126
-22
lines changed

src/client/conn.rs

Lines changed: 125 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
//! todo
1+
//! Tower layers and services for HTTP/1 and HTTP/2 client connections.
2+
//!
3+
//! This module provides Tower-compatible layers that wrap Hyper's low-level
4+
//! HTTP client connection types, making them easier to compose with other
5+
//! middleware and connection pooling strategies.
26
37
use std::future::Future;
48
use std::marker::PhantomData;
@@ -12,14 +16,39 @@ use crate::common::future::poll_fn;
1216

1317
type BoxError = Box<dyn std::error::Error + Send + Sync>;
1418

15-
/// todo
19+
/// A Tower [`Layer`](tower_layer::Layer) for creating HTTP/1 client connections.
20+
///
21+
/// This layer wraps a connection service (typically a TCP or TLS connector) and
22+
/// performs the HTTP/1 handshake, producing an [`Http1ClientService`] that can
23+
/// send requests.
24+
///
25+
/// Use [`http1()`] to create a layer with default settings, or construct from
26+
/// a [`hyper::client::conn::http1::Builder`] for custom configuration.
27+
///
28+
/// # Example
29+
///
30+
/// ```ignore
31+
/// use hyper_util::client::conn::http1;
32+
/// use hyper::{client::connect::HttpConnector, body::Bytes};
33+
/// use tower:: ServiceBuilder;
34+
/// use http_body_util::Empty;
35+
///
36+
/// let connector = HttpConnector::new();
37+
/// let layer: Http1Layer<Empty<Bytes>> = http1();
38+
/// let client = ServiceBuilder::new()
39+
/// .layer(layer)
40+
/// .service(connector);
41+
/// ```
1642
#[cfg(feature = "http1")]
1743
pub struct Http1Layer<B> {
1844
builder: hyper::client::conn::http1::Builder,
1945
_body: PhantomData<fn(B)>,
2046
}
2147

22-
/// todo
48+
/// Creates an [`Http1Layer`] with default HTTP/1 settings.
49+
///
50+
/// For custom settings, construct an [`Http1Layer`] from a
51+
/// [`hyper::client::conn::http1::Builder`] using `.into()`.
2352
#[cfg(feature = "http1")]
2453
pub fn http1<B>() -> Http1Layer<B> {
2554
Http1Layer {
@@ -60,7 +89,11 @@ impl<B> From<hyper::client::conn::http1::Builder> for Http1Layer<B> {
6089
}
6190
}
6291

63-
/// todo
92+
/// A Tower [`Service`] that establishes HTTP/1 connections.
93+
///
94+
/// This service wraps an underlying connection service (e.g., TCP or TLS) and
95+
/// performs the HTTP/1 handshake when called. The resulting service can be used
96+
/// to send HTTP requests over the established connection.
6497
#[cfg(feature = "http1")]
6598
pub struct Http1Connect<M, B> {
6699
inner: M,
@@ -118,21 +151,56 @@ impl<M: Clone, B> Clone for Http1Connect<M, B> {
118151
}
119152
}
120153

121-
/// todo
154+
/// A Tower [`Layer`](tower_layer::Layer) for creating HTTP/2 client connections.
155+
///
156+
/// This layer wraps a connection service (typically a TCP or TLS connector) and
157+
/// performs the HTTP/2 handshake, producing an [`Http2ClientService`] that can
158+
/// send requests.
159+
///
160+
/// Use [`http2()`] to create a layer with a specific executor, or construct from
161+
/// a [`hyper::client::conn::http2::Builder`] for custom configuration.
162+
///
163+
/// # Example
164+
///
165+
/// ```ignore
166+
/// use hyper_util::client::conn::http2;
167+
/// use hyper::{client::connect::HttpConnector, body::Bytes};
168+
/// use tower:: ServiceBuilder;
169+
/// use http_body_util::Empty;
170+
///
171+
/// let connector = HttpConnector::new();
172+
/// let layer: Http2Layer<Empty<Bytes>> = http2();
173+
/// let client = ServiceBuilder::new()
174+
/// .layer(layer)
175+
/// .service(connector);
176+
/// ```
122177
#[cfg(feature = "http2")]
123-
pub struct Http2Layer<B> {
178+
pub struct Http2Layer<B, E> {
179+
builder: hyper::client::conn::http2::Builder<E>,
124180
_body: PhantomData<fn(B)>,
125181
}
126182

127-
/// todo
183+
/// Creates an [`Http2Layer`] with default HTTP/1 settings.
184+
///
185+
/// For custom settings, construct an [`Http2Layer`] from a
186+
/// [`hyper::client::conn::http2::Builder`] using `.into()`.
128187
#[cfg(feature = "http2")]
129-
pub fn http2<B>() -> Http2Layer<B> {
130-
Http2Layer { _body: PhantomData }
188+
pub fn http2<B, E>(executor: E) -> Http2Layer<B, E>
189+
where
190+
E: Clone,
191+
{
192+
Http2Layer {
193+
builder: hyper::client::conn::http2::Builder::new(executor),
194+
_body: PhantomData,
195+
}
131196
}
132197

133198
#[cfg(feature = "http2")]
134-
impl<M, B> tower_layer::Layer<M> for Http2Layer<B> {
135-
type Service = Http2Connect<M, B>;
199+
impl<M, B, E> tower_layer::Layer<M> for Http2Layer<B, E>
200+
where
201+
E: Clone,
202+
{
203+
type Service = Http2Connect<M, B, E>;
136204
fn layer(&self, inner: M) -> Self::Service {
137205
Http2Connect {
138206
inner,
@@ -143,25 +211,40 @@ impl<M, B> tower_layer::Layer<M> for Http2Layer<B> {
143211
}
144212

145213
#[cfg(feature = "http2")]
146-
impl<B> Clone for Http2Layer<B> {
214+
impl<B, E: Clone> Clone for Http2Layer<B, E> {
147215
fn clone(&self) -> Self {
148216
Self {
217+
builder: self.builder.clone(),
149218
_body: self._body.clone(),
150219
}
151220
}
152221
}
153222

154-
/// todo
223+
#[cfg(feature = "http2")]
224+
impl<B, E> From<hyper::client::conn::http2::Builder<E>> for Http2Layer<B, E> {
225+
fn from(builder: hyper::client::conn::http2::Builder<E>) -> Self {
226+
Self {
227+
builder,
228+
_body: PhantomData,
229+
}
230+
}
231+
}
232+
233+
/// A Tower [`Service`] that establishes HTTP/2 connections.
234+
///
235+
/// This service wraps an underlying connection service (e.g., TCP or TLS) and
236+
/// performs the HTTP/2 handshake when called. The resulting service can be used
237+
/// to send HTTP requests over the established connection.
155238
#[cfg(feature = "http2")]
156239
#[derive(Debug)]
157-
pub struct Http2Connect<M, B> {
240+
pub struct Http2Connect<M, B, E> {
158241
inner: M,
159-
builder: hyper::client::conn::http2::Builder<crate::rt::TokioExecutor>,
242+
builder: hyper::client::conn::http2::Builder<E>,
160243
_body: PhantomData<fn(B)>,
161244
}
162245

163246
#[cfg(feature = "http2")]
164-
impl<M, Dst, B> Service<Dst> for Http2Connect<M, B>
247+
impl<M, Dst, B, E> Service<Dst> for Http2Connect<M, B, E>
165248
where
166249
M: Service<Dst>,
167250
M::Future: Send + 'static,
@@ -170,6 +253,7 @@ where
170253
B: hyper::body::Body + Unpin + Send + 'static,
171254
B::Data: Send + 'static,
172255
B::Error: Into<BoxError>,
256+
E: hyper::rt::bounds::Http2ClientConnExec<B, M::Response> + Unpin + Clone + Send + 'static,
173257
{
174258
type Response = Http2ClientService<B>;
175259
type Error = BoxError;
@@ -199,7 +283,7 @@ where
199283
}
200284

201285
#[cfg(feature = "http2")]
202-
impl<M: Clone, B> Clone for Http2Connect<M, B> {
286+
impl<M: Clone, B, E: Clone> Clone for Http2Connect<M, B, E> {
203287
fn clone(&self) -> Self {
204288
Self {
205289
inner: self.inner.clone(),
@@ -209,7 +293,14 @@ impl<M: Clone, B> Clone for Http2Connect<M, B> {
209293
}
210294
}
211295

212-
/// A thin adapter over hyper HTTP/1 client SendRequest.
296+
/// A Tower [`Service`] that sends HTTP/1 requests over an established connection.
297+
///
298+
/// This is a thin wrapper around [`hyper::client::conn::http1::SendRequest`] that implements
299+
/// the Tower `Service` trait, making it composable with other Tower middleware.
300+
///
301+
/// The service maintains a single HTTP/1 connection and can be used to send multiple
302+
/// sequential requests. For concurrent requests or connection pooling, wrap this service
303+
/// with appropriate middleware.
213304
#[cfg(feature = "http1")]
214305
#[derive(Debug)]
215306
pub struct Http1ClientService<B> {
@@ -218,7 +309,10 @@ pub struct Http1ClientService<B> {
218309

219310
#[cfg(feature = "http1")]
220311
impl<B> Http1ClientService<B> {
221-
/// todo
312+
/// Constructs a new HTTP/1 client service from a Hyper `SendRequest`.
313+
///
314+
/// Typically you won't call this directly; instead, use [`Http1Connect`] to
315+
/// establish connections and produce this service.
222316
pub fn new(tx: hyper::client::conn::http1::SendRequest<B>) -> Self {
223317
Self { tx }
224318
}
@@ -248,7 +342,14 @@ where
248342
}
249343
}
250344

251-
/// todo
345+
/// A Tower [`Service`] that sends HTTP/2 requests over an established connection.
346+
///
347+
/// This is a thin wrapper around [`hyper::client::conn::http2::SendRequest`] that implements
348+
/// the Tower `Service` trait, making it composable with other Tower middleware.
349+
///
350+
/// The service maintains a single HTTP/2 connection and supports multiplexing multiple
351+
/// concurrent requests over that connection. The service can be cloned to send requests
352+
/// concurrently, or used with the [`Singleton`](crate::client::pool::singleton::Singleton) pool service.
252353
#[cfg(feature = "http2")]
253354
#[derive(Debug)]
254355
pub struct Http2ClientService<B> {
@@ -257,7 +358,10 @@ pub struct Http2ClientService<B> {
257358

258359
#[cfg(feature = "http2")]
259360
impl<B> Http2ClientService<B> {
260-
/// todo
361+
/// Constructs a new HTTP/2 client service from a Hyper `SendRequest`.
362+
///
363+
/// Typically you won't call this directly; instead, use [`Http2Connect`] to
364+
/// establish connections and produce this service.
261365
pub fn new(tx: hyper::client::conn::http2::SendRequest<B>) -> Self {
262366
Self { tx }
263367
}

src/client/pool/map.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ where
4848
// impl Map
4949

5050
impl Map<builder::StartHere, builder::StartHere> {
51-
/// Create a [`Builder`] to configure a new `Map`.
51+
/// Create a `Builder` to configure a new `Map`.
5252
pub fn builder<Dst>() -> builder::Builder<Dst, builder::WantsKeyer, builder::WantsServiceMaker>
5353
{
5454
builder::Builder::new()

0 commit comments

Comments
 (0)