You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-11-20 12:02:22 +03:00
Gate some crates behind features in mas-http
This commit is contained in:
@@ -24,30 +24,14 @@
|
||||
#![warn(clippy::pedantic)]
|
||||
#![allow(clippy::module_name_repetitions)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use bytes::Bytes;
|
||||
use futures_util::{FutureExt, TryFutureExt};
|
||||
use http::{Request, Response};
|
||||
use http_body::{combinators::BoxBody, Body};
|
||||
use hyper::{
|
||||
client::{connect::dns::GaiResolver, HttpConnector},
|
||||
Client,
|
||||
};
|
||||
use hyper_rustls::{ConfigBuilderExt, HttpsConnector, HttpsConnectorBuilder};
|
||||
use thiserror::Error;
|
||||
use tokio::{sync::OnceCell, task::JoinError};
|
||||
use tower::{util::BoxCloneService, ServiceBuilder, ServiceExt};
|
||||
|
||||
use self::layers::{
|
||||
client::ClientResponse,
|
||||
otel::{TraceDns, TraceLayer},
|
||||
};
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
mod client;
|
||||
mod ext;
|
||||
mod future_service;
|
||||
mod layers;
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
pub use self::client::client;
|
||||
pub use self::{
|
||||
ext::{
|
||||
set_propagator, CorsLayerExt, ServiceBuilderExt as HttpServiceBuilderExt,
|
||||
@@ -67,97 +51,3 @@ pub use self::{
|
||||
};
|
||||
|
||||
pub(crate) type BoxError = Box<dyn std::error::Error + Send + Sync>;
|
||||
|
||||
/// A wrapper over a boxed error that implements ``std::error::Error``.
|
||||
/// This is helps converting to ``anyhow::Error`` with the `?` operator
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ClientError {
|
||||
#[error("failed to initialize HTTPS client")]
|
||||
Init(#[from] ClientInitError),
|
||||
|
||||
#[error(transparent)]
|
||||
Call(#[from] BoxError),
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Clone)]
|
||||
pub enum ClientInitError {
|
||||
#[error("failed to load system certificates")]
|
||||
CertificateLoad {
|
||||
#[from]
|
||||
inner: Arc<JoinError>, // That error is in an Arc to have the error implement Clone
|
||||
},
|
||||
}
|
||||
|
||||
static TLS_CONFIG: OnceCell<rustls::ClientConfig> = OnceCell::const_new();
|
||||
|
||||
async fn make_base_client<B, E>(
|
||||
) -> Result<hyper::Client<HttpsConnector<HttpConnector<TraceDns<GaiResolver>>>, B>, ClientInitError>
|
||||
where
|
||||
B: http_body::Body<Data = Bytes, Error = E> + Send + 'static,
|
||||
E: Into<BoxError>,
|
||||
{
|
||||
// Trace DNS requests
|
||||
let resolver = ServiceBuilder::new()
|
||||
.layer(TraceLayer::dns())
|
||||
.service(GaiResolver::new());
|
||||
|
||||
let mut http = HttpConnector::new_with_resolver(resolver);
|
||||
http.enforce_http(false);
|
||||
|
||||
let tls_config = TLS_CONFIG
|
||||
.get_or_try_init(|| async move {
|
||||
// Load the TLS config once in a blocking task because loading the system
|
||||
// certificates can take a long time (~200ms) on macOS
|
||||
let span = tracing::info_span!("load_certificates");
|
||||
tokio::task::spawn_blocking(|| {
|
||||
let _span = span.entered();
|
||||
rustls::ClientConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_native_roots()
|
||||
.with_no_client_auth()
|
||||
})
|
||||
.await
|
||||
})
|
||||
.await
|
||||
.map_err(|e| ClientInitError::from(Arc::new(e)))?;
|
||||
|
||||
let https = HttpsConnectorBuilder::new()
|
||||
.with_tls_config(tls_config.clone())
|
||||
.https_or_http()
|
||||
.enable_http1()
|
||||
.enable_http2()
|
||||
.wrap_connector(http);
|
||||
|
||||
// TODO: we should get the remote address here
|
||||
let client = Client::builder().build(https);
|
||||
|
||||
Ok::<_, ClientInitError>(client)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn client<B, E>(
|
||||
operation: &'static str,
|
||||
) -> BoxCloneService<Request<B>, Response<BoxBody<bytes::Bytes, ClientError>>, ClientError>
|
||||
where
|
||||
B: http_body::Body<Data = Bytes, Error = E> + Default + Send + 'static,
|
||||
E: Into<BoxError> + 'static,
|
||||
{
|
||||
let fut = make_base_client()
|
||||
// Map the error to a ClientError
|
||||
.map_ok(|s| s.map_err(|e| ClientError::from(BoxError::from(e))))
|
||||
// Wrap it in an Shared (Arc) to be able to Clone it
|
||||
.shared();
|
||||
|
||||
let client: FutureService<_, _> = FutureService::new(fut);
|
||||
|
||||
let client = ServiceBuilder::new()
|
||||
// Convert the errors to ClientError to help dealing with them
|
||||
.map_err(ClientError::from)
|
||||
.map_response(|r: ClientResponse<hyper::Body>| {
|
||||
r.map(|body| body.map_err(ClientError::from).boxed())
|
||||
})
|
||||
.layer(ClientLayer::new(operation))
|
||||
.service(client);
|
||||
|
||||
client.boxed_clone()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user