Skip to content

Commit bb3af17

Browse files
authoredAug 15, 2022
feat(client): remove higher-level hyper::Client (#2941)
This removes the following types and methods from hyper: - `Client` - `Error::is_connect()` BREAKING CHANGE: A pooling client is in the hyper-util crate.
1 parent 889fa2d commit bb3af17

File tree

14 files changed

+34
-3924
lines changed

14 files changed

+34
-3924
lines changed
 

‎src/body/body.rs

+2-91
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ use http_body::{Body as HttpBody, SizeHint};
1010

1111
use super::DecodedLength;
1212
use crate::common::Future;
13-
#[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))]
14-
use crate::common::Never;
1513
use crate::common::{task, watch, Pin, Poll};
1614
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
1715
use crate::proto::h2::ping;
@@ -29,9 +27,6 @@ type TrailersSender = oneshot::Sender<HeaderMap>;
2927
#[must_use = "streams do nothing unless polled"]
3028
pub struct Body {
3129
kind: Kind,
32-
/// Keep the extra bits in an `Option<Box<Extra>>`, so that
33-
/// Body stays small in the common case (no extras needed).
34-
extra: Option<Box<Extra>>,
3530
}
3631

3732
enum Kind {
@@ -52,34 +47,6 @@ enum Kind {
5247
Ffi(crate::ffi::UserBody),
5348
}
5449

55-
struct Extra {
56-
/// Allow the client to pass a future to delay the `Body` from returning
57-
/// EOF. This allows the `Client` to try to put the idle connection
58-
/// back into the pool before the body is "finished".
59-
///
60-
/// The reason for this is so that creating a new request after finishing
61-
/// streaming the body of a response could sometimes result in creating
62-
/// a brand new connection, since the pool didn't know about the idle
63-
/// connection yet.
64-
delayed_eof: Option<DelayEof>,
65-
}
66-
67-
#[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))]
68-
type DelayEofUntil = oneshot::Receiver<Never>;
69-
70-
enum DelayEof {
71-
/// Initial state, stream hasn't seen EOF yet.
72-
#[cfg(any(feature = "http1", feature = "http2"))]
73-
#[cfg(feature = "client")]
74-
NotEof(DelayEofUntil),
75-
/// Transitions to this state once we've seen `poll` try to
76-
/// return EOF (`None`). This future is then polled, and
77-
/// when it completes, the Body finally returns EOF (`None`).
78-
#[cfg(any(feature = "http1", feature = "http2"))]
79-
#[cfg(feature = "client")]
80-
Eof(DelayEofUntil),
81-
}
82-
8350
/// A sender half created through [`Body::channel()`].
8451
///
8552
/// Useful when wanting to stream chunks from another thread.
@@ -153,7 +120,7 @@ impl Body {
153120
}
154121

155122
fn new(kind: Kind) -> Body {
156-
Body { kind, extra: None }
123+
Body { kind }
157124
}
158125

159126
#[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
@@ -176,62 +143,6 @@ impl Body {
176143
body
177144
}
178145

179-
#[cfg(any(feature = "http1", feature = "http2"))]
180-
#[cfg(feature = "client")]
181-
pub(crate) fn delayed_eof(&mut self, fut: DelayEofUntil) {
182-
self.extra_mut().delayed_eof = Some(DelayEof::NotEof(fut));
183-
}
184-
185-
fn take_delayed_eof(&mut self) -> Option<DelayEof> {
186-
self.extra
187-
.as_mut()
188-
.and_then(|extra| extra.delayed_eof.take())
189-
}
190-
191-
#[cfg(any(feature = "http1", feature = "http2"))]
192-
fn extra_mut(&mut self) -> &mut Extra {
193-
self.extra
194-
.get_or_insert_with(|| Box::new(Extra { delayed_eof: None }))
195-
}
196-
197-
fn poll_eof(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<crate::Result<Bytes>>> {
198-
match self.take_delayed_eof() {
199-
#[cfg(any(feature = "http1", feature = "http2"))]
200-
#[cfg(feature = "client")]
201-
Some(DelayEof::NotEof(mut delay)) => match self.poll_inner(cx) {
202-
ok @ Poll::Ready(Some(Ok(..))) | ok @ Poll::Pending => {
203-
self.extra_mut().delayed_eof = Some(DelayEof::NotEof(delay));
204-
ok
205-
}
206-
Poll::Ready(None) => match Pin::new(&mut delay).poll(cx) {
207-
Poll::Ready(Ok(never)) => match never {},
208-
Poll::Pending => {
209-
self.extra_mut().delayed_eof = Some(DelayEof::Eof(delay));
210-
Poll::Pending
211-
}
212-
Poll::Ready(Err(_done)) => Poll::Ready(None),
213-
},
214-
Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
215-
},
216-
#[cfg(any(feature = "http1", feature = "http2"))]
217-
#[cfg(feature = "client")]
218-
Some(DelayEof::Eof(mut delay)) => match Pin::new(&mut delay).poll(cx) {
219-
Poll::Ready(Ok(never)) => match never {},
220-
Poll::Pending => {
221-
self.extra_mut().delayed_eof = Some(DelayEof::Eof(delay));
222-
Poll::Pending
223-
}
224-
Poll::Ready(Err(_done)) => Poll::Ready(None),
225-
},
226-
#[cfg(any(
227-
not(any(feature = "http1", feature = "http2")),
228-
not(feature = "client")
229-
))]
230-
Some(delay_eof) => match delay_eof {},
231-
None => self.poll_inner(cx),
232-
}
233-
}
234-
235146
#[cfg(feature = "ffi")]
236147
pub(crate) fn as_ffi_mut(&mut self) -> &mut crate::ffi::UserBody {
237148
match self.kind {
@@ -313,7 +224,7 @@ impl HttpBody for Body {
313224
mut self: Pin<&mut Self>,
314225
cx: &mut task::Context<'_>,
315226
) -> Poll<Option<Result<Self::Data, Self::Error>>> {
316-
self.poll_eof(cx)
227+
self.poll_inner(cx)
317228
}
318229

319230
fn poll_trailers(

‎src/client/client.rs

-1,356
This file was deleted.

‎src/client/conn/http2.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use super::super::dispatch;
2222

2323
/// The sender side of an established connection.
2424
pub struct SendRequest<B> {
25-
dispatch: dispatch::Sender<Request<B>, Response<Body>>,
25+
dispatch: dispatch::UnboundedSender<Request<B>, Response<Body>>,
2626
}
2727

2828
/// A future that processes all HTTP state for the IO object.
@@ -66,8 +66,12 @@ impl<B> SendRequest<B> {
6666
/// Polls to determine whether this sender can be used yet for a request.
6767
///
6868
/// If the associated connection is closed, this returns an Error.
69-
pub fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> {
70-
self.dispatch.poll_ready(cx)
69+
pub fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> {
70+
if self.is_closed() {
71+
Poll::Ready(Err(crate::Error::new_closed()))
72+
} else {
73+
Poll::Ready(Ok(()))
74+
}
7175
}
7276

7377
/*
@@ -83,11 +87,11 @@ impl<B> SendRequest<B> {
8387
pub(super) fn is_ready(&self) -> bool {
8488
self.dispatch.is_ready()
8589
}
90+
*/
8691

8792
pub(super) fn is_closed(&self) -> bool {
8893
self.dispatch.is_closed()
8994
}
90-
*/
9195
}
9296

9397
impl<B> SendRequest<B>
@@ -423,7 +427,7 @@ impl Builder {
423427
proto::h2::client::handshake(io, rx, &opts.h2_builder, opts.exec)
424428
.await?;
425429
Ok((
426-
SendRequest { dispatch: tx },
430+
SendRequest { dispatch: tx.unbound() },
427431
Connection { inner: (PhantomData, h2) },
428432
))
429433
}

‎src/client/conn/mod.rs

+1-122
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ use std::sync::Arc;
6363
use std::time::Duration;
6464

6565
use bytes::Bytes;
66-
use futures_util::future::{self, Either, FutureExt as _};
66+
use futures_util::future;
6767
use httparse::ParserConfig;
6868
use pin_project_lite::pin_project;
6969
use tokio::io::{AsyncRead, AsyncWrite};
@@ -214,16 +214,6 @@ pub struct Parts<T> {
214214
_inner: (),
215215
}
216216

217-
// ========== internal client api
218-
219-
// A `SendRequest` that can be cloned to send HTTP2 requests.
220-
// private for now, probably not a great idea of a type...
221-
#[must_use = "futures do nothing unless polled"]
222-
#[cfg(feature = "http2")]
223-
pub(super) struct Http2SendRequest<B> {
224-
dispatch: dispatch::UnboundedSender<Request<B>, Response<Body>>,
225-
}
226-
227217
// ===== impl SendRequest
228218

229219
impl<B> SendRequest<B> {
@@ -233,30 +223,6 @@ impl<B> SendRequest<B> {
233223
pub fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<crate::Result<()>> {
234224
self.dispatch.poll_ready(cx)
235225
}
236-
237-
pub(super) async fn when_ready(self) -> crate::Result<Self> {
238-
let mut me = Some(self);
239-
future::poll_fn(move |cx| {
240-
ready!(me.as_mut().unwrap().poll_ready(cx))?;
241-
Poll::Ready(Ok(me.take().unwrap()))
242-
})
243-
.await
244-
}
245-
246-
pub(super) fn is_ready(&self) -> bool {
247-
self.dispatch.is_ready()
248-
}
249-
250-
pub(super) fn is_closed(&self) -> bool {
251-
self.dispatch.is_closed()
252-
}
253-
254-
#[cfg(feature = "http2")]
255-
pub(super) fn into_http2(self) -> Http2SendRequest<B> {
256-
Http2SendRequest {
257-
dispatch: self.dispatch.unbound(),
258-
}
259-
}
260226
}
261227

262228
impl<B> SendRequest<B>
@@ -316,32 +282,6 @@ where
316282

317283
ResponseFuture { inner }
318284
}
319-
320-
pub(super) fn send_request_retryable(
321-
&mut self,
322-
req: Request<B>,
323-
) -> impl Future<Output = Result<Response<Body>, (crate::Error, Option<Request<B>>)>> + Unpin
324-
where
325-
B: Send,
326-
{
327-
match self.dispatch.try_send(req) {
328-
Ok(rx) => {
329-
Either::Left(rx.then(move |res| {
330-
match res {
331-
Ok(Ok(res)) => future::ok(res),
332-
Ok(Err(err)) => future::err(err),
333-
// this is definite bug if it happens, but it shouldn't happen!
334-
Err(_) => panic!("dispatch dropped without returning error"),
335-
}
336-
}))
337-
}
338-
Err(req) => {
339-
debug!("connection was not ready");
340-
let err = crate::Error::new_canceled().with("connection was not ready");
341-
Either::Right(future::err((err, Some(req))))
342-
}
343-
}
344-
}
345285
}
346286

347287
impl<B> Service<Request<B>> for SendRequest<B>
@@ -367,67 +307,6 @@ impl<B> fmt::Debug for SendRequest<B> {
367307
}
368308
}
369309

370-
// ===== impl Http2SendRequest
371-
372-
#[cfg(feature = "http2")]
373-
impl<B> Http2SendRequest<B> {
374-
pub(super) fn is_ready(&self) -> bool {
375-
self.dispatch.is_ready()
376-
}
377-
378-
pub(super) fn is_closed(&self) -> bool {
379-
self.dispatch.is_closed()
380-
}
381-
}
382-
383-
#[cfg(feature = "http2")]
384-
impl<B> Http2SendRequest<B>
385-
where
386-
B: HttpBody + 'static,
387-
{
388-
pub(super) fn send_request_retryable(
389-
&mut self,
390-
req: Request<B>,
391-
) -> impl Future<Output = Result<Response<Body>, (crate::Error, Option<Request<B>>)>>
392-
where
393-
B: Send,
394-
{
395-
match self.dispatch.try_send(req) {
396-
Ok(rx) => {
397-
Either::Left(rx.then(move |res| {
398-
match res {
399-
Ok(Ok(res)) => future::ok(res),
400-
Ok(Err(err)) => future::err(err),
401-
// this is definite bug if it happens, but it shouldn't happen!
402-
Err(_) => panic!("dispatch dropped without returning error"),
403-
}
404-
}))
405-
}
406-
Err(req) => {
407-
debug!("connection was not ready");
408-
let err = crate::Error::new_canceled().with("connection was not ready");
409-
Either::Right(future::err((err, Some(req))))
410-
}
411-
}
412-
}
413-
}
414-
415-
#[cfg(feature = "http2")]
416-
impl<B> fmt::Debug for Http2SendRequest<B> {
417-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
418-
f.debug_struct("Http2SendRequest").finish()
419-
}
420-
}
421-
422-
#[cfg(feature = "http2")]
423-
impl<B> Clone for Http2SendRequest<B> {
424-
fn clone(&self) -> Self {
425-
Http2SendRequest {
426-
dispatch: self.dispatch.clone(),
427-
}
428-
}
429-
}
430-
431310
// ===== impl Connection
432311

433312
impl<T, B> Connection<T, B>

‎src/client/connect/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ impl Connected {
166166
self.alpn == Alpn::H2
167167
}
168168

169+
/*
169170
// Don't public expose that `Connected` is `Clone`, unsure if we want to
170171
// keep that contract...
171172
#[cfg(feature = "http2")]
@@ -176,6 +177,7 @@ impl Connected {
176177
extra: self.extra.clone(),
177178
}
178179
}
180+
*/
179181
}
180182

