use super::owned::OwnedUriRef;
use super::resolve::remove_dot_segments_graceful;
use super::{Uri, UriInner};
use crate::normalize::normalize_pct;
use rama_core::bytes::BytesMut;
pub(super) fn canonicalize_uri(uri: Uri) -> Uri {
if matches!(uri.inner, UriInner::Asterisk) {
return uri;
}
let owned = uri.as_owned_components();
let canonical = canonicalize_owned(owned);
Uri {
inner: UriInner::Owned(crate::std::sync::Arc::new(canonical)),
}
}
fn canonicalize_owned(mut owned: OwnedUriRef) -> OwnedUriRef {
if let Some(scheme) = owned.scheme.take() {
owned.scheme = Some(scheme.canonicalize());
}
if let Some(authority) = &mut owned.authority {
authority.address = authority.address.clone().canonicalize();
if let Some(scheme) = &owned.scheme
&& let Some(default) = scheme.default_port()
&& authority.address.port == crate::address::OptPort::Set(default)
{
authority.address.port = crate::address::OptPort::Unset;
}
if authority.address.port == crate::address::OptPort::Empty {
authority.address.port = crate::address::OptPort::Unset;
}
}
normalize_pct(&mut owned.path);
if let Some(q) = &mut owned.query {
normalize_pct(&mut q.bytes);
}
if let Some(f) = &mut owned.fragment {
normalize_pct(&mut f.bytes);
}
owned.path = remove_dot_segments_graceful(&owned.path);
if owned.authority.is_some() && owned.path.is_empty() {
owned.path = BytesMut::from(&b"/"[..]);
}
owned
}