use std::str::FromStr;
use axum::{
extract::{FromRequestParts, OriginalUri},
http::{Uri, request::Parts},
};
use axum_extra::extract::Host;
pub(crate) struct RemoteUrl(pub Uri);
impl<S> FromRequestParts<S> for RemoteUrl
where
S: Send + Sync,
{
type Rejection = &'static str;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
let uri = OriginalUri::from_request_parts(parts, state).await.unwrap();
let url = if uri.0.scheme().is_some() {
uri.0
} else {
let host = Host::from_request_parts(parts, state)
.await
.map_err(|_| "Unable to extract host")?;
let proto = parts
.headers
.get("X-Forwarded-Proto")
.and_then(|f| f.to_str().ok())
.unwrap_or("http");
let url = format!("{}://{}{}", proto, host.0, uri.0);
Uri::from_str(&url).unwrap()
};
Ok(RemoteUrl(url))
}
}