181183
// ===== impl Extra =====

‎src/client/dispatch.rs

+17
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use tokio::sync::{mpsc, oneshot};
77
use crate::common::Pin;
88
use crate::common::{task, Poll};
99

10+
#[cfg(test)]
1011
pub(crate) type RetryPromise<T, U> = oneshot::Receiver<Result<U, (crate::Error, Option<T>)>>;
1112
pub(crate) type Promise<T> = oneshot::Receiver<Result<T, crate::Error>>;
1213

@@ -58,13 +59,16 @@ impl<T, U> Sender<T, U> {
5859
.map_err(|_| crate::Error::new_closed())
5960
}
6061

62+
#[cfg(test)]
6163
pub(crate) fn is_ready(&self) -> bool {
6264
self.giver.is_wanting()
6365
}
6466

67+
/*
6568
pub(crate) fn is_closed(&self) -> bool {
6669
self.giver.is_canceled()
6770
}
71+
*/
6872

6973
fn can_send(&mut self) -> bool {
7074
if self.giver.give() || !self.buffered_once {
@@ -79,6 +83,7 @@ impl<T, U> Sender<T, U> {
7983
}
8084
}
8185

86+
#[cfg(test)]
8287
pub(crate) fn try_send(&mut self, val: T) -> Result<RetryPromise<T, U>, T> {
8388
if !self.can_send() {
8489
return Err(val);
@@ -112,21 +117,32 @@ impl<T, U> Sender<T, U> {
112117

113118
#[cfg(feature = "http2")]
114119
impl<T, U> UnboundedSender<T, U> {
120+
/*
115121
pub(crate) fn is_ready(&self) -> bool {
116122
!self.giver.is_canceled()
117123
}
124+
*/
118125

119126
pub(crate) fn is_closed(&self) -> bool {
120127
self.giver.is_canceled()
121128
}
122129

130+
#[cfg(test)]
123131
pub(crate) fn try_send(&mut self, val: T) -> Result<RetryPromise<T, U>, T> {
124132
let (tx, rx) = oneshot::channel();
125133
self.inner
126134
.send(Envelope(Some((val, Callback::Retry(tx)))))
127135
.map(move |_| rx)
128136
.map_err(|mut e| (e.0).0.take().expect("envelope not dropped").0)
129137
}
138+
139+
pub(crate) fn send(&mut self, val: T) -> Result<Promise<U>, T> {
140+
let (tx, rx) = oneshot::channel();
141+
self.inner
142+
.send(Envelope(Some((val, Callback::NoRetry(tx)))))
143+
.map(move |_| rx)
144+
.map_err(|mut e| (e.0).0.take().expect("envelope not dropped").0)
145+
}
130146
}
131147

132148
#[cfg(feature = "http2")]
@@ -198,6 +214,7 @@ impl<T, U> Drop for Envelope<T, U> {
198214
}
199215

200216
pub(crate) enum Callback<T, U> {
217+
#[allow(unused)]
201218
Retry(oneshot::Sender<Result<U, (crate::Error, Option<T>)>>),
202219
NoRetry(oneshot::Sender<Result<U, crate::Error>>),
203220
}

‎src/client/mod.rs

+1-25
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,11 @@
11
//! HTTP Client
22
//!
3-
//! There are two levels of APIs provided for construct HTTP clients:
4-
//!
5-
//! - The higher-level [`Client`](Client) type.
6-
//! - The lower-level [`conn`](conn) module.
7-
//!
8-
//! # Client
9-
//!
10-
//! The [`Client`](Client) is the main way to send HTTP requests to a server.
11-
//! The default `Client` provides these things on top of the lower-level API:
12-
//!
13-
//! - A default **connector**, able to resolve hostnames and connect to
14-
//! destinations over plain-text TCP.
15-
//! - A **pool** of existing connections, allowing better performance when
16-
//! making multiple requests to the same hostname.
17-
//! - Automatic setting of the `Host` header, based on the request `Uri`.
18-
//! - Automatic request **retries** when a pooled connection is closed by the
19-
//! server before any bytes have been written.
20-
//!
21-
//! Many of these features can configured, by making use of
22-
//! [`Client::builder`](Client::builder).
3+
//! hyper provides HTTP over a single connection. See the [`conn`](conn) module.
234
//!
245
//! ## Example
256
//!
267
//! For a small example program simply fetching a URL, take a look at the
278
//! [full client example](https://github.com/hyperium/hyper/blob/master/examples/client.rs).
28-
//!
299
3010
pub mod connect;
3111
#[cfg(all(test, feature = "runtime"))]
@@ -34,10 +14,6 @@ mod tests;
3414
cfg_feature! {
3515
#![any(feature = "http1", feature = "http2")]
3616

37-
pub use self::client::{Builder, Client, ResponseFuture};
38-
39-
mod client;
4017
pub mod conn;
4118
pub(super) mod dispatch;
42-
mod pool;
4319
}

‎src/client/pool.rs

-1,044
This file was deleted.

‎src/common/lazy.rs

-76
This file was deleted.

‎src/common/mod.rs

-6
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,10 @@ pub(crate) mod date;
1313
#[cfg(any(feature = "http1", feature = "http2", feature = "server"))]
1414
pub(crate) mod exec;
1515
pub(crate) mod io;
16-
#[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))]
17-
mod lazy;
1816
mod never;
19-
#[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))]
20-
pub(crate) mod sync_wrapper;
2117
pub(crate) mod task;
2218
pub(crate) mod watch;
2319

24-
#[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))]
25-
pub(crate) use self::lazy::{lazy, Started as Lazy};
2620
#[cfg(any(feature = "http1", feature = "http2", feature = "runtime"))]
2721
pub(crate) use self::never::Never;
2822
pub(crate) use self::task::Poll;

‎src/common/sync_wrapper.rs

-110
This file was deleted.

‎src/error.rs

-54
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ pub(super) enum Kind {
3434
/// An `io::Error` that occurred while trying to read or write to a network stream.
3535
#[cfg(any(feature = "http1", feature = "http2"))]
3636
Io,
37-
/// Error occurred while connecting.
38-
#[allow(unused)]
39-
Connect,
4037
/// Error creating a TcpListener.
4138
#[cfg(all(feature = "tcp", feature = "server"))]
4239
Listen,
@@ -101,22 +98,10 @@ pub(super) enum User {
10198
#[cfg(any(feature = "http1", feature = "http2"))]
10299
#[cfg(feature = "server")]
103100
UnexpectedHeader,
104-
/// User tried to create a Request with bad version.
105-
#[cfg(any(feature = "http1", feature = "http2"))]
106-
#[cfg(feature = "client")]
107-
UnsupportedVersion,
108-
/// User tried to create a CONNECT Request with the Client.
109-
#[cfg(any(feature = "http1", feature = "http2"))]
110-
#[cfg(feature = "client")]
111-
UnsupportedRequestMethod,
112101
/// User tried to respond with a 1xx (not 101) response code.
113102
#[cfg(feature = "http1")]
114103
#[cfg(feature = "server")]
115104
UnsupportedStatusCode,
116-
/// User tried to send a Request with Client with non-absolute URI.
117-
#[cfg(any(feature = "http1", feature = "http2"))]
118-
#[cfg(feature = "client")]
119-
AbsoluteUriRequired,
120105

121106
/// User tried polling for an upgrade that doesn't exist.
122107
NoUpgrade,
@@ -173,11 +158,6 @@ impl Error {
173158
matches!(self.inner.kind, Kind::ChannelClosed)
174159
}
175160

176-
/// Returns true if this was an error from `Connect`.
177-
pub fn is_connect(&self) -> bool {
178-
matches!(self.inner.kind, Kind::Connect)
179-
}
180-
181161
/// Returns true if the connection closed before a message could complete.
182162
pub fn is_incomplete_message(&self) -> bool {
183163
matches!(self.inner.kind, Kind::IncompleteMessage)
@@ -270,12 +250,6 @@ impl Error {
270250
Error::new(Kind::Listen).with(cause)
271251
}
272252

273-
#[cfg(any(feature = "http1", feature = "http2"))]
274-
#[cfg(feature = "client")]
275-
pub(super) fn new_connect<E: Into<Cause>>(cause: E) -> Error {
276-
Error::new(Kind::Connect).with(cause)
277-
}
278-
279253
pub(super) fn new_closed() -> Error {
280254
Error::new(Kind::ChannelClosed)
281255
}
@@ -309,30 +283,12 @@ impl Error {
309283
Error::new(Kind::HeaderTimeout)
310284
}
311285

312-
#[cfg(any(feature = "http1", feature = "http2"))]
313-
#[cfg(feature = "client")]
314-
pub(super) fn new_user_unsupported_version() -> Error {
315-
Error::new_user(User::UnsupportedVersion)
316-
}
317-
318-
#[cfg(any(feature = "http1", feature = "http2"))]
319-
#[cfg(feature = "client")]
320-
pub(super) fn new_user_unsupported_request_method() -> Error {
321-
Error::new_user(User::UnsupportedRequestMethod)
322-
}
323-
324286
#[cfg(feature = "http1")]
325287
#[cfg(feature = "server")]
326288
pub(super) fn new_user_unsupported_status_code() -> Error {
327289
Error::new_user(User::UnsupportedStatusCode)
328290
}
329291

330-
#[cfg(any(feature = "http1", feature = "http2"))]
331-
#[cfg(feature = "client")]
332-
pub(super) fn new_user_absolute_uri_required() -> Error {
333-
Error::new_user(User::AbsoluteUriRequired)
334-
}
335-
336292
pub(super) fn new_user_no_upgrade() -> Error {
337293
Error::new_user(User::NoUpgrade)
338294
}
@@ -411,7 +367,6 @@ impl Error {
411367
#[cfg(feature = "http1")]
412368
Kind::UnexpectedMessage => "received unexpected message from connection",
413369
Kind::ChannelClosed => "channel closed",
414-
Kind::Connect => "error trying to connect",
415370
Kind::Canceled => "operation was canceled",
416371
#[cfg(all(feature = "server", feature = "tcp"))]
417372
Kind::Listen => "error creating server listener",
@@ -436,20 +391,11 @@ impl Error {
436391
#[cfg(any(feature = "http1", feature = "http2"))]
437392
#[cfg(feature = "server")]
438393
Kind::User(User::UnexpectedHeader) => "user sent unexpected header",
439-
#[cfg(any(feature = "http1", feature = "http2"))]
440-
#[cfg(feature = "client")]
441-
Kind::User(User::UnsupportedVersion) => "request has unsupported HTTP version",
442-
#[cfg(any(feature = "http1", feature = "http2"))]
443-
#[cfg(feature = "client")]
444-
Kind::User(User::UnsupportedRequestMethod) => "request has unsupported HTTP method",
445394
#[cfg(feature = "http1")]
446395
#[cfg(feature = "server")]
447396
Kind::User(User::UnsupportedStatusCode) => {
448397
"response has 1xx status code, not supported by server"
449398
}
450-
#[cfg(any(feature = "http1", feature = "http2"))]
451-
#[cfg(feature = "client")]
452-
Kind::User(User::AbsoluteUriRequired) => "client requires absolute-form URIs",
453399
Kind::User(User::NoUpgrade) => "no upgrade available",
454400
#[cfg(feature = "http1")]
455401
Kind::User(User::ManualUpgrade) => "upgrade expected but low level API in use",

‎src/lib.rs

-3
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,6 @@ cfg_feature! {
9393
#![feature = "client"]
9494

9595
pub mod client;
96-
#[cfg(any(feature = "http1", feature = "http2"))]
97-
#[doc(no_inline)]
98-
pub use crate::client::Client;
9996
}
10097

10198
cfg_feature! {

‎tests/client.rs

+2-1,032
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.