use url::Url;
use crate::plain::exchange;
use crate::{Error, Response, Scheme, Status};
pub(crate) async fn fetch(url: &Url) -> Result<Response, Error> {
let host = url
.host_str()
.ok_or_else(|| Error::BadUrl("finger URL has no host".into()))?;
let port = url.port().unwrap_or_else(|| Scheme::Finger.default_port());
let user = query_target(url);
let request = format!("{user}\r\n");
let body = exchange(host, port, request.as_bytes()).await?;
Ok(Response {
url: url.clone(),
status: Status::Success,
raw_status: None,
meta: "text/plain".to_string(),
body,
})
}
fn query_target(url: &Url) -> String {
let from_path = url.path().trim_start_matches('/');
if !from_path.is_empty() {
from_path.to_string()
} else {
url.username().to_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn target(u: &str) -> String {
query_target(&Url::parse(u).unwrap())
}
#[test]
fn user_from_path_or_userinfo_or_empty() {
assert_eq!(target("finger://example.org/alice"), "alice");
assert_eq!(target("finger://bob@example.org"), "bob");
assert_eq!(target("finger://example.org/"), "");
}
}