diff --git a/src/actor.rs b/src/actor.rs index f571d45..38596d6 100644 --- a/src/actor.rs +++ b/src/actor.rs @@ -26,6 +26,30 @@ pub struct Actor { } impl Actor { + pub fn from_uri(mut uri: &str) -> Option { + if ! uri.starts_with("https://") { + return None; + } + uri = &uri[8..]; + + let parts = uri.split("/").collect::>(); + if parts.len() != 3 { + return None; + } + + let Ok(topic) = urlencoding::decode(parts[2]) else { return None; }; + let kind = match parts[1] { + "tag" => + ActorKind::TagRelay(topic.to_string()), + "instance" => + ActorKind::InstanceRelay(topic.to_string()), + _ => + return None, + }; + let host = Arc::new(parts[0].to_string()); + Some(Actor { host, kind }) + } + pub fn uri(&self) -> String { match &self.kind { ActorKind::TagRelay(tag) => diff --git a/src/main.rs b/src/main.rs index 0150a3f..1e18e42 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,7 @@ mod activitypub; mod actor_cache; mod endpoint; +use actor::Actor; use state::State; @@ -46,26 +47,33 @@ async fn webfinger( return StatusCode::NOT_FOUND.into_response(); }, }; - let (target_kind, target_host) = - if resource.starts_with("acct:tag-") { - let off = "acct:tag-".len(); - let at = resource.find('@'); - (actor::ActorKind::TagRelay(resource[off..at.unwrap_or(resource.len())].to_string()), - at.map_or_else(|| state.hostname.clone(), |at| Arc::new(resource[at + 1..].to_string()))) - } else if resource.starts_with("acct:instance-") { - let off = "acct:instance-".len(); - let at = resource.find('@'); - (actor::ActorKind::InstanceRelay(resource[off..at.unwrap_or(resource.len())].to_string()), - at.map_or_else(|| state.hostname.clone(), |at| Arc::new(resource[at + 1..].to_string()))) - } else { - track_request("GET", "webfinger", "not_found"); - return StatusCode::NOT_FOUND.into_response(); - }; - track_request("GET", "webfinger", "found"); - let target = actor::Actor { - host: target_host, - kind: target_kind, + let target = if resource.starts_with("acct:") { + let (target_kind, target_host) = + if resource.starts_with("acct:tag-") { + let off = "acct:tag-".len(); + let at = resource.find('@'); + (actor::ActorKind::TagRelay(resource[off..at.unwrap_or(resource.len())].to_string()), + at.map_or_else(|| state.hostname.clone(), |at| Arc::new(resource[at + 1..].to_string()))) + } else if resource.starts_with("acct:instance-") { + let off = "acct:instance-".len(); + let at = resource.find('@'); + (actor::ActorKind::InstanceRelay(resource[off..at.unwrap_or(resource.len())].to_string()), + at.map_or_else(|| state.hostname.clone(), |at| Arc::new(resource[at + 1..].to_string()))) + } else { + track_request("GET", "webfinger", "not_found"); + return StatusCode::NOT_FOUND.into_response(); + }; + actor::Actor { + host: target_host, + kind: target_kind, + } + } else if let Some(target) = Actor::from_uri(resource) { + target + } else { + track_request("GET", "webfinger", "not_found"); + return StatusCode::NOT_FOUND.into_response(); }; + track_request("GET", "webfinger", "found"); Json(json!({ "subject": &resource, "aliases": &[