diff --git a/Cargo.lock b/Cargo.lock index 22b981f90..a78d2b9b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3660,6 +3660,7 @@ dependencies = [ "kitsune-db", "kitsune-embed", "kitsune-federation-filter", + "kitsune-http-client", "kitsune-search", "kitsune-service", "kitsune-url", @@ -3695,6 +3696,7 @@ dependencies = [ "hyper", "hyper-rustls", "hyper-util", + "kitsune-core", "kitsune-type", "pin-project", "serde", @@ -3721,6 +3723,7 @@ dependencies = [ "kitsune-error", "kitsune-federation", "kitsune-federation-filter", + "kitsune-http-client", "kitsune-jobs", "kitsune-observability", "kitsune-service", diff --git a/crates/kitsune-activitypub/src/deliverer/core.rs b/crates/kitsune-activitypub/src/deliverer/core.rs index 56f753813..034f7bb57 100644 --- a/crates/kitsune-activitypub/src/deliverer/core.rs +++ b/crates/kitsune-activitypub/src/deliverer/core.rs @@ -1,6 +1,5 @@ use futures_util::{stream::FuturesUnordered, Stream, StreamExt}; use http::{Method, Request}; -use kitsune_core::consts::USER_AGENT; use kitsune_db::model::{account::Account, user::User}; use kitsune_error::{Error, Result}; use kitsune_federation_filter::FederationFilter; @@ -17,8 +16,7 @@ use url::Url; /// Does not need to be Arc wrapped for cheap cloning. It's inherently cheap to clone. #[derive(Clone, TypedBuilder)] pub struct Deliverer { - #[builder(default = Client::builder().user_agent(USER_AGENT).unwrap().build())] - client: Client, + http_client: Client, federation_filter: FederationFilter, mrf_service: MrfService, } @@ -55,7 +53,7 @@ impl Deliverer { .body(body.into())?; let response = self - .client + .http_client .execute_signed(request, &account.public_key_id, &user.private_key) .await?; diff --git a/crates/kitsune-activitypub/src/fetcher/mod.rs b/crates/kitsune-activitypub/src/fetcher/mod.rs index 4be794838..380afc9b6 100644 --- a/crates/kitsune-activitypub/src/fetcher/mod.rs +++ b/crates/kitsune-activitypub/src/fetcher/mod.rs @@ -1,15 +1,12 @@ use async_trait::async_trait; use headers::{ContentType, HeaderMapExt}; -use http::HeaderValue; +use http::{header::ACCEPT, HeaderValue, Request}; use kitsune_cache::ArcCache; use kitsune_config::language_detection::Configuration as LanguageDetectionConfig; -use kitsune_core::{ - consts::USER_AGENT, - traits::{ - coerce::CoerceResolver, - fetcher::{AccountFetchOptions, PostFetchOptions}, - Fetcher as FetcherTrait, Resolver, - }, +use kitsune_core::traits::{ + coerce::CoerceResolver, + fetcher::{AccountFetchOptions, PostFetchOptions}, + Fetcher as FetcherTrait, Resolver, }; use kitsune_db::{ model::{account::Account, custom_emoji::CustomEmoji, post::Post}, @@ -32,23 +29,14 @@ mod actor; mod emoji; mod object; +static ACCEPT_VALUE: HeaderValue = HeaderValue::from_static( + "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\", application/activity+json", +); + #[derive(TypedBuilder)] #[builder(build_method(into = Arc))] pub struct Fetcher { - #[builder(default = - Client::builder() - .default_header( - "accept", - HeaderValue::from_static( - "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\", application/activity+json", - ), - ) - .unwrap() - .user_agent(USER_AGENT) - .unwrap() - .build() - )] - client: Client, + http_client: Client, db_pool: PgPool, embed_client: Option, federation_filter: FederationFilter, @@ -74,8 +62,13 @@ impl Fetcher { bail!("instance is blocked"); } - let response = self.client.get(url.as_str()).await?; + let request = Request::builder() + .method(http::Method::GET) + .uri(url.as_str()) + .header(ACCEPT, &ACCEPT_VALUE) + .body(kitsune_http_client::Body::empty())?; + let response = self.http_client.execute(request).await?; if !response.status().is_success() { return Ok(None); } diff --git a/crates/kitsune-activitypub/tests/fetcher/basic.rs b/crates/kitsune-activitypub/tests/fetcher/basic.rs index 8d9601671..6569bd2f2 100644 --- a/crates/kitsune-activitypub/tests/fetcher/basic.rs +++ b/crates/kitsune-activitypub/tests/fetcher/basic.rs @@ -25,7 +25,7 @@ async fn fetch_actor() { let client = Client::builder().service(service_fn(handle)); let fetcher = Fetcher::builder() - .client(client.clone()) + .http_client(client.clone()) .db_pool(db_pool) .embed_client(None) .federation_filter( @@ -36,7 +36,7 @@ async fn fetch_actor() { ) .language_detection_config(language_detection_config()) .search_backend(NoopSearchService) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .account_cache(Arc::new(NoopCache.into())) .post_cache(Arc::new(NoopCache.into())) .build(); @@ -64,7 +64,7 @@ async fn fetch_emoji() { let client = Client::builder().service(service_fn(handle)); let fetcher = Fetcher::builder() - .client(client.clone()) + .http_client(client.clone()) .db_pool(db_pool.clone()) .embed_client(None) .federation_filter( @@ -75,7 +75,7 @@ async fn fetch_emoji() { ) .language_detection_config(language_detection_config()) .search_backend(NoopSearchService) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .account_cache(Arc::new(NoopCache.into())) .post_cache(Arc::new(NoopCache.into())) .build(); @@ -115,7 +115,7 @@ async fn fetch_note() { let client = Client::builder().service(service_fn(handle)); let fetcher = Fetcher::builder() - .client(client.clone()) + .http_client(client.clone()) .db_pool(db_pool.clone()) .embed_client(None) .federation_filter( @@ -126,7 +126,7 @@ async fn fetch_note() { ) .language_detection_config(language_detection_config()) .search_backend(NoopSearchService) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .account_cache(Arc::new(NoopCache.into())) .post_cache(Arc::new(NoopCache.into())) .build(); diff --git a/crates/kitsune-activitypub/tests/fetcher/filter.rs b/crates/kitsune-activitypub/tests/fetcher/filter.rs index bb3484700..d82068f6b 100644 --- a/crates/kitsune-activitypub/tests/fetcher/filter.rs +++ b/crates/kitsune-activitypub/tests/fetcher/filter.rs @@ -45,9 +45,9 @@ async fn federation_allow() { let client = Client::builder().service(client); let fetcher = builder .clone() - .client(client.clone()) + .http_client(client.clone()) .language_detection_config(language_detection_config()) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .build(); assert_blocked!(fetcher @@ -63,9 +63,9 @@ async fn federation_allow() { let client = Client::builder().service(service_fn(handle)); let fetcher = builder .clone() - .client(client.clone()) + .http_client(client.clone()) .language_detection_config(language_detection_config()) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .build(); assert!(matches!( @@ -90,7 +90,7 @@ async fn federation_deny() { let client = Client::builder().service(client); let fetcher = Fetcher::builder() - .client(client.clone()) + .http_client(client.clone()) .db_pool(db_pool) .embed_client(None) .federation_filter( @@ -101,7 +101,7 @@ async fn federation_deny() { ) .language_detection_config(language_detection_config()) .search_backend(NoopSearchService) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .account_cache(Arc::new(NoopCache.into())) .post_cache(Arc::new(NoopCache.into())) .build(); diff --git a/crates/kitsune-activitypub/tests/fetcher/infinite.rs b/crates/kitsune-activitypub/tests/fetcher/infinite.rs index aa03eba99..e0264da2b 100644 --- a/crates/kitsune-activitypub/tests/fetcher/infinite.rs +++ b/crates/kitsune-activitypub/tests/fetcher/infinite.rs @@ -91,7 +91,7 @@ async fn fetch_infinitely_long_reply_chain() { let client = Client::builder().service(client); let fetcher = Fetcher::builder() - .client(client.clone()) + .http_client(client.clone()) .db_pool(db_pool) .embed_client(None) .federation_filter( @@ -102,7 +102,7 @@ async fn fetch_infinitely_long_reply_chain() { ) .language_detection_config(language_detection_config()) .search_backend(NoopSearchService) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .account_cache(Arc::new(NoopCache.into())) .post_cache(Arc::new(NoopCache.into())) .build(); diff --git a/crates/kitsune-activitypub/tests/fetcher/origin.rs b/crates/kitsune-activitypub/tests/fetcher/origin.rs index 3181fe5cd..54baed964 100644 --- a/crates/kitsune-activitypub/tests/fetcher/origin.rs +++ b/crates/kitsune-activitypub/tests/fetcher/origin.rs @@ -37,9 +37,9 @@ async fn check_ap_id_authority() { let client = Client::builder().service(client); let fetcher = builder .clone() - .client(client.clone()) + .http_client(client.clone()) .language_detection_config(language_detection_config()) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .build(); // The mock HTTP client ensures that the fetcher doesn't access the correct server @@ -60,9 +60,9 @@ async fn check_ap_id_authority() { let client = Client::builder().service(client); let fetcher = builder .clone() - .client(client.clone()) + .http_client(client.clone()) .language_detection_config(language_detection_config()) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .build(); let _ = fetcher @@ -84,7 +84,7 @@ async fn check_ap_content_type() { let client = Client::builder().service(client); let fetcher = Fetcher::builder() - .client(client.clone()) + .http_client(client.clone()) .db_pool(db_pool) .embed_client(None) .federation_filter( @@ -95,7 +95,7 @@ async fn check_ap_content_type() { ) .language_detection_config(language_detection_config()) .search_backend(NoopSearchService) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .account_cache(Arc::new(NoopCache.into())) .post_cache(Arc::new(NoopCache.into())) .build(); diff --git a/crates/kitsune-activitypub/tests/fetcher/webfinger.rs b/crates/kitsune-activitypub/tests/fetcher/webfinger.rs index a332e5a96..7c4cac600 100644 --- a/crates/kitsune-activitypub/tests/fetcher/webfinger.rs +++ b/crates/kitsune-activitypub/tests/fetcher/webfinger.rs @@ -47,7 +47,7 @@ async fn fetch_actor_with_custom_acct() { let client = Client::builder().service(client); let fetcher = Fetcher::builder() - .client(client.clone()) + .http_client(client.clone()) .db_pool(db_pool) .embed_client(None) .federation_filter( @@ -58,7 +58,7 @@ async fn fetch_actor_with_custom_acct() { ) .language_detection_config(language_detection_config()) .search_backend(NoopSearchService) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .account_cache(Arc::new(NoopCache.into())) .post_cache(Arc::new(NoopCache.into())) .build(); @@ -125,7 +125,7 @@ async fn ignore_fake_webfinger_acct() { let client = Client::builder().service(client); let fetcher = Fetcher::builder() - .client(client.clone()) + .http_client(client.clone()) .db_pool(db_pool) .embed_client(None) .federation_filter( @@ -136,7 +136,7 @@ async fn ignore_fake_webfinger_acct() { ) .language_detection_config(language_detection_config()) .search_backend(NoopSearchService) - .resolver(Arc::new(Webfinger::with_client(client, Arc::new(NoopCache.into()))).coerce()) + .resolver(Arc::new(Webfinger::new(client, Arc::new(NoopCache.into()))).coerce()) .account_cache(Arc::new(NoopCache.into())) .post_cache(Arc::new(NoopCache.into())) .build(); diff --git a/crates/kitsune-captcha/src/hcaptcha.rs b/crates/kitsune-captcha/src/hcaptcha.rs index 30905a490..a07430a0f 100644 --- a/crates/kitsune-captcha/src/hcaptcha.rs +++ b/crates/kitsune-captcha/src/hcaptcha.rs @@ -10,8 +10,7 @@ pub struct Captcha { pub site_key: String, pub secret_key: String, - #[builder(default)] - client: Client, + http_client: Client, } #[derive(Serialize, Deserialize, TypedBuilder)] @@ -46,7 +45,7 @@ impl CaptchaBackend for Captcha { .header("Accept", "application/json") .body(body.into())?; - let response = self.client.execute(request).await?; + let response = self.http_client.execute(request).await?; let verification_result = response.json::().await?; if !verification_result.success { diff --git a/crates/kitsune-captcha/src/mcaptcha.rs b/crates/kitsune-captcha/src/mcaptcha.rs index 53c20b542..ab8a33912 100644 --- a/crates/kitsune-captcha/src/mcaptcha.rs +++ b/crates/kitsune-captcha/src/mcaptcha.rs @@ -11,8 +11,7 @@ pub struct Captcha { pub secret_key: String, pub site_key: String, - #[builder(default)] - client: Client, + http_client: Client, } #[derive(Debug, Serialize, Deserialize)] @@ -41,7 +40,7 @@ impl CaptchaBackend for Captcha { .header("Accept", "application/json") .body(body.into())?; - let response = self.client.execute(request).await?; + let response = self.http_client.execute(request).await?; let verification_result = response.json::().await?; if !verification_result.valid { diff --git a/crates/kitsune-federation/Cargo.toml b/crates/kitsune-federation/Cargo.toml index 12441fe70..5ff563b8b 100644 --- a/crates/kitsune-federation/Cargo.toml +++ b/crates/kitsune-federation/Cargo.toml @@ -13,6 +13,7 @@ kitsune-core = { workspace = true } kitsune-db = { workspace = true } kitsune-embed = { workspace = true } kitsune-federation-filter = { workspace = true } +kitsune-http-client.workspace = true kitsune-search = { workspace = true } kitsune-service = { workspace = true } kitsune-url = { workspace = true } diff --git a/crates/kitsune-federation/src/activitypub.rs b/crates/kitsune-federation/src/activitypub.rs index 348f0af8f..5e447e15a 100644 --- a/crates/kitsune-federation/src/activitypub.rs +++ b/crates/kitsune-federation/src/activitypub.rs @@ -27,6 +27,7 @@ pub struct PrepareDeliverer { attachment_service: AttachmentService, db_pool: PgPool, federation_filter: FederationFilter, + http_client: kitsune_http_client::Client, mrf_service: MrfService, url_service: UrlService, } @@ -38,6 +39,7 @@ pub struct PrepareFetcher { db_pool: PgPool, embed_client: Option, federation_filter: FederationFilter, + http_client: kitsune_http_client::Client, language_detection_config: LanguageDetectionConfig, post_cache: ArcCache, search_backend: AnySearchBackend, @@ -47,6 +49,7 @@ pub struct PrepareFetcher { pub(crate) fn prepare_deliverer(prepare: PrepareDeliverer) -> Arc { let core_deliverer = kitsune_activitypub::CoreDeliverer::builder() .federation_filter(prepare.federation_filter) + .http_client(prepare.http_client) .mrf_service(prepare.mrf_service) .build(); @@ -67,13 +70,14 @@ pub(crate) fn prepare_deliverer(prepare: PrepareDeliverer) -> Arc #[inline] pub(crate) fn prepare_fetcher(prepare: PrepareFetcher) -> Arc { - let webfinger = Webfinger::new(prepare.account_resource_cache); + let webfinger = Webfinger::new(prepare.http_client.clone(), prepare.account_resource_cache); ActivityPubFetcher::builder() .account_cache(prepare.account_cache) .db_pool(prepare.db_pool.clone()) .embed_client(prepare.embed_client) .federation_filter(prepare.federation_filter.clone()) + .http_client(prepare.http_client) .language_detection_config(prepare.language_detection_config) .post_cache(prepare.post_cache) .resolver(Arc::new(webfinger).coerce()) diff --git a/crates/kitsune-http-client/Cargo.toml b/crates/kitsune-http-client/Cargo.toml index d0e84fd46..7accd6139 100644 --- a/crates/kitsune-http-client/Cargo.toml +++ b/crates/kitsune-http-client/Cargo.toml @@ -30,6 +30,7 @@ hyper-rustls = { version = "0.27.3", default-features = false, features = [ "ring", "tls12", ] } +kitsune-core = { workspace = true } kitsune-type = { workspace = true } pin-project = "1.1.7" serde = "1.0.214" diff --git a/crates/kitsune-http-client/src/lib.rs b/crates/kitsune-http-client/src/lib.rs index 5e7615439..e364ebd54 100644 --- a/crates/kitsune-http-client/src/lib.rs +++ b/crates/kitsune-http-client/src/lib.rs @@ -233,7 +233,9 @@ impl Default for ClientBuilder { timeout: Option::default(), }; - builder.user_agent("kitsune-http-client").unwrap() + builder + .user_agent(kitsune_core::consts::USER_AGENT) + .unwrap() } } diff --git a/crates/kitsune-service/src/attachment.rs b/crates/kitsune-service/src/attachment.rs index 296dde8c5..ce9409914 100644 --- a/crates/kitsune-service/src/attachment.rs +++ b/crates/kitsune-service/src/attachment.rs @@ -84,7 +84,7 @@ pub struct AttachmentService { .unwrap() .build() )] - client: Client, + http_client: Client, db_pool: PgPool, media_proxy_enabled: bool, #[builder(setter(into))] @@ -132,7 +132,7 @@ impl AttachmentService { Ok(stream.map_err(Error::from).boxed()) } else if self.media_proxy_enabled { Ok(self - .client + .http_client .get(media_attachment.remote_url.as_ref().unwrap()) .await? .stream() @@ -267,7 +267,7 @@ mod test { .build(); let attachment_service = AttachmentService::builder() - .client(client) + .http_client(client) .db_pool(db_pool) .url_service(url_service) .storage_backend(storage) diff --git a/crates/kitsune-service/src/post/resolver.rs b/crates/kitsune-service/src/post/resolver.rs index 56d241749..4d430bb3d 100644 --- a/crates/kitsune-service/src/post/resolver.rs +++ b/crates/kitsune-service/src/post/resolver.rs @@ -165,10 +165,10 @@ mod test { }); let client = Client::builder().service(client); - let webfinger = Arc::new(Webfinger::with_client(client.clone(), Arc::new(NoopCache.into()))).coerce(); + let webfinger = Arc::new(Webfinger::new(client.clone(), Arc::new(NoopCache.into()))).coerce(); let fetcher = Fetcher::builder() - .client(client) + .http_client(client) .db_pool(db_pool.clone()) .embed_client(None) .federation_filter( diff --git a/crates/kitsune-service/src/prepare.rs b/crates/kitsune-service/src/prepare.rs index 0ffef713d..550696c10 100644 --- a/crates/kitsune-service/src/prepare.rs +++ b/crates/kitsune-service/src/prepare.rs @@ -55,12 +55,13 @@ where } #[must_use] -pub fn captcha(config: &captcha::Configuration) -> AnyCaptcha { +pub fn captcha(client: kitsune_http_client::Client, config: &captcha::Configuration) -> AnyCaptcha { match config { captcha::Configuration::HCaptcha(config) => HCaptcha::builder() .verify_url(config.verify_url.to_string()) .site_key(config.site_key.to_string()) .secret_key(config.secret_key.to_string()) + .http_client(client) .build() .into(), captcha::Configuration::MCaptcha(config) => MCaptcha::builder() @@ -68,6 +69,7 @@ pub fn captcha(config: &captcha::Configuration) -> AnyCaptcha { .verify_url(config.verify_url.to_string()) .site_key(config.site_key.to_string()) .secret_key(config.secret_key.to_string()) + .http_client(client) .build() .into(), } diff --git a/crates/kitsune-webfinger/src/lib.rs b/crates/kitsune-webfinger/src/lib.rs index 9d55fe080..97be41ae8 100644 --- a/crates/kitsune-webfinger/src/lib.rs +++ b/crates/kitsune-webfinger/src/lib.rs @@ -4,12 +4,9 @@ extern crate tracing; use async_trait::async_trait; use fred::clients::RedisPool; use futures_util::future::{FutureExt, OptionFuture}; -use http::{HeaderValue, StatusCode}; +use http::{header::ACCEPT, HeaderValue, Request, StatusCode}; use kitsune_cache::{ArcCache, CacheBackend, RedisCache}; -use kitsune_core::{ - consts::USER_AGENT, - traits::{resolver::AccountResource, Resolver}, -}; +use kitsune_core::traits::{resolver::AccountResource, Resolver}; use kitsune_error::Result; use kitsune_http_client::Client; use kitsune_type::webfinger::Resource; @@ -18,6 +15,7 @@ use std::{ptr, time::Duration}; use triomphe::Arc; const CACHE_DURATION: Duration = Duration::from_secs(10 * 60); // 10 minutes +static ACCEPT_VALUE: HeaderValue = HeaderValue::from_static("application/jrd+json"); /// Intended to allow up to one canonicalisation on the originating server, one cross-origin /// canonicalisation and one more canonicalisation on the destination server, @@ -28,35 +26,26 @@ pub const MAX_JRD_REDIRECTS: u32 = 3; #[derive(Clone)] pub struct Webfinger { cache: ArcCache, - client: Client, + http_client: Client, } impl Webfinger { #[must_use] - pub fn with_defaults(redis_pool: RedisPool) -> Self { - Self::new(Arc::new( - RedisCache::new(redis_pool, "webfinger", CACHE_DURATION).into(), - )) + pub fn with_defaults(client: Client, redis_pool: RedisPool) -> Self { + Self::new( + client, + Arc::new(RedisCache::new(redis_pool, "webfinger", CACHE_DURATION).into()), + ) } } impl Webfinger { - #[allow(clippy::missing_panics_doc)] // The invariants are covered. It won't panic. #[must_use] - pub fn new(cache: ArcCache) -> Self { - let client = Client::builder() - .default_header("Accept", HeaderValue::from_static("application/jrd+json")) - .unwrap() - .user_agent(USER_AGENT) - .unwrap() - .build(); - - Self::with_client(client, cache) - } - - #[must_use] - pub fn with_client(client: Client, cache: ArcCache) -> Self { - Self { cache, client } + pub fn new(client: Client, cache: ArcCache) -> Self { + Self { + cache, + http_client: client, + } } } @@ -95,8 +84,13 @@ impl Resolver for Webfinger { } let webfinger_url = format!("https://{domain}/.well-known/webfinger?resource={acct}"); - let response = self.client.get(webfinger_url).await?; + let request = Request::builder() + .header(ACCEPT, &ACCEPT_VALUE) + .uri(webfinger_url) + .body(kitsune_http_client::Body::empty()) + .unwrap(); + let response = self.http_client.execute(request).await?; if matches!(response.status(), StatusCode::NOT_FOUND | StatusCode::GONE) { // Either the actor couldn't be found or the server doesn't support WebFinger return Ok(None); diff --git a/crates/kitsune-webfinger/tests/basic.rs b/crates/kitsune-webfinger/tests/basic.rs index f2d76e789..be480ecb3 100644 --- a/crates/kitsune-webfinger/tests/basic.rs +++ b/crates/kitsune-webfinger/tests/basic.rs @@ -21,7 +21,7 @@ async fn basic() { }); let client = Client::builder().service(client); - let webfinger = Webfinger::with_client(client, Arc::new(NoopCache.into())); + let webfinger = Webfinger::new(client, Arc::new(NoopCache.into())); let resource = webfinger .resolve_account("0x0", "corteximplant.com") .await diff --git a/crates/kitsune-webfinger/tests/redirects.rs b/crates/kitsune-webfinger/tests/redirects.rs index 3f3adcfb5..8792e51c2 100644 --- a/crates/kitsune-webfinger/tests/redirects.rs +++ b/crates/kitsune-webfinger/tests/redirects.rs @@ -40,7 +40,7 @@ async fn follow_jrd_redirect() { let client = Client::builder().service(client); - let webfinger = Webfinger::with_client(client, Arc::new(NoopCache.into())); + let webfinger = Webfinger::new(client, Arc::new(NoopCache.into())); let resource = webfinger .resolve_account("0x0", "corteximplant.com") .await @@ -79,7 +79,7 @@ async fn reject_fake_jrd_redirect() { }); let client = Client::builder().service(client); - let webfinger = Webfinger::with_client(client, Arc::new(NoopCache.into())); + let webfinger = Webfinger::new(client, Arc::new(NoopCache.into())); let resource = webfinger .resolve_account("0x0", "corteximplant.com") .await @@ -116,7 +116,7 @@ async fn reject_unbounded_number_of_jrd_redirects() { }); let client = Client::builder().service(client); - let webfinger = Webfinger::with_client(client, Arc::new(NoopCache.into())); + let webfinger = Webfinger::new(client, Arc::new(NoopCache.into())); let resource = webfinger .resolve_account("0x0", "corteximplant.com") .await diff --git a/kitsune-job-runner/Cargo.toml b/kitsune-job-runner/Cargo.toml index 2de5dd17e..a74026526 100644 --- a/kitsune-job-runner/Cargo.toml +++ b/kitsune-job-runner/Cargo.toml @@ -24,6 +24,7 @@ kitsune-email = { workspace = true } kitsune-error = { workspace = true } kitsune-federation = { workspace = true } kitsune-federation-filter = { workspace = true } +kitsune-http-client.workspace = true kitsune-jobs = { workspace = true } kitsune-observability = { workspace = true } kitsune-service = { workspace = true } diff --git a/kitsune-job-runner/src/lib.rs b/kitsune-job-runner/src/lib.rs index 6d12a4c7d..8c2476c7a 100644 --- a/kitsune-job-runner/src/lib.rs +++ b/kitsune-job-runner/src/lib.rs @@ -58,8 +58,9 @@ pub async fn prepare_job_queue( Ok(Arc::new(queue).coerce()) } -#[instrument(skip(job_queue, state))] +#[instrument(skip(http_client, job_queue, state))] pub async fn run_dispatcher( + http_client: kitsune_http_client::Client, job_queue: Arc + '_>, state: JobDispatcherState, num_job_workers: usize, @@ -68,6 +69,7 @@ pub async fn run_dispatcher( .attachment_service(state.attachment_service) .db_pool(state.db_pool.clone()) .federation_filter(state.federation_filter) + .http_client(http_client) .mrf_service(state.mrf_service) .url_service(state.url_service.clone()) .build(); diff --git a/kitsune-job-runner/src/main.rs b/kitsune-job-runner/src/main.rs index 3a11d7160..340841ba7 100644 --- a/kitsune-job-runner/src/main.rs +++ b/kitsune-job-runner/src/main.rs @@ -30,6 +30,7 @@ async fn main() -> eyre::Result<()> { kitsune_observability::initialise(&config)?; + let http_client = kitsune_http_client::Client::default(); let db_pool = kitsune_db::connect(&config.database) .await .map_err(kitsune_error::Error::into_error)?; @@ -67,7 +68,13 @@ async fn main() -> eyre::Result<()> { .url_service(url_service) .build(); - kitsune_job_runner::run_dispatcher(job_queue, state, config.job_queue.num_workers.into()).await; + kitsune_job_runner::run_dispatcher( + http_client, + job_queue, + state, + config.job_queue.num_workers.into(), + ) + .await; Ok(()) } diff --git a/kitsune/Cargo.toml b/kitsune/Cargo.toml index 58088483f..62bab132c 100644 --- a/kitsune/Cargo.toml +++ b/kitsune/Cargo.toml @@ -55,6 +55,7 @@ kitsune-embed = { workspace = true } kitsune-error = { workspace = true } kitsune-federation = { workspace = true } kitsune-federation-filter = { workspace = true } +kitsune-http-client = { workspace = true } kitsune-job-runner = { workspace = true } kitsune-jobs = { workspace = true } kitsune-language = { workspace = true } diff --git a/kitsune/src/http/handler/well_known/webfinger.rs b/kitsune/src/http/handler/well_known/webfinger.rs index 8591d4546..e8622c295 100644 --- a/kitsune/src/http/handler/well_known/webfinger.rs +++ b/kitsune/src/http/handler/well_known/webfinger.rs @@ -108,17 +108,21 @@ mod tests { let client = Client::builder().service(service_fn(handle)); let attachment_service = AttachmentService::builder() - .client(client.clone()) + .http_client(client.clone()) .db_pool(db_pool.clone()) .url_service(url_service.clone()) .storage_backend(storage) .media_proxy_enabled(false) .build(); - let resolver = Arc::new(Webfinger::new(Arc::new(NoopCache.into()))).coerce(); + let resolver = Arc::new(Webfinger::new( + Client::default(), + Arc::new(NoopCache.into()), + )) + .coerce(); let fetcher = Fetcher::builder() - .client(client) + .http_client(client) .db_pool(db_pool.clone()) .embed_client(None) .federation_filter( diff --git a/kitsune/src/lib.rs b/kitsune/src/lib.rs index fe534a321..623dc92d6 100644 --- a/kitsune/src/lib.rs +++ b/kitsune/src/lib.rs @@ -47,6 +47,7 @@ use {futures_util::future::OptionFuture, kitsune_oidc::OidcService}; pub async fn initialise_state( config: &Configuration, db_pool: PgPool, + http_client: kitsune_http_client::Client, job_queue: Arc>, ) -> eyre::Result { let url_service = UrlService::builder() @@ -83,6 +84,7 @@ pub async fn initialise_state( .db_pool(db_pool.clone()) .embed_client(embed_client.clone()) .federation_filter(federation_filter.clone()) + .http_client(http_client.clone()) .language_detection_config(config.language_detection) .post_cache(prepare::cache(&config.cache, "POST-CACHE").await?) .search_backend(search_backend.clone()) @@ -104,7 +106,12 @@ pub async fn initialise_state( .build(); let captcha_service = CaptchaService::builder() - .backend(config.captcha.as_ref().map(prepare::captcha)) + .backend( + config + .captcha + .as_ref() + .map(|captcha_config| prepare::captcha(http_client.clone(), captcha_config)), + ) .build(); let custom_emoji_service = CustomEmojiService::builder() diff --git a/kitsune/src/main.rs b/kitsune/src/main.rs index 904f8f383..b5a6407d5 100644 --- a/kitsune/src/main.rs +++ b/kitsune/src/main.rs @@ -22,6 +22,7 @@ async fn boot() -> eyre::Result<()> { let config = Configuration::load(args.config).await?; kitsune_observability::initialise(&config)?; + let http_client = kitsune_http_client::Client::default(); let conn = kitsune_db::connect(&config.database) .await .map_err(kitsune_error::Error::into_error) @@ -31,7 +32,9 @@ async fn boot() -> eyre::Result<()> { .await .wrap_err("Failed to connect to the Redis instance for the job scheduler")?; - let state = kitsune::initialise_state(&config, conn, job_queue.clone()).await?; + let state = + kitsune::initialise_state(&config, conn, http_client.clone(), job_queue.clone()).await?; + let dispatcher_state = JobDispatcherState::builder() .attachment_service(state.service.attachment.clone()) .db_pool(state.db_pool.clone()) @@ -49,6 +52,7 @@ async fn boot() -> eyre::Result<()> { shutdown_signal.clone(), )); let job_runner_fut = tokio::spawn(kitsune_job_runner::run_dispatcher( + http_client, job_queue, dispatcher_state, config.job_queue.num_workers.get(),