magnetar/src/client/forwarding_client.rs

73 lines
1.9 KiB
Rust

use axum::http::{HeaderMap, Method};
use hyper::client::HttpConnector;
use hyper::http::uri;
use hyper::{header, Body, Client, Request, Response, Uri};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ProxyClientError {
#[error("Client error: {0}")]
ClientError(String),
#[error("URL error: {0}")]
UriError(#[from] uri::InvalidUri),
#[error("HTTP error: {0}")]
HttpError(#[from] axum::http::Error),
#[error("Hyper error: {0}")]
HyperError(#[from] hyper::Error),
}
pub struct ProxyClient {
pub client: Client<HttpConnector, Body>,
pub upstream: String,
}
impl ProxyClient {
pub fn new(upstream: String) -> ProxyClient {
let client = Client::builder().set_host(false).build_http();
ProxyClient { client, upstream }
}
pub async fn send(
&self,
host: &str,
path: &str,
method: Method,
body: Body,
headers_in: &HeaderMap,
) -> Result<Response<Body>, ProxyClientError> {
let mut builder = Request::builder();
let Some(headers) = builder.headers_mut() else {
return Err(ProxyClientError::ClientError("No headers".to_owned()));
};
*headers = headers_in.clone();
headers.insert(
header::HOST,
host.parse().map_err(|e| {
ProxyClientError::ClientError(format!("Invalid header value: {e:?}"))
})?,
);
let uri = format!("{}/{}", self.upstream, path)
.parse::<Uri>()
.map_err(ProxyClientError::UriError)?;
let request = builder
.method(method)
.uri(uri)
.body(body)
.map_err(ProxyClientError::HttpError)?;
let response = self
.client
.request(request)
.await
.map_err(ProxyClientError::HyperError)?;
Ok(response)
}
}