Menu
Public repository / master
AkurAI-Framework / crates/http/src/endpoint.rs
Latest change c6179dcf3abbf53272e4279e6740397ad2e75726 - AKURAI-FRAMEWORK-1..9 consolidate framework APIs by Ólafur Búi Ólafsson
//! Shared parsing for plain-HTTP service endpoints.
/// Return whether an endpoint uses the unsupported HTTPS scheme.
pub fn is_https_endpoint(endpoint: &str) -> bool {
let trimmed = endpoint.trim();
trimmed.len() >= 8 && trimmed[..8].eq_ignore_ascii_case("https://")
}
/// Parse `http://host[:port]` into an authority and port.
///
/// Paths, queries, and fragments are ignored. Callers retain ownership of
/// scheme-specific errors while this helper owns trimming, authority parsing,
/// defaulting, and invalid-host/port behavior.
pub fn parse_plain_endpoint(endpoint: &str) -> Result<(String, u16), String> {
let trimmed = endpoint.trim();
let rest = strip_ci_prefix(trimmed, "http://")
.ok_or_else(|| format!("must start with http://: {trimmed}"))?;
let authority = rest
.split(['/', '?', '#'])
.next()
.unwrap_or("")
.trim_end_matches('/');
if authority.is_empty() {
return Err(format!("missing host: {trimmed}"));
}
let (host, port) = match authority.rsplit_once(':') {
Some((host, port)) => {
let port = port
.parse::<u16>()
.map_err(|_| format!("bad port: {port}"))?;
(host, port)
}
None => (authority, 80),
};
if host.is_empty() {
return Err(format!("missing host: {trimmed}"));
}
Ok((host.to_string(), port))
}
fn strip_ci_prefix<'a>(s: &'a str, prefix: &str) -> Option<&'a str> {
if s.len() >= prefix.len() && s[..prefix.len()].eq_ignore_ascii_case(prefix) {
Some(&s[prefix.len()..])
} else {
None
}
}
#[cfg(test)]
mod tests {
use super::parse_plain_endpoint;
#[test]
fn parses_authority_and_ignores_path() {
assert_eq!(
parse_plain_endpoint(" HTTP://localhost:8080/v1?q#f "),
Ok(("localhost".to_string(), 8080))
);
assert_eq!(
parse_plain_endpoint("http://localhost"),
Ok(("localhost".to_string(), 80))
);
}
#[test]
fn preserves_invalid_endpoint_errors() {
assert_eq!(
parse_plain_endpoint("https://localhost"),
Err("must start with http://: https://localhost".to_string())
);
assert_eq!(
parse_plain_endpoint("http://localhost:nope"),
Err("bad port: nope".to_string())
);
}
}