fix(activitypub-base): lookup_actor fetches WebFinger via HTTPS directly
Some checks failed
lint / lint (push) Has been cancelled
test / unit (push) Has been cancelled
test / integration (push) Has been cancelled
lint / lint (pull_request) Failing after 9m40s
test / unit (pull_request) Successful in 16m33s
test / integration (pull_request) Failing after 17m33s

This commit is contained in:
2026-05-14 20:25:14 +02:00
parent baf8b57b6d
commit dbd891d60d

View File

@@ -1336,13 +1336,52 @@ impl domain::ports::FederationActionPort for ActivityPubService {
&self,
handle: &str,
) -> Result<domain::models::remote_actor::RemoteActor, domain::errors::DomainError> {
let data = self.federation_config.to_request_data();
use activitypub_federation::fetch::object_id::ObjectId;
let normalized = handle.trim_start_matches('@');
let actor: crate::actors::DbActor = webfinger_resolve_actor(normalized, &data)
let at = normalized.rfind('@').ok_or_else(|| {
domain::errors::DomainError::InvalidInput("handle must be user@domain".into())
})?;
let (user, domain_str) = (&normalized[..at], &normalized[at + 1..]);
// Fetch WebFinger over HTTPS directly — the library's webfinger_resolve_actor
// tries HTTP first in debug mode, which fails on servers without HTTP→HTTPS redirect.
let wf_url = format!(
"https://{}/.well-known/webfinger?resource=acct:{}@{}",
domain_str, user, domain_str
);
let wf: serde_json::Value = reqwest::Client::new()
.get(&wf_url)
.header("Accept", "application/jrd+json, application/json")
.send()
.await
.map_err(|e| domain::errors::DomainError::ExternalService(e.to_string()))?
.json()
.await
.map_err(|e| domain::errors::DomainError::ExternalService(e.to_string()))?;
let self_href = wf["links"]
.as_array()
.and_then(|links| {
links.iter().find(|l| {
l["rel"].as_str() == Some("self")
&& l["type"].as_str() == Some("application/activity+json")
})
})
.and_then(|l| l["href"].as_str())
.ok_or(domain::errors::DomainError::NotFound)?;
let self_url = url::Url::parse(self_href)
.map_err(|e| domain::errors::DomainError::ExternalService(e.to_string()))?;
let data = self.federation_config.to_request_data();
let actor: crate::actors::DbActor = ObjectId::from(self_url)
.dereference(&data)
.await
.map_err(|e: crate::error::Error| {
domain::errors::DomainError::ExternalService(e.to_string())
})?;
Ok(domain::models::remote_actor::RemoteActor {
url: actor.ap_id.to_string(),
handle: actor.username.clone(),