use crate::service::hyper::NewConnection;
use crate::service::{Layer, Service, Stack};
use crate::tls::ClientCertificate;
use http::Request;
use tokio_rustls::server::TlsStream;
use webpki::types::CertificateDer;
pub struct ClientCertificateLayer;
impl<S> Layer<S> for ClientCertificateLayer {
type Service = ClientCertificateService<S>;
fn layer(self, inner: S) -> Self::Service {
ClientCertificateService { inner }
}
}
pub struct ClientCertificateService<S> {
inner: S,
}
impl<S, T, L> Service<NewConnection<TlsStream<T>, L>> for ClientCertificateService<S>
where
S: Service<NewConnection<TlsStream<T>, Stack<L, ClientCertificateRequestLayer>>> + Sync,
T: Send,
L: Send,
{
type Response = S::Response;
async fn call(&self, req: NewConnection<TlsStream<T>, L>) -> Self::Response {
let cert = req
.stream
.get_ref()
.1
.peer_certificates()
.and_then(|c| c.first())
.cloned()
.map(CertificateDer::into_owned)
.map(ClientCertificate::new);
self.inner
.call(NewConnection {
stream: req.stream,
service_builder: req
.service_builder
.layer(ClientCertificateRequestLayer { cert }),
})
.await
}
}
pub struct ClientCertificateRequestLayer {
cert: Option<ClientCertificate>,
}
impl<S> Layer<S> for ClientCertificateRequestLayer {
type Service = ClientCertificateRequestService<S>;
fn layer(self, inner: S) -> Self::Service {
ClientCertificateRequestService {
inner,
cert: self.cert,
}
}
}
pub struct ClientCertificateRequestService<S> {
inner: S,
cert: Option<ClientCertificate>,
}
impl<S, B> Service<Request<B>> for ClientCertificateRequestService<S>
where
S: Service<Request<B>> + Sync,
B: Send,
{
type Response = S::Response;
async fn call(&self, mut req: Request<B>) -> Self::Response {
if let Some(cert) = &self.cert {
req.extensions_mut().insert(cert.clone());
}
self.inner.call(req).await
}
}