feat(client): remove hyper::client::server (#2940)
BREAKING CHANGE: Tower `Service` utilities will exist in `hyper-util`.
This commit is contained in:
@@ -181,11 +181,6 @@ name = "state"
|
||||
path = "examples/state.rs"
|
||||
required-features = ["full"]
|
||||
|
||||
[[example]]
|
||||
name = "tower_client"
|
||||
path = "examples/tower_client.rs"
|
||||
required-features = ["full"]
|
||||
|
||||
[[example]]
|
||||
name = "tower_server"
|
||||
path = "examples/tower_server.rs"
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use hyper::service::Service;
|
||||
use hyper::{Body, Request, Response};
|
||||
use tokio::net::TcpStream;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
|
||||
pretty_env_logger::init();
|
||||
|
||||
let uri = "http://127.0.0.1:8080".parse::<http::Uri>()?;
|
||||
|
||||
let mut svc = Connector;
|
||||
|
||||
let body = Body::empty();
|
||||
|
||||
let req = Request::get(uri).body(body)?;
|
||||
let res = svc.call(req).await?;
|
||||
|
||||
println!("RESPONSE={:?}", res);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct Connector;
|
||||
|
||||
impl Service<Request<Body>> for Connector {
|
||||
type Response = Response<Body>;
|
||||
type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
|
||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
|
||||
|
||||
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> std::task::Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: Request<Body>) -> Self::Future {
|
||||
Box::pin(async move {
|
||||
let host = req.uri().host().expect("no host in uri");
|
||||
let port = req.uri().port_u16().expect("no port in uri");
|
||||
|
||||
let stream = TcpStream::connect(format!("{}:{}", host, port)).await?;
|
||||
|
||||
let (mut sender, conn) = hyper::client::conn::handshake(stream).await?;
|
||||
|
||||
tokio::task::spawn(async move {
|
||||
if let Err(err) = conn.await {
|
||||
println!("Connection error: {:?}", err);
|
||||
}
|
||||
});
|
||||
|
||||
let res = sender.send_request(req).await?;
|
||||
Ok(res)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -40,5 +40,4 @@ cfg_feature! {
|
||||
pub mod conn;
|
||||
pub(super) mod dispatch;
|
||||
mod pool;
|
||||
pub mod service;
|
||||
}
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
//! Utilities used to interact with the Tower ecosystem.
|
||||
//!
|
||||
//! This module provides `Connect` which hook-ins into the Tower ecosystem.
|
||||
|
||||
use std::error::Error as StdError;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use tracing::debug;
|
||||
|
||||
use super::conn::{Builder, SendRequest};
|
||||
use crate::{
|
||||
body::HttpBody,
|
||||
common::{task, Pin, Poll},
|
||||
service::{MakeConnection, Service},
|
||||
};
|
||||
|
||||
/// Creates a connection via `SendRequest`.
|
||||
///
|
||||
/// This accepts a `hyper::client::conn::Builder` and provides
|
||||
/// a `MakeService` implementation to create connections from some
|
||||
/// target `T`.
|
||||
#[derive(Debug)]
|
||||
pub struct Connect<C, B, T> {
|
||||
inner: C,
|
||||
builder: Builder,
|
||||
_pd: PhantomData<fn(T, B)>,
|
||||
}
|
||||
|
||||
impl<C, B, T> Connect<C, B, T> {
|
||||
/// Create a new `Connect` with some inner connector `C` and a connection
|
||||
/// builder.
|
||||
pub fn new(inner: C, builder: Builder) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
builder,
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, B, T> Service<T> for Connect<C, B, T>
|
||||
where
|
||||
C: MakeConnection<T>,
|
||||
C::Connection: Unpin + Send + 'static,
|
||||
C::Future: Send + 'static,
|
||||
C::Error: Into<Box<dyn StdError + Send + Sync>> + Send,
|
||||
B: HttpBody + Unpin + Send + 'static,
|
||||
B::Data: Send + Unpin,
|
||||
B::Error: Into<Box<dyn StdError + Send + Sync>>,
|
||||
{
|
||||
type Response = SendRequest<B>;
|
||||
type Error = crate::Error;
|
||||
type Future =
|
||||
Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.inner
|
||||
.poll_ready(cx)
|
||||
.map_err(|e| crate::Error::new(crate::error::Kind::Connect).with(e.into()))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: T) -> Self::Future {
|
||||
let builder = self.builder.clone();
|
||||
let io = self.inner.make_connection(req);
|
||||
|
||||
let fut = async move {
|
||||
match io.await {
|
||||
Ok(io) => match builder.handshake(io).await {
|
||||
Ok((sr, conn)) => {
|
||||
builder.exec.execute(async move {
|
||||
if let Err(e) = conn.await {
|
||||
debug!("connection error: {:?}", e);
|
||||
}
|
||||
});
|
||||
Ok(sr)
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
Err(e) => {
|
||||
let err = crate::Error::new(crate::error::Kind::Connect).with(e.into());
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Box::pin(fut)
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use super::Service;
|
||||
use crate::common::{task, Future, Poll};
|
||||
|
||||
// The same "trait alias" as tower::MakeConnection, but inlined to reduce
|
||||
// dependencies.
|
||||
pub trait MakeConnection<Target>: self::sealed::Sealed<(Target,)> {
|
||||
type Connection: AsyncRead + AsyncWrite;
|
||||
type Error;
|
||||
type Future: Future<Output = Result<Self::Connection, Self::Error>>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>>;
|
||||
fn make_connection(&mut self, target: Target) -> Self::Future;
|
||||
}
|
||||
|
||||
impl<S, Target> self::sealed::Sealed<(Target,)> for S where S: Service<Target> {}
|
||||
|
||||
impl<S, Target> MakeConnection<Target> for S
|
||||
where
|
||||
S: Service<Target>,
|
||||
S::Response: AsyncRead + AsyncWrite,
|
||||
{
|
||||
type Connection = S::Response;
|
||||
type Error = S::Error;
|
||||
type Future = S::Future;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Service::poll_ready(self, cx)
|
||||
}
|
||||
|
||||
fn make_connection(&mut self, target: Target) -> Self::Future {
|
||||
Service::call(self, target)
|
||||
}
|
||||
}
|
||||
|
||||
mod sealed {
|
||||
pub trait Sealed<X> {}
|
||||
}
|
||||
@@ -10,8 +10,6 @@
|
||||
//!
|
||||
//! - `HttpService`: This is blanketly implemented for all types that
|
||||
//! implement `Service<http::Request<B1>, Response = http::Response<B2>>`.
|
||||
//! - `MakeConnection`: A `Service` that returns a "connection", a type that
|
||||
//! implements `AsyncRead` and `AsyncWrite`.
|
||||
//!
|
||||
//! # HttpService
|
||||
//!
|
||||
@@ -26,7 +24,6 @@
|
||||
pub use tower_service::Service;
|
||||
|
||||
mod http;
|
||||
mod make;
|
||||
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "client"))]
|
||||
mod oneshot;
|
||||
mod util;
|
||||
@@ -34,8 +31,6 @@ mod util;
|
||||
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "server"))]
|
||||
pub(super) use self::http::HttpService;
|
||||
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "client"))]
|
||||
pub(super) use self::make::MakeConnection;
|
||||
#[cfg(all(any(feature = "http1", feature = "http2"), feature = "client"))]
|
||||
pub(super) use self::oneshot::{oneshot, Oneshot};
|
||||
|
||||
pub use self::util::service_fn;
|
||||
|
||||
Reference in New Issue
Block a user