Files
tonic/tonic/src/transport/service/connect.rs
T
2019-09-16 18:27:54 -04:00

82 lines
2.2 KiB
Rust

use super::{layer::ServiceBuilderExt, AddOrigin, Connector};
use crate::{transport::Endpoint, BoxBody};
use hyper::client::conn::Builder;
use hyper::client::service::Connect as HyperConnect;
use std::{
fmt,
future::Future,
pin::Pin,
task::{Context, Poll},
};
use tower::{
layer::Layer, limit::concurrency::ConcurrencyLimitLayer, timeout::TimeoutLayer,
util::BoxService, ServiceBuilder,
};
use tower_load::Load;
use tower_reconnect::Reconnect;
use tower_service::Service;
type Request = http::Request<BoxBody>;
type Response = http::Response<hyper::Body>;
pub struct Connection {
// inner: AddOrigin<Reconnect<HyperConnect<Connector, BoxBody, Uri>, Uri>>,
inner: BoxService<Request, Response, crate::Error>,
}
impl Connection {
pub fn new(mut endpoint: Endpoint) -> Result<Self, crate::Error> {
let connector = Connector::new(endpoint.cert.take())?;
let settings = Builder::new().http2_only(true).clone();
let stack = ServiceBuilder::new()
.layer_fn(|s| AddOrigin::new(s, endpoint.uri.clone()))
.optional_layer(endpoint.timeout.map(|t| TimeoutLayer::new(t)))
.optional_layer(
endpoint
.concurrency_limit
.map(|l| ConcurrencyLimitLayer::new(l)),
)
.into_inner();
let conn = Reconnect::new(HyperConnect::new(connector, settings), endpoint.uri.clone());
let inner = stack.layer(conn);
Ok(Self {
inner: BoxService::new(inner),
})
}
}
impl Service<Request> for Connection {
type Response = Response;
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 Context<'_>) -> Poll<Result<(), Self::Error>> {
Service::poll_ready(&mut self.inner, cx).map_err(Into::into)
}
fn call(&mut self, req: Request) -> Self::Future {
self.inner.call(req)
}
}
impl Load for Connection {
type Metric = usize;
fn load(&self) -> Self::Metric {
0
}
}
impl fmt::Debug for Connection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Connection").finish()
}
}