diff --git a/Cargo.lock b/Cargo.lock index 08b663a57..e119a646e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -989,9 +989,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.37" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" +checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8" dependencies = [ "shlex", ] @@ -1296,9 +1296,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -2698,9 +2698,12 @@ dependencies = [ "ipnet", "once_cell", "rand 0.8.5", + "rustls", + "rustls-native-certs 0.7.3", "thiserror 1.0.69", "tinyvec", "tokio", + "tokio-rustls", "tracing", "url", ] @@ -2714,15 +2717,16 @@ dependencies = [ "cfg-if", "futures-util", "hickory-proto", - "ipconfig", "lru-cache", "once_cell", "parking_lot", "rand 0.8.5", - "resolv-conf", + "rustls", + "rustls-native-certs 0.7.3", "smallvec", "thiserror 1.0.69", "tokio", + "tokio-rustls", "tracing", ] @@ -2744,17 +2748,6 @@ dependencies = [ "digest", ] -[[package]] -name = "hostname" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] - [[package]] name = "hostname" version = "0.4.0" @@ -3202,18 +3195,6 @@ version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" -[[package]] -name = "ipconfig" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" -dependencies = [ - "socket2", - "widestring", - "windows-sys 0.48.0", - "winreg", -] - [[package]] name = "ipnet" version = "2.10.1" @@ -3681,6 +3662,7 @@ dependencies = [ "kitsune-db", "kitsune-embed", "kitsune-federation-filter", + "kitsune-http-client", "kitsune-search", "kitsune-service", "kitsune-url", @@ -3709,12 +3691,14 @@ dependencies = [ "asynk-strim", "bytes", "futures-util", + "hickory-resolver", "http-body", "http-body-util", "http-signatures", "hyper", "hyper-rustls", "hyper-util", + "kitsune-core", "kitsune-type", "pin-project", "serde", @@ -3741,6 +3725,7 @@ dependencies = [ "kitsune-error", "kitsune-federation", "kitsune-federation-filter", + "kitsune-http-client", "kitsune-jobs", "kitsune-observability", "kitsune-service", @@ -3848,6 +3833,7 @@ dependencies = [ "serde", "sonic-rs", "speedy-uuid", + "thiserror 2.0.3", "tokio", "url", ] @@ -4148,7 +4134,7 @@ dependencies = [ "fastrand", "futures-io", "futures-util", - "hostname 0.4.0", + "hostname", "httpdate", "idna 1.0.3", "mime", @@ -4303,12 +4289,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - [[package]] name = "matches" version = "0.1.10" @@ -4406,7 +4386,7 @@ dependencies = [ "terminal_size 0.3.0", "textwrap", "thiserror 1.0.69", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -4534,8 +4514,8 @@ dependencies = [ "serde", "sonic-rs", "thiserror 2.0.3", - "wasm-encoder 0.219.1", - "wasmparser 0.219.1", + "wasm-encoder 0.220.0", + "wasmparser 0.220.0", "wat", ] @@ -4548,7 +4528,7 @@ dependencies = [ "colored_json", "mrf-manifest", "sonic-rs", - "wasmparser 0.219.1", + "wasmparser 0.220.0", "wat", ] @@ -4775,9 +4755,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "opentelemetry" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570074cc999d1a58184080966e5bd3bf3a9a4af650c3b05047c2621e7405cd17" +checksum = "0f3cebff57f7dbd1255b44d8bddc2cebeb0ea677dbaa2e25a3070a91b318f660" dependencies = [ "futures-core", "futures-sink", @@ -4789,9 +4769,9 @@ dependencies = [ [[package]] name = "opentelemetry-http" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6351496aeaa49d7c267fb480678d85d1cd30c5edb20b497c48c56f62a8c14b99" +checksum = "10a8a7f5f6ba7c1b286c2fbca0454eaba116f63bbe69ed250b642d36fbb04d80" dependencies = [ "async-trait", "bytes", @@ -4801,9 +4781,9 @@ dependencies = [ [[package]] name = "opentelemetry-otlp" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e1f9c8b032d4f635c730c0efcf731d5e2530ea13fa8bef7939ddc8420696bd" +checksum = "91cf61a1868dacc576bf2b2a1c3e9ab150af7272909e80085c3173384fe11f76" dependencies = [ "async-trait", "futures-core", @@ -4821,9 +4801,9 @@ dependencies = [ [[package]] name = "opentelemetry-proto" -version = "0.26.1" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d3968ce3aefdcca5c27e3c4ea4391b37547726a70893aab52d3de95d5f8b34" +checksum = "a6e05acbfada5ec79023c85368af14abd0b307c015e9064d249b2a950ef459a6" dependencies = [ "hex", "opentelemetry", @@ -4835,9 +4815,9 @@ dependencies = [ [[package]] name = "opentelemetry_sdk" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c627d9f4c9cdc1f21a29ee4bfbd6028fcb8bcf2a857b43f3abdf72c9c862f3" +checksum = "27b742c1cae4693792cc564e58d75a2a0ba29421a34a85b50da92efa89ecb2bc" dependencies = [ "async-trait", "futures-channel", @@ -5436,12 +5416,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quick-xml" version = "0.30.0" @@ -5683,16 +5657,6 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" -[[package]] -name = "resolv-conf" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" -dependencies = [ - "hostname 0.3.1", - "quick-error", -] - [[package]] name = "retry-policies" version = "0.4.0" @@ -6110,9 +6074,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] @@ -6129,9 +6093,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -6746,7 +6710,7 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" dependencies = [ "smawk", "unicode-linebreak", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -7289,8 +7253,7 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc58af5d3f6c5811462cabb3289aec0093f7338e367e5a33d28c0433b3c7360b" +source = "git+https://github.com/tokio-rs/tracing-opentelemetry.git?rev=d18214596c97b1243ee955a63bed3875a4f8f5f9#d18214596c97b1243ee955a63bed3875a4f8f5f9" dependencies = [ "js-sys", "once_cell", @@ -7477,6 +7440,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -7720,6 +7689,16 @@ dependencies = [ "wasmparser 0.219.1", ] +[[package]] +name = "wasm-encoder" +version = "0.220.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebf48234b389415b226a4daef6562933d38c7b28a8b8f64c5c4130dad1561ab7" +dependencies = [ + "leb128", + "wasmparser 0.220.0", +] + [[package]] name = "wasm-metadata" version = "0.219.1" @@ -7755,6 +7734,19 @@ name = "wasmparser" version = "0.219.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c771866898879073c53b565a6c7b49953795159836714ac56a5befb581227c5" +dependencies = [ + "ahash", + "bitflags 2.6.0", + "hashbrown 0.14.5", + "indexmap 2.6.0", + "semver", +] + +[[package]] +name = "wasmparser" +version = "0.220.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e246c2772ce3ebc83f89a2d4487ac5794cad6c309b2071818a88c7db7c36d87b" dependencies = [ "ahash", "bitflags 2.6.0", @@ -8010,22 +8002,22 @@ dependencies = [ [[package]] name = "wast" -version = "219.0.1" +version = "220.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f79a9d9df79986a68689a6b40bcc8d5d40d807487b235bebc2ac69a242b54a1" +checksum = "4e708c8de08751fd66e70961a32bae9d71901f14a70871e181cb8461a3bb3165" dependencies = [ "bumpalo", "leb128", "memchr", - "unicode-width", - "wasm-encoder 0.219.1", + "unicode-width 0.2.0", + "wasm-encoder 0.220.0", ] [[package]] name = "wat" -version = "1.219.1" +version = "1.220.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bc3cf014fb336883a411cd662f987abf6a1d2a27f2f0008616a0070bbf6bd0d" +checksum = "de4f1d7d59614ba690541360102b995c4eb1b9ed373701d5102cc1a968b1c5a3" dependencies = [ "wast", ] @@ -8086,12 +8078,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "widestring" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" - [[package]] name = "winapi" version = "0.3.9" @@ -8316,16 +8302,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "winx" version = "0.36.3" diff --git a/Cargo.toml b/Cargo.toml index fa63fd659..691025a24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -109,6 +109,11 @@ garde = { version = "0.20.0", features = [ "regex", "serde", ] } +hickory-resolver = { version = "0.25.0-alpha.3", default-features = false, features = [ + "dns-over-rustls", + "native-certs", + "tokio-runtime", +] } iso8601-timestamp = "0.3.0" itertools = { version = "0.13.0", default-features = false } moka = { version = "=0.12.7", features = ["sync"] } @@ -199,3 +204,6 @@ license = "AGPL-3.0-or-later" [patch.crates-io] # SIMD runtime detection and generic I/O wrapper sonic-rs = { git = "https://github.com/aumetra/sonic-rs.git", rev = "12df930a57ff9f07eb16111a3da1feff3dc8e5ad" } + +# Compatibility with latest opentelemetry crates +tracing-opentelemetry = { git = "https://github.com/tokio-rs/tracing-opentelemetry.git", rev = "d18214596c97b1243ee955a63bed3875a4f8f5f9" } diff --git a/crates/kitsune-activitypub/Cargo.toml b/crates/kitsune-activitypub/Cargo.toml index 2d8e79822..98e961cbb 100644 --- a/crates/kitsune-activitypub/Cargo.toml +++ b/crates/kitsune-activitypub/Cargo.toml @@ -31,7 +31,7 @@ kitsune-util = { workspace = true } kitsune-wasm-mrf = { workspace = true } mime = "0.3.17" mime_guess = { version = "2.0.5", default-features = false } -serde = "1.0.214" +serde = "1.0.215" sha2 = "0.10.8" sonic-rs = { workspace = true } speedy-uuid = { workspace = true } 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-cache/Cargo.toml b/crates/kitsune-cache/Cargo.toml index d3a6a4712..75389e8c0 100644 --- a/crates/kitsune-cache/Cargo.toml +++ b/crates/kitsune-cache/Cargo.toml @@ -10,7 +10,7 @@ enum_dispatch = "0.3.13" fred = { workspace = true } kitsune-error = { workspace = true } moka = { workspace = true } -serde = "1.0.214" +serde = "1.0.215" sonic-rs = { workspace = true } tracing = "0.1.40" triomphe = { workspace = true } diff --git a/crates/kitsune-captcha/Cargo.toml b/crates/kitsune-captcha/Cargo.toml index f16560ba1..1f17ffef6 100644 --- a/crates/kitsune-captcha/Cargo.toml +++ b/crates/kitsune-captcha/Cargo.toml @@ -10,7 +10,7 @@ enum_dispatch = "0.3.13" http = "1.1.0" kitsune-error = { workspace = true } kitsune-http-client = { workspace = true } -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } serde_urlencoded = "0.7.1" sonic-rs = { workspace = true } strum = { version = "0.26.3", features = ["derive"] } 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-config/Cargo.toml b/crates/kitsune-config/Cargo.toml index f9ade3a3f..c4c02fd22 100644 --- a/crates/kitsune-config/Cargo.toml +++ b/crates/kitsune-config/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true eyre = "0.6.12" human-size = { version = "0.4.3", features = ["serde"] } isolang = { version = "2.4.0", features = ["serde"] } -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } smol_str = { version = "0.3.2", features = ["serde"] } tokio = { workspace = true, features = ["fs"] } toml = { version = "0.8.19", default-features = false, features = ["parse"] } diff --git a/crates/kitsune-core/Cargo.toml b/crates/kitsune-core/Cargo.toml index 19a5f38f1..c6a283b91 100644 --- a/crates/kitsune-core/Cargo.toml +++ b/crates/kitsune-core/Cargo.toml @@ -12,7 +12,7 @@ git-version = "0.3.9" kitsune-db = { workspace = true } kitsune-error = { workspace = true } paste = "1.0.15" -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } triomphe = { workspace = true } typed-builder = "0.20.0" unsize = "1.1.0" diff --git a/crates/kitsune-db/Cargo.toml b/crates/kitsune-db/Cargo.toml index 680e6231c..72dbea8a0 100644 --- a/crates/kitsune-db/Cargo.toml +++ b/crates/kitsune-db/Cargo.toml @@ -29,7 +29,7 @@ rustls = { version = "0.23.16", default-features = false, features = [ "tls12", ] } rustls-native-certs = "0.8.0" -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } sonic-rs = { workspace = true } speedy-uuid = { workspace = true, features = ["diesel"] } tokio = { workspace = true, features = ["rt"] } 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 dd83fe5ef..540476435 100644 --- a/crates/kitsune-http-client/Cargo.toml +++ b/crates/kitsune-http-client/Cargo.toml @@ -11,6 +11,7 @@ bytes = "1.8.0" futures-util = { version = "0.3.31", default-features = false, features = [ "alloc", ] } +hickory-resolver = { workspace = true } http-body = "1.0.1" http-body-util = "0.1.2" http-signatures = { workspace = true } @@ -29,9 +30,10 @@ 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" +serde = "1.0.215" simdutf8 = { workspace = true } sonic-rs = { workspace = true } tower = { version = "0.5.1", features = ["util"] } diff --git a/crates/kitsune-http-client/src/lib.rs b/crates/kitsune-http-client/src/lib.rs index 8b35d86bd..e364ebd54 100644 --- a/crates/kitsune-http-client/src/lib.rs +++ b/crates/kitsune-http-client/src/lib.rs @@ -1,9 +1,10 @@ #![doc = include_str!("../README.md")] #![deny(missing_docs)] -use self::util::BoxCloneService; +use self::{resolver::Resolver, util::BoxCloneService}; use bytes::Buf; use futures_util::{Stream, StreamExt}; +use hickory_resolver::config::{ResolverConfig, ResolverOpts}; use http_body::Body as HttpBody; use http_body_util::{BodyExt, BodyStream, Limited}; use hyper::{ @@ -13,7 +14,10 @@ use hyper::{ HeaderMap, Request, Response as HyperResponse, StatusCode, Uri, Version, }; use hyper_rustls::HttpsConnectorBuilder; -use hyper_util::{client::legacy::Client as HyperClient, rt::TokioExecutor}; +use hyper_util::{ + client::legacy::{connect::HttpConnector, Client as HyperClient}, + rt::TokioExecutor, +}; use kitsune_type::jsonld::RdfNode; use serde::de::DeserializeOwned; use std::{error::Error as StdError, fmt, time::Duration}; @@ -26,6 +30,7 @@ use tower_http::{ }; mod body; +mod resolver; mod util; type BoxBody = http_body_util::combinators::BoxBody; @@ -44,8 +49,7 @@ pub struct Error { impl Error { #[inline] - #[doc(hidden)] - pub fn new(inner: E) -> Self + fn new(inner: E) -> Self where E: Into, { @@ -73,6 +77,7 @@ impl StdError for Error {} pub struct ClientBuilder { content_length_limit: Option, default_headers: HeaderMap, + dns_resolver: Option, timeout: Option, } @@ -113,6 +118,15 @@ impl ClientBuilder { Ok(self) } + /// Set a hickory DNS resolver you want this client to use + /// + /// Otherwise it creates a new one which connects to Quad9 via DNS-over-TLS + #[must_use] + pub fn dns_resolver(mut self, resolver: impl Into) -> Self { + self.dns_resolver = Some(resolver.into()); + self + } + /// Set the User-Agent header /// /// Defaults to `kitsune-http-client` @@ -143,14 +157,22 @@ impl ClientBuilder { /// /// Yes, this operation is infallible #[must_use] - pub fn build(self) -> Client { + pub fn build(mut self) -> Client { + let resolver = self.dns_resolver.take().unwrap_or_else(|| { + let resolver = hickory_resolver::TokioResolver::tokio( + ResolverConfig::quad9_tls(), + ResolverOpts::default(), + ); + resolver.into() + }); + let connector = HttpsConnectorBuilder::new() .with_native_roots() .expect("Failed to fetch native certificates") .https_or_http() .enable_http1() .enable_http2() - .build(); + .wrap_connector(HttpConnector::new_with_resolver(resolver)); let client = HyperClient::builder(TokioExecutor::new()) .build(connector) @@ -207,10 +229,13 @@ impl Default for ClientBuilder { let builder = ClientBuilder { content_length_limit: Some(DEFAULT_BODY_LIMIT), default_headers: HeaderMap::default(), + dns_resolver: None, timeout: Option::default(), }; - builder.user_agent("kitsune-http-client").unwrap() + builder + .user_agent(kitsune_core::consts::USER_AGENT) + .unwrap() } } diff --git a/crates/kitsune-http-client/src/resolver.rs b/crates/kitsune-http-client/src/resolver.rs new file mode 100644 index 000000000..2b390fe7e --- /dev/null +++ b/crates/kitsune-http-client/src/resolver.rs @@ -0,0 +1,55 @@ +use futures_util::{future::BoxFuture, FutureExt}; +use hickory_resolver::{lookup_ip::LookupIpIntoIter, TokioResolver}; +use hyper_util::client::legacy::connect::dns::Name; +use std::{ + net::SocketAddr, + task::{self, Poll}, +}; +use tower::{BoxError, Service}; + +pub struct ResolveIter { + inner: LookupIpIntoIter, +} + +impl Iterator for ResolveIter { + type Item = SocketAddr; + + #[inline] + fn next(&mut self) -> Option { + let item = self.inner.next()?; + Some(SocketAddr::new(item, 80)) + } +} + +#[derive(Clone)] +pub struct Resolver { + inner: TokioResolver, +} + +impl From for Resolver { + fn from(value: TokioResolver) -> Self { + Self { inner: value } + } +} + +impl Service for Resolver { + type Error = BoxError; + type Response = ResolveIter; + type Future = BoxFuture<'static, Result>; + + fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, req: Name) -> Self::Future { + let dns_client = self.inner.clone(); + + async move { + let lookup_ips = dns_client.lookup_ip(req.as_str()).await?; + Ok(ResolveIter { + inner: lookup_ips.into_iter(), + }) + } + .boxed() + } +} diff --git a/crates/kitsune-jobs/Cargo.toml b/crates/kitsune-jobs/Cargo.toml index 9150b9214..76b6e8ca4 100644 --- a/crates/kitsune-jobs/Cargo.toml +++ b/crates/kitsune-jobs/Cargo.toml @@ -15,7 +15,7 @@ kitsune-core = { workspace = true } kitsune-db = { workspace = true } kitsune-email = { workspace = true } kitsune-error = { workspace = true } -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } speedy-uuid = { workspace = true } tracing = "0.1.40" typed-builder = "0.20.0" diff --git a/crates/kitsune-mastodon/Cargo.toml b/crates/kitsune-mastodon/Cargo.toml index ef946b3f3..9bc22f5ce 100644 --- a/crates/kitsune-mastodon/Cargo.toml +++ b/crates/kitsune-mastodon/Cargo.toml @@ -19,7 +19,7 @@ kitsune-type = { workspace = true } kitsune-url = { workspace = true } kitsune-util = { workspace = true } mime = "0.3.17" -serde = "1.0.214" +serde = "1.0.215" smol_str = "0.3.2" sonic-rs = { workspace = true } speedy-uuid = { workspace = true } diff --git a/crates/kitsune-observability/Cargo.toml b/crates/kitsune-observability/Cargo.toml index d9b9063c6..eb997a279 100644 --- a/crates/kitsune-observability/Cargo.toml +++ b/crates/kitsune-observability/Cargo.toml @@ -13,11 +13,11 @@ hyper = { version = "1.5.0", default-features = false } kitsune-config = { workspace = true } kitsune-core = { workspace = true } kitsune-http-client = { workspace = true } -opentelemetry = { version = "0.26.0", default-features = false, features = [ +opentelemetry = { version = "0.27.0", default-features = false, features = [ "trace", ] } -opentelemetry-http = "0.26.0" -opentelemetry-otlp = { version = "0.26.0", default-features = false, features = [ +opentelemetry-http = "0.27.0" +opentelemetry-otlp = { version = "0.27.0", default-features = false, features = [ "grpc-tonic", "http-json", "http-proto", @@ -25,7 +25,7 @@ opentelemetry-otlp = { version = "0.26.0", default-features = false, features = "tls-roots", "trace", ] } -opentelemetry_sdk = { version = "0.26.0", default-features = false, features = [ +opentelemetry_sdk = { version = "0.27.0", default-features = false, features = [ "rt-tokio", ] } tracing = "0.1.40" diff --git a/crates/kitsune-observability/src/lib.rs b/crates/kitsune-observability/src/lib.rs index 517dbd854..98fa55952 100644 --- a/crates/kitsune-observability/src/lib.rs +++ b/crates/kitsune-observability/src/lib.rs @@ -5,7 +5,7 @@ use kitsune_config::{open_telemetry::Transport, Configuration}; use kitsune_core::consts::PROJECT_IDENTIFIER; use opentelemetry::trace::{noop::NoopTracer, Tracer, TracerProvider}; use opentelemetry_http::{Bytes, HttpClient, HttpError, Request, Response}; -use opentelemetry_otlp::{SpanExporterBuilder, WithExportConfig}; +use opentelemetry_otlp::{WithExportConfig, WithHttpConfig}; use opentelemetry_sdk::runtime::Tokio; use std::{env, fmt}; use tracing_error::ErrorLayer; @@ -43,24 +43,6 @@ impl HttpClient for HttpClientAdapter { } } -macro_rules! build_exporter { - ($exporter_type:ty : $transport:expr, $http_client:expr, $endpoint:expr $(,)?) => {{ - let exporter: $exporter_type = match $transport { - Transport::Grpc => opentelemetry_otlp::new_exporter() - .tonic() - .with_endpoint($endpoint) - .into(), - Transport::Http => opentelemetry_otlp::new_exporter() - .http() - .with_endpoint($endpoint) - .with_http_client($http_client.clone()) - .into(), - }; - - exporter - }}; -} - fn initialise_logging(tracer: T) -> eyre::Result<()> where T: Tracer + PreSampledTracer + Send + Sync + 'static, @@ -87,17 +69,21 @@ pub fn initialise(config: &Configuration) -> eyre::Result<()> { inner: kitsune_http_client::Client::default(), }; - let trace_exporter = build_exporter!( - SpanExporterBuilder: - opentelemetry_config.tracing_transport, - &http_client, - opentelemetry_config.tracing_endpoint.as_str(), - ); + let trace_exporter = match opentelemetry_config.tracing_transport { + Transport::Grpc => opentelemetry_otlp::SpanExporter::builder() + .with_tonic() + .with_endpoint(opentelemetry_config.tracing_endpoint.as_str()) + .build()?, + Transport::Http => opentelemetry_otlp::SpanExporter::builder() + .with_http() + .with_endpoint(opentelemetry_config.tracing_endpoint.as_str()) + .with_http_client(http_client.clone()) + .build()?, + }; - let tracer = opentelemetry_otlp::new_pipeline() - .tracing() - .with_exporter(trace_exporter) - .install_batch(Tokio)? + let tracer = opentelemetry_sdk::trace::TracerProvider::builder() + .with_batch_exporter(trace_exporter, Tokio) + .build() .tracer(PROJECT_IDENTIFIER); initialise_logging(tracer)?; diff --git a/crates/kitsune-oidc/Cargo.toml b/crates/kitsune-oidc/Cargo.toml index 87f64b964..cd0892609 100644 --- a/crates/kitsune-oidc/Cargo.toml +++ b/crates/kitsune-oidc/Cargo.toml @@ -21,9 +21,10 @@ openidconnect = { version = "4.0.0-rc.1", default-features = false, features = [ "accept-string-booleans", "timing-resistant-secret-traits", ] } -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } sonic-rs = { workspace = true } speedy-uuid = { workspace = true } +thiserror = "2.0.3" url = "2.5.3" [dev-dependencies] diff --git a/crates/kitsune-oidc/src/error.rs b/crates/kitsune-oidc/src/error.rs new file mode 100644 index 000000000..28882f7d9 --- /dev/null +++ b/crates/kitsune-oidc/src/error.rs @@ -0,0 +1,7 @@ +use thiserror::Error; + +/// Don't ask me why we need this wrapper, I really don't know. +/// I would have preferred to just use a boxed error but here we are. +#[derive(Debug, Error)] +#[error(transparent)] +pub struct ErrorWrapper(pub kitsune_error::BoxError); diff --git a/crates/kitsune-oidc/src/http.rs b/crates/kitsune-oidc/src/http.rs index 25666bd09..bffbfb784 100644 --- a/crates/kitsune-oidc/src/http.rs +++ b/crates/kitsune-oidc/src/http.rs @@ -1,3 +1,4 @@ +use crate::error::ErrorWrapper; use http_body_util::BodyExt; use kitsune_http_client::Client as HttpClient; use openidconnect::{HttpRequest, HttpResponse}; @@ -6,15 +7,14 @@ use std::sync::LazyLock; static HTTP_CLIENT: LazyLock = LazyLock::new(HttpClient::default); #[inline] -pub async fn async_client(req: HttpRequest) -> Result { - let response = HTTP_CLIENT.execute(req.map(Into::into)).await?; +pub async fn async_client(req: HttpRequest) -> Result { + let response = HTTP_CLIENT + .execute(req.map(Into::into)) + .await + .map_err(|err| ErrorWrapper(err.into()))?; let (parts, body) = response.into_inner().into_parts(); - let body = body - .collect() - .await - .map_err(kitsune_http_client::Error::new)? - .to_bytes(); + let body = body.collect().await.map_err(ErrorWrapper)?.to_bytes(); Ok(HttpResponse::from_parts(parts, body.to_vec())) } diff --git a/crates/kitsune-oidc/src/lib.rs b/crates/kitsune-oidc/src/lib.rs index edf60e96b..91416e7d8 100644 --- a/crates/kitsune-oidc/src/lib.rs +++ b/crates/kitsune-oidc/src/lib.rs @@ -46,6 +46,7 @@ type OidcClient = openidconnect::Client< openidconnect::EndpointMaybeSet, >; +mod error; mod state; pub mod http; diff --git a/crates/kitsune-s3/Cargo.toml b/crates/kitsune-s3/Cargo.toml index bb238d6f6..7f852348f 100644 --- a/crates/kitsune-s3/Cargo.toml +++ b/crates/kitsune-s3/Cargo.toml @@ -13,7 +13,7 @@ kitsune-error = { workspace = true } kitsune-http-client = { workspace = true } quick-xml = { version = "0.37.0", features = ["serialize"] } rusty-s3 = "0.5.0" -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } typed-builder = "0.20.0" [dev-dependencies] diff --git a/crates/kitsune-search/Cargo.toml b/crates/kitsune-search/Cargo.toml index df6e8792a..e56f0932a 100644 --- a/crates/kitsune-search/Cargo.toml +++ b/crates/kitsune-search/Cargo.toml @@ -23,7 +23,7 @@ kitsune-http-client = { workspace = true } kitsune-language = { workspace = true } meilisearch-sdk = { version = "0.27.1", default-features = false } pin-project-lite = "0.2.15" -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } serde_urlencoded = "0.7.1" speedy-uuid = { workspace = true } strum = { version = "0.26.3", features = ["derive"] } diff --git a/crates/kitsune-service/Cargo.toml b/crates/kitsune-service/Cargo.toml index d7491e490..deb50c831 100644 --- a/crates/kitsune-service/Cargo.toml +++ b/crates/kitsune-service/Cargo.toml @@ -45,7 +45,7 @@ post-process = { workspace = true } rand = "0.8.5" rsa = "0.9.6" rusty-s3 = { version = "0.5.0", default-features = false } -serde = "1.0.214" +serde = "1.0.215" smol_str = "0.3.2" speedy-uuid = { workspace = true } tokio = { workspace = true, features = ["macros", "sync"] } 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-type/Cargo.toml b/crates/kitsune-type/Cargo.toml index 83e8d6b89..8f14bd41d 100644 --- a/crates/kitsune-type/Cargo.toml +++ b/crates/kitsune-type/Cargo.toml @@ -7,7 +7,7 @@ license.workspace = true [dependencies] iso8601-timestamp = { workspace = true } -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } serde_with = { version = "3.11.0", default-features = false, features = [ "alloc", "macros", diff --git a/crates/kitsune-wasm-mrf/Cargo.toml b/crates/kitsune-wasm-mrf/Cargo.toml index f489dfb28..edab5e44c 100644 --- a/crates/kitsune-wasm-mrf/Cargo.toml +++ b/crates/kitsune-wasm-mrf/Cargo.toml @@ -44,7 +44,7 @@ wasmtime-wasi = { version = "26.0.1", default-features = false } tempfile = "3.14.0" tokio = { workspace = true, features = ["macros", "rt"] } tracing-subscriber = "0.3.18" -wat = "1.219.1" +wat = "1.220.0" [lints] workspace = true 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-cli/Cargo.toml b/kitsune-cli/Cargo.toml index 19bc4e514..3123d1c88 100644 --- a/kitsune-cli/Cargo.toml +++ b/kitsune-cli/Cargo.toml @@ -22,7 +22,7 @@ kitsune-config = { workspace = true } kitsune-core = { workspace = true } kitsune-db = { workspace = true } kitsune-error = { workspace = true } -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } speedy-uuid = { workspace = true } tokio = { workspace = true, features = ["full"] } tracing-subscriber = "0.3.18" 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..1a29b1414 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 } @@ -75,7 +76,7 @@ oxide-auth-async = "0.2.1" oxide-auth-axum = "0.5.0" rust-embed = { version = "8.5.0", features = ["include-exclude"] } scoped-futures = "0.1.4" -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } serde_urlencoded = "0.7.1" sonic-rs = { workspace = true } simdutf8 = { 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(), diff --git a/lib/athena/Cargo.toml b/lib/athena/Cargo.toml index b47f82a7b..b8c5e69f2 100644 --- a/lib/athena/Cargo.toml +++ b/lib/athena/Cargo.toml @@ -18,7 +18,7 @@ iso8601-timestamp = { workspace = true } fred = { workspace = true, optional = true } just-retry = { workspace = true } rand = { version = "0.8.5", optional = true } -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } smol_str = "0.3.2" sonic-rs = { workspace = true, optional = true } speedy-uuid = { workspace = true, features = ["redis"] } diff --git a/lib/fast-cjson/Cargo.toml b/lib/fast-cjson/Cargo.toml index 29ae70ee7..24e099e60 100644 --- a/lib/fast-cjson/Cargo.toml +++ b/lib/fast-cjson/Cargo.toml @@ -12,7 +12,7 @@ harness = false [dependencies] icu_normalizer = "1.5.0" memchr = "2.7.4" -serde = "1.0.214" +serde = "1.0.215" sonic-rs = { workspace = true } [dev-dependencies] @@ -21,7 +21,7 @@ mimalloc = "0.1.43" olpc-cjson = "0.1.4" proptest = { version = "1.5.0", default-features = false, features = ["std"] } proptest-derive = "0.5.0" -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } serde_json = "1.0.132" [lints] diff --git a/lib/geomjeungja/Cargo.toml b/lib/geomjeungja/Cargo.toml index 368c5ca2a..1f6b58088 100644 --- a/lib/geomjeungja/Cargo.toml +++ b/lib/geomjeungja/Cargo.toml @@ -7,9 +7,9 @@ license = "MIT OR Apache-2.0" [dependencies] async-trait = "0.1.83" -hickory-resolver = "0.25.0-alpha.3" +hickory-resolver = { workspace = true } rand = "0.8.5" -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } simdutf8 = { workspace = true } thiserror = "2.0.3" tracing = "0.1.40" diff --git a/lib/geomjeungja/src/lib.rs b/lib/geomjeungja/src/lib.rs index 409982cd6..f5e87bbd4 100644 --- a/lib/geomjeungja/src/lib.rs +++ b/lib/geomjeungja/src/lib.rs @@ -8,7 +8,7 @@ use crate::util::OpaqueDebug; use async_trait::async_trait; use hickory_resolver::{ config::{ResolverConfig, ResolverOpts}, - TokioAsyncResolver, + TokioResolver, }; use rand::{ distributions::{Alphanumeric, DistString}, @@ -71,7 +71,7 @@ pub trait DnsResolver: Send + Sync { } #[async_trait] -impl DnsResolver for TokioAsyncResolver { +impl DnsResolver for TokioResolver { async fn lookup_txt(&self, fqdn: &str) -> Result, BoxError> { let records = self.txt_lookup(fqdn) @@ -160,8 +160,10 @@ impl VerificationStrategy for KeyValueStrategy { /// Construct the default resolver used by this library #[must_use] pub fn default_resolver() -> Arc { - Arc::new(TokioAsyncResolver::tokio( - ResolverConfig::default(), + Arc::new(TokioResolver::tokio( + // Per-default hickory-resolver would use Google's DNS servers. + // Since Google is kinda disgusting, we use Quad9 instead. + ResolverConfig::quad9_tls(), ResolverOpts::default(), )) .unsize(Coercion!(to dyn DnsResolver)) @@ -266,7 +268,7 @@ mod test { .strategy(dummy) .build(); - assert!(verifier.verify().await.is_ok()); + verifier.verify().await.unwrap(); } #[tokio::test] diff --git a/lib/mrf-manifest/Cargo.toml b/lib/mrf-manifest/Cargo.toml index c80876225..2d6a0e536 100644 --- a/lib/mrf-manifest/Cargo.toml +++ b/lib/mrf-manifest/Cargo.toml @@ -10,16 +10,16 @@ fast-cjson = { workspace = true, optional = true } leb128 = { version = "0.2.5", optional = true } schemars = { version = "0.8.21", features = ["impl_json_schema", "semver"] } semver = { version = "1.0.23", features = ["serde"] } -serde = { version = "1.0.214", features = ["derive"] } +serde = { version = "1.0.215", features = ["derive"] } sonic-rs = { workspace = true, optional = true } thiserror = { version = "2.0.3", optional = true } -wasm-encoder = { version = "0.219.1", optional = true } -wasmparser = { version = "0.219.1", optional = true } +wasm-encoder = { version = "0.220.0", optional = true } +wasmparser = { version = "0.220.0", optional = true } [dev-dependencies] insta = { version = "1.41.1", default-features = false, features = ["json"] } sonic-rs = { workspace = true } -wat = "1.219.1" +wat = "1.220.0" [features] decode = ["dep:leb128", "dep:sonic-rs", "dep:thiserror", "dep:wasmparser"] diff --git a/lib/mrf-tool/Cargo.toml b/lib/mrf-tool/Cargo.toml index bd307150a..2471f2939 100644 --- a/lib/mrf-tool/Cargo.toml +++ b/lib/mrf-tool/Cargo.toml @@ -16,11 +16,11 @@ mrf-manifest = { workspace = true, features = [ "serialise", ] } sonic-rs = { workspace = true } -wasmparser = "0.219.1" +wasmparser = "0.220.0" [lints] workspace = true [dev-dependencies] sonic-rs = { workspace = true } -wat = "1.219.1" +wat = "1.220.0" diff --git a/lib/speedy-uuid/Cargo.toml b/lib/speedy-uuid/Cargo.toml index 0fb985d2c..2f9912f9d 100644 --- a/lib/speedy-uuid/Cargo.toml +++ b/lib/speedy-uuid/Cargo.toml @@ -12,7 +12,7 @@ diesel = { version = "2.2.4", default-features = false, features = [ "uuid", ], optional = true } fred = { version = "9.4.0", default-features = false, optional = true } -serde = { version = "1.0.214", optional = true } +serde = { version = "1.0.215", optional = true } thiserror = "2.0.3" uuid = { version = "1.11.0", features = ["fast-rng", "v7"] } uuid-simd = { version = "0.8.0", features = ["uuid"] }