diff --git a/src/fetch/collection_id.rs b/src/fetch/collection_id.rs index a45419c..8f42008 100644 --- a/src/fetch/collection_id.rs +++ b/src/fetch/collection_id.rs @@ -40,9 +40,10 @@ where where ::Error: From, { - let json = fetch_object_http(&self.0, data).await?; - Kind::verify(&json, &self.0, data).await?; - Kind::from_json(json, owner, data).await + let res = fetch_object_http(&self.0, data).await?; + let redirect_url = &res.url; + Kind::verify(&res.object, redirect_url, data).await?; + Kind::from_json(res.object, owner, data).await } } diff --git a/src/fetch/mod.rs b/src/fetch/mod.rs index 28b709e..bf1bfd5 100644 --- a/src/fetch/mod.rs +++ b/src/fetch/mod.rs @@ -23,6 +23,14 @@ pub mod object_id; /// Resolves identifiers of the form `name@example.com` pub mod webfinger; +/// Response from fetching a remote object +pub struct FetchObjectResponse { + /// The resolved object + pub object: Kind, + /// Contains the final URL (different from request URL in case of redirect) + pub url: Url, +} + /// Fetch a remote object over HTTP and convert to `Kind`. /// /// [crate::fetch::object_id::ObjectId::dereference] wraps this function to add caching and @@ -38,7 +46,7 @@ pub mod webfinger; pub async fn fetch_object_http( url: &Url, data: &Data, -) -> Result { +) -> Result, Error> { fetch_object_http_with_accept(url, data, FEDERATION_CONTENT_TYPE).await } @@ -48,7 +56,7 @@ async fn fetch_object_http_with_accept( url: &Url, data: &Data, content_type: &str, -) -> Result { +) -> Result, Error> { let config = &data.config; // dont fetch local objects this way debug_assert!(url.domain() != Some(&config.domain)); @@ -84,5 +92,9 @@ async fn fetch_object_http_with_accept( return Err(Error::ObjectDeleted); } - res.json_limited().await + let url = res.url().clone(); + Ok(FetchObjectResponse { + object: res.json_limited().await?, + url, + }) } diff --git a/src/fetch/object_id.rs b/src/fetch/object_id.rs index 29d5507..8c0e5aa 100644 --- a/src/fetch/object_id.rs +++ b/src/fetch/object_id.rs @@ -156,10 +156,11 @@ where return Err(anyhow!("Fetched remote object {} which was deleted", self).into()); } - let res2 = res?; + let res = res?; + let redirect_url = &res.url; - Kind::verify(&res2, self.inner(), data).await?; - Kind::from_json(res2, data).await + Kind::verify(&res.object, redirect_url, data).await?; + Kind::from_json(res.object, data).await } } diff --git a/src/fetch/webfinger.rs b/src/fetch/webfinger.rs index 078816f..0b8c4a1 100644 --- a/src/fetch/webfinger.rs +++ b/src/fetch/webfinger.rs @@ -38,7 +38,8 @@ where let res: Webfinger = fetch_object_http_with_accept(&Url::parse(&fetch_url)?, data, "application/jrd+json") - .await?; + .await? + .object; debug_assert_eq!(res.subject, format!("acct:{identifier}")); let links: Vec = res