]> Untitled Git - lemmy.git/blob - crates/apub/src/fetcher/fetch.rs
Merge branch 'remove_settings_and_secret_singletons_squashed'
[lemmy.git] / crates / apub / src / fetcher / fetch.rs
1 use crate::{check_is_apub_id_valid, APUB_JSON_CONTENT_TYPE};
2 use anyhow::anyhow;
3 use lemmy_utils::{request::retry, settings::structs::Settings, LemmyError};
4 use log::info;
5 use reqwest::Client;
6 use serde::Deserialize;
7 use std::time::Duration;
8 use url::Url;
9
10 /// Maximum number of HTTP requests allowed to handle a single incoming activity (or a single object
11 /// fetch through the search).
12 ///
13 /// A community fetch will load the outbox with up to 20 items, and fetch the creator for each item.
14 /// So we are looking at a maximum of 22 requests (rounded up just to be safe).
15 static MAX_REQUEST_NUMBER: i32 = 25;
16
17 /// Fetch any type of ActivityPub object, handling things like HTTP headers, deserialisation,
18 /// timeouts etc.
19 pub(in crate::fetcher) async fn fetch_remote_object<Response>(
20   client: &Client,
21   settings: &Settings,
22   url: &Url,
23   recursion_counter: &mut i32,
24 ) -> Result<Response, LemmyError>
25 where
26   Response: for<'de> Deserialize<'de> + std::fmt::Debug,
27 {
28   *recursion_counter += 1;
29   if *recursion_counter > MAX_REQUEST_NUMBER {
30     return Err(anyhow!("Maximum recursion depth reached").into());
31   }
32   check_is_apub_id_valid(url, false, settings)?;
33
34   let timeout = Duration::from_secs(60);
35
36   let res = retry(|| {
37     client
38       .get(url.as_str())
39       .header("Accept", APUB_JSON_CONTENT_TYPE)
40       .timeout(timeout)
41       .send()
42   })
43   .await?;
44
45   let object = res.json().await?;
46   info!("Fetched remote object {}", url);
47   Ok(object)
48 }