From 770575b0503f935c265de1e5f1f447b3717dd565 Mon Sep 17 00:00:00 2001 From: Ben Dean-Kawamura Date: Fri, 16 Jan 2026 11:21:43 -0500 Subject: [PATCH] Add viaduct-hyper to the iOS megazord The goal is to move iOS to viaduct-hyper, which implements the new viaduct backend. This is the step 1. Next up is switching firefox-ios to initializing `hyper` rather than `reqwest`. The last step is removing `viaduct-reqwest` from the megazord. Also, added a workaround to get the user-agent from `GLOBAL_SETTINGS` if it's not set. This replaces the `viaduct-reqwest` code that uses a hard-coded value: https://github.com/mozilla/application-services/blob/464f6ff4b0362d66bfe9213ebf42bb02f4fb447d/components/support/viaduct-reqwest/src/lib.rs#L30 Co-authored-by: Alexandre --- Cargo.lock | 2 ++ .../suggest-bench/benches/benchmark_all.rs | 4 +++- .../src/bin/debug_ingestion_sizes.rs | 2 +- components/support/nimbus-cli/src/main.rs | 2 +- components/support/viaduct-hyper/src/lib.rs | 21 +++++++++++++++++-- components/support/viaduct-hyper/uniffi.toml | 3 +++ examples/autofill-utils/src/autofill-utils.rs | 2 +- examples/example-cli/src/main.rs | 2 +- examples/fxa-client/src/main.rs | 2 +- examples/merino-cli/src/main.rs | 2 +- examples/nimbus/src/main.rs | 2 +- examples/places-utils/src/places-utils.rs | 2 +- examples/push-livetest/src/livetest.rs | 2 +- examples/relay-cli/src/main.rs | 2 +- examples/relevancy-cli/src/main.rs | 2 +- examples/remote-settings-cli/src/main.rs | 2 +- examples/suggest-cli/src/main.rs | 2 +- examples/sync-pass/src/sync-pass.rs | 2 +- examples/tabs-sync/src/tabs-sync.rs | 2 +- examples/viaduct-cli/src/main.rs | 6 +++--- megazords/ios-rust/Cargo.toml | 1 + megazords/ios-rust/focus/Cargo.toml | 1 + megazords/ios-rust/src/lib.rs | 1 + testing/sync-test/src/main.rs | 2 +- 24 files changed, 49 insertions(+), 22 deletions(-) create mode 100644 components/support/viaduct-hyper/uniffi.toml diff --git a/Cargo.lock b/Cargo.lock index e0a5865ef2..81643acf87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2609,6 +2609,7 @@ dependencies = [ "remote_settings", "rust-log-forwarder", "viaduct", + "viaduct-hyper", "viaduct-reqwest", ] @@ -2639,6 +2640,7 @@ dependencies = [ "tabs", "tracing-support", "viaduct", + "viaduct-hyper", "viaduct-reqwest", ] diff --git a/components/suggest/suggest-bench/benches/benchmark_all.rs b/components/suggest/suggest-bench/benches/benchmark_all.rs index 6cf0757aab..bff28ee7e1 100644 --- a/components/suggest/suggest-bench/benches/benchmark_all.rs +++ b/components/suggest/suggest-bench/benches/benchmark_all.rs @@ -49,7 +49,9 @@ fn run_benchmarks( fn setup_viaduct() { static INIT: Once = Once::new(); - INIT.call_once(|| viaduct_hyper::init_backend_hyper().expect("error initializing viaduct")); + INIT.call_once(|| { + viaduct_hyper::viaduct_init_backend_hyper().expect("error initializing viaduct") + }); } criterion_group!(benches, geoname, ingest, query); diff --git a/components/suggest/suggest-bench/src/bin/debug_ingestion_sizes.rs b/components/suggest/suggest-bench/src/bin/debug_ingestion_sizes.rs index fb2b022daf..75c0a9ad4a 100644 --- a/components/suggest/suggest-bench/src/bin/debug_ingestion_sizes.rs +++ b/components/suggest/suggest-bench/src/bin/debug_ingestion_sizes.rs @@ -5,6 +5,6 @@ use suggest::benchmarks::ingest; fn main() { - viaduct_hyper::init_backend_hyper().expect("Error initializing viaduct"); + viaduct_hyper::viaduct_init_backend_hyper().expect("Error initializing viaduct"); ingest::print_debug_ingestion_sizes() } diff --git a/components/support/nimbus-cli/src/main.rs b/components/support/nimbus-cli/src/main.rs index a695e327df..2c1d654982 100644 --- a/components/support/nimbus-cli/src/main.rs +++ b/components/support/nimbus-cli/src/main.rs @@ -23,7 +23,7 @@ pub(crate) static USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),); fn main() -> Result<()> { - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; let cmds = get_commands_from_cli(std::env::args_os())?; for c in cmds { let success = cmd::process_cmd(&c)?; diff --git a/components/support/viaduct-hyper/src/lib.rs b/components/support/viaduct-hyper/src/lib.rs index a83854d516..5e6b775dd3 100644 --- a/components/support/viaduct-hyper/src/lib.rs +++ b/components/support/viaduct-hyper/src/lib.rs @@ -30,8 +30,11 @@ struct HyperBackend { } /// Set the viaduct backend to the `hyper`-based one with HTTPS support. +/// +/// Named `viaduct_init_backend_hyper` since that reads better on iOS/Swift where there aren't any +/// namespaces. Once we move to UniFII 0.31 we can use the renaming feature to do this instead. #[uniffi::export] -pub fn init_backend_hyper() -> Result<()> { +pub fn viaduct_init_backend_hyper() -> Result<()> { info!("initializing hyper backend"); // Create a multi-threaded runtime, with 1 worker thread. // @@ -80,10 +83,24 @@ impl Backend for HyperBackend { /// This expects to be run in a `tokio::spawn` closure async fn make_request_inner( client: Client, - request: Request, + mut request: Request, settings: ClientSettings, ) -> Result { let mut url = request.url.clone(); + // If the user-agent isn't set, try to get it from `GLOBAL_SETTINGS`. + // This only affects consumers who aren't yet using `Client` to make their requests, since + // `Client` already does this. Once we move all consumers over, we can remove this code. + if request.headers.get("User-Agent").is_none() { + let user_agent = settings.user_agent.or_else(|| { + viaduct::settings::GLOBAL_SETTINGS + .read() + .default_user_agent + .clone() + }); + if let Some(ua) = user_agent { + request = request.header("User-Agent", ua)?; + } + } let mut resp = make_single_request(&client, request.clone()).await?; let mut redirect_count = 0; while resp.status().is_redirection() { diff --git a/components/support/viaduct-hyper/uniffi.toml b/components/support/viaduct-hyper/uniffi.toml new file mode 100644 index 0000000000..8c814ea023 --- /dev/null +++ b/components/support/viaduct-hyper/uniffi.toml @@ -0,0 +1,3 @@ +[bindings.swift] +ffi_module_name = "MozillaRustComponents" +ffi_module_filename = "viaducthyperFFI" diff --git a/examples/autofill-utils/src/autofill-utils.rs b/examples/autofill-utils/src/autofill-utils.rs index 3760fa8f51..d400312bcf 100644 --- a/examples/autofill-utils/src/autofill-utils.rs +++ b/examples/autofill-utils/src/autofill-utils.rs @@ -475,7 +475,7 @@ fn get_encryption_key(store: &Store, db_path: &str, opts: &Opts) -> Result Result<()> { nss::ensure_initialized(); - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; let opts = Opts::parse(); if !opts.no_logging { diff --git a/examples/example-cli/src/main.rs b/examples/example-cli/src/main.rs index 4f0a7783ed..3d1c16ab9e 100644 --- a/examples/example-cli/src/main.rs +++ b/examples/example-cli/src/main.rs @@ -93,7 +93,7 @@ fn main() -> ApiResult<()> { init_logging(&cli); // Applications must initialize viaduct for the HTTP client to work. // This example uses the `hyper` backend because it's easy to setup. - viaduct_hyper::init_backend_hyper().expect("Error initializing viaduct"); + viaduct_hyper::viaduct_init_backend_hyper().expect("Error initializing viaduct"); let component = build_example_component()?; println!(); match cli.command { diff --git a/examples/fxa-client/src/main.rs b/examples/fxa-client/src/main.rs index 00995f8963..ed9be39e55 100644 --- a/examples/fxa-client/src/main.rs +++ b/examples/fxa-client/src/main.rs @@ -68,7 +68,7 @@ enum Command { fn main() -> Result<()> { let cli = Cli::parse(); nss::ensure_initialized(); - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; if cli.log { if cli.debug { init_logging_with("fxa_client=debug"); diff --git a/examples/merino-cli/src/main.rs b/examples/merino-cli/src/main.rs index 00bed5480d..5f8ea3b102 100644 --- a/examples/merino-cli/src/main.rs +++ b/examples/merino-cli/src/main.rs @@ -38,7 +38,7 @@ enum Commands { fn main() -> Result<()> { let cli = Cli::parse(); - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; let config = CuratedRecommendationsConfig { base_host: cli.base_host.clone(), user_agent_header: cli.user_agent.clone(), diff --git a/examples/nimbus/src/main.rs b/examples/nimbus/src/main.rs index e1ea037530..e63319cd8d 100644 --- a/examples/nimbus/src/main.rs +++ b/examples/nimbus/src/main.rs @@ -134,7 +134,7 @@ fn main() -> Result<()> { // Possible values are "info", "debug", "warn" and "error" // Check [`env_logger`](https://docs.rs/env_logger/) for more details error_support::init_for_tests_with_level(error_support::Level::Info); - viaduct_hyper::init_backend_hyper().expect("Error initalizing viaduct"); + viaduct_hyper::viaduct_init_backend_hyper().expect("Error initalizing viaduct"); // Initiate the matches for the command line arguments let args = Args::parse(); diff --git a/examples/places-utils/src/places-utils.rs b/examples/places-utils/src/places-utils.rs index f19b50f015..3f030bb5d5 100644 --- a/examples/places-utils/src/places-utils.rs +++ b/examples/places-utils/src/places-utils.rs @@ -234,7 +234,7 @@ fn sync( nsyncs: u32, wait: u64, ) -> Result<()> { - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; let cli_fxa = get_cli_fxa(get_default_fxa_config(), &cred_file, &[SYNC_SCOPE])?; diff --git a/examples/push-livetest/src/livetest.rs b/examples/push-livetest/src/livetest.rs index 1aef02b5ca..bb746ea94c 100644 --- a/examples/push-livetest/src/livetest.rs +++ b/examples/push-livetest/src/livetest.rs @@ -14,7 +14,7 @@ use push::{BridgeType, PushConfiguration, PushManager}; */ fn test_live_server() { let tempdir = tempfile::tempdir().unwrap(); - viaduct_hyper::init_backend_hyper().expect("Error initializing viaduct"); + viaduct_hyper::viaduct_init_backend_hyper().expect("Error initializing viaduct"); let push_config = PushConfiguration { server_host: "localhost:8082".to_string(), diff --git a/examples/relay-cli/src/main.rs b/examples/relay-cli/src/main.rs index 1c9487db53..cd805a3586 100644 --- a/examples/relay-cli/src/main.rs +++ b/examples/relay-cli/src/main.rs @@ -29,7 +29,7 @@ fn main() -> anyhow::Result<()> { let cli = Cli::parse(); init_logging(&cli); - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; let token = prompt_token()?; let client = RelayClient::new("https://relay.firefox.com".to_string(), Some(token)); diff --git a/examples/relevancy-cli/src/main.rs b/examples/relevancy-cli/src/main.rs index d4e1c3fedb..28de0971d9 100644 --- a/examples/relevancy-cli/src/main.rs +++ b/examples/relevancy-cli/src/main.rs @@ -37,7 +37,7 @@ struct Cli { fn main() -> Result<()> { let cli = Cli::parse(); nss::ensure_initialized(); - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; if let Some(dir) = std::path::PathBuf::from(CREDENTIALS_PATH).parent() { std::fs::create_dir_all(dir)?; } diff --git a/examples/remote-settings-cli/src/main.rs b/examples/remote-settings-cli/src/main.rs index 4f1d98de29..561c074414 100644 --- a/examples/remote-settings-cli/src/main.rs +++ b/examples/remote-settings-cli/src/main.rs @@ -81,7 +81,7 @@ fn main() -> Result<()> { DEFAULT_LOG_FILTER }); nss::ensure_initialized(); - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; let service = build_service(&cli)?; match cli.command { Commands::Sync { collections } => sync(service, collections), diff --git a/examples/suggest-cli/src/main.rs b/examples/suggest-cli/src/main.rs index 6bd2146d3d..19684a9f3e 100644 --- a/examples/suggest-cli/src/main.rs +++ b/examples/suggest-cli/src/main.rs @@ -114,7 +114,7 @@ fn main() -> Result<()> { DEFAULT_LOG_FILTER }); nss::ensure_initialized(); - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; let store = build_store(&cli)?; match cli.command { Commands::Ingest { diff --git a/examples/sync-pass/src/sync-pass.rs b/examples/sync-pass/src/sync-pass.rs index 880d5030b8..538948d417 100644 --- a/examples/sync-pass/src/sync-pass.rs +++ b/examples/sync-pass/src/sync-pass.rs @@ -364,7 +364,7 @@ fn do_sync( #[allow(clippy::cognitive_complexity)] // FIXME fn main() -> Result<()> { cli_support::init_trace_logging(); - viaduct_hyper::init_backend_hyper().expect("Error initializing viaduct"); + viaduct_hyper::viaduct_init_backend_hyper().expect("Error initializing viaduct"); let matches = clap::Command::new("sync_pass_sql") .about("CLI login syncing tool") diff --git a/examples/tabs-sync/src/tabs-sync.rs b/examples/tabs-sync/src/tabs-sync.rs index 796be55a37..930dd7be4c 100644 --- a/examples/tabs-sync/src/tabs-sync.rs +++ b/examples/tabs-sync/src/tabs-sync.rs @@ -99,7 +99,7 @@ fn do_sync( fn main() -> Result<()> { nss::ensure_initialized(); - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; cli_support::init_logging(); let opts = Opts::parse(); diff --git a/examples/viaduct-cli/src/main.rs b/examples/viaduct-cli/src/main.rs index 525d9f681d..44d194c9e5 100644 --- a/examples/viaduct-cli/src/main.rs +++ b/examples/viaduct-cli/src/main.rs @@ -89,7 +89,7 @@ fn main() -> Result<()> { match backend_style { BackendStyle::New => { - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; let settings = ClientSettings { timeout: cli.timeout.unwrap_or(0) as u32, ..ClientSettings::default() @@ -98,7 +98,7 @@ fn main() -> Result<()> { print_response(client.send_sync(req)); } BackendStyle::Bridged => { - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; if let Some(t) = cli.timeout { set_old_global_timeout(t); } @@ -131,7 +131,7 @@ fn run_ohttp_example( match backend_style { BackendStyle::New => { - viaduct_hyper::init_backend_hyper()?; + viaduct_hyper::viaduct_init_backend_hyper()?; } BackendStyle::Bridged => { println!("OHTTP is not compatible with the bridged backend. Use --backend=new or omit the backend parameter."); diff --git a/megazords/ios-rust/Cargo.toml b/megazords/ios-rust/Cargo.toml index cb7b36a26f..56cee31221 100644 --- a/megazords/ios-rust/Cargo.toml +++ b/megazords/ios-rust/Cargo.toml @@ -11,6 +11,7 @@ crate-type = ["staticlib", "rlib"] [dependencies] rust-log-forwarder = { path = "../../components/support/rust-log-forwarder" } viaduct = { path = "../../components/viaduct", features = ["ohttp"] } +viaduct-hyper = { path = "../../components/support/viaduct-hyper" } viaduct-reqwest = { path = "../../components/support/viaduct-reqwest" } nimbus-sdk = { path = "../../components/nimbus" } crashtest = { path = "../../components/crashtest" } diff --git a/megazords/ios-rust/focus/Cargo.toml b/megazords/ios-rust/focus/Cargo.toml index 10cbf62941..8fc3ce3cbc 100644 --- a/megazords/ios-rust/focus/Cargo.toml +++ b/megazords/ios-rust/focus/Cargo.toml @@ -11,6 +11,7 @@ crate-type = ["staticlib"] [dependencies] rust-log-forwarder = { path = "../../../components/support/rust-log-forwarder" } viaduct = { path = "../../../components/viaduct" } +viaduct-hyper = { path = "../../../components/support/viaduct-hyper" } viaduct-reqwest = { path = "../../../components/support/viaduct-reqwest" } nimbus-sdk = { path = "../../../components/nimbus" } error-support = { path = "../../../components/support/error" } diff --git a/megazords/ios-rust/src/lib.rs b/megazords/ios-rust/src/lib.rs index 364c817c8d..051f6f8cf3 100644 --- a/megazords/ios-rust/src/lib.rs +++ b/megazords/ios-rust/src/lib.rs @@ -28,4 +28,5 @@ pub use sync_manager; pub use tabs; pub use tracing_support; pub use viaduct; +pub use viaduct_hyper; pub use viaduct_reqwest; diff --git a/testing/sync-test/src/main.rs b/testing/sync-test/src/main.rs index 25cbe10aaf..61315d3a69 100644 --- a/testing/sync-test/src/main.rs +++ b/testing/sync-test/src/main.rs @@ -28,7 +28,7 @@ macro_rules! cleanup_clients { } pub fn init_testing() { - viaduct_hyper::init_backend_hyper().expect("Error initializing viaduct"); + viaduct_hyper::viaduct_init_backend_hyper().expect("Error initializing viaduct"); ensure_initialized(); // Enable backtraces.