use bytes::Bytes;
use http_body_util::combinators::UnsyncBoxBody;
use hyper::header::{AUTHORIZATION, HOST, HeaderValue};
use hyper::http::uri::Scheme;
use wasmtime_wasi_http::p3::bindings::http::types::ErrorCode;
#[derive(Clone, Debug)]
pub struct OtlpHijack {
pub placeholder_host: String,
pub target_host: String,
pub target_path_prefix: String,
pub auth: String,
}
impl OtlpHijack {
pub(crate) fn matches(&self, uri: &hyper::Uri) -> bool {
uri.host() == Some(self.placeholder_host.as_str())
}
pub(crate) fn rewrite(
&self,
req: &mut hyper::Request<UnsyncBoxBody<Bytes, ErrorCode>>,
) -> Result<(), ErrorCode> {
let original_path = req
.uri()
.path_and_query()
.map(|pq| pq.as_str().to_string())
.unwrap_or_else(|| "/".to_string());
let new_path = format!("{}{}", self.target_path_prefix, original_path);
let new_uri = hyper::Uri::builder()
.scheme(Scheme::HTTPS)
.authority(self.target_host.as_str())
.path_and_query(new_path.as_str())
.build()
.map_err(|_| ErrorCode::HttpRequestUriInvalid)?;
*req.uri_mut() = new_uri;
let headers = req.headers_mut();
headers.remove(HOST);
headers.insert(
HOST,
HeaderValue::from_str(&self.target_host).map_err(|_| ErrorCode::HttpRequestUriInvalid)?,
);
let auth_value = format!("Basic {}", self.auth);
headers.insert(
AUTHORIZATION,
HeaderValue::from_str(&auth_value).map_err(|_| ErrorCode::HttpRequestDenied)?,
);
Ok(())
}
}