diff --git a/Cargo.lock b/Cargo.lock index a48f5a4dd8..081d174c11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1110,15 +1110,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" -[[package]] -name = "encoding_rs" -version = "0.8.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" -dependencies = [ - "cfg-if", -] - [[package]] name = "env_logger" version = "0.10.2" @@ -1464,7 +1455,6 @@ dependencies = [ "url", "viaduct", "viaduct-hyper", - "viaduct-reqwest", ] [[package]] @@ -2306,12 +2296,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ipnet" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" - [[package]] name = "is-docker" version = "0.2.0" @@ -2666,7 +2650,6 @@ dependencies = [ "rust-log-forwarder", "viaduct", "viaduct-hyper", - "viaduct-reqwest", ] [[package]] @@ -2697,7 +2680,6 @@ dependencies = [ "tracing-support", "viaduct", "viaduct-hyper", - "viaduct-reqwest", ] [[package]] @@ -3779,43 +3761,6 @@ dependencies = [ "viaduct-dev", ] -[[package]] -name = "reqwest" -version = "0.11.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" -dependencies = [ - "base64 0.21.2", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - [[package]] name = "restmail-client" version = "0.1.0" @@ -5183,6 +5128,7 @@ dependencies = [ "parking_lot", "pollster", "prost", + "rusqlite", "serde", "serde_json", "thiserror 2.0.3", @@ -5216,16 +5162,6 @@ dependencies = [ "viaduct", ] -[[package]] -name = "viaduct-reqwest" -version = "0.2.0" -dependencies = [ - "error-support", - "once_cell", - "reqwest", - "viaduct", -] - [[package]] name = "walkdir" version = "2.5.0" @@ -5293,18 +5229,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.100" @@ -5777,15 +5701,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - [[package]] name = "wit-bindgen-rt" version = "0.33.0" diff --git a/Cargo.toml b/Cargo.toml index 5a6f25c298..c8379d4d82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,6 @@ members = [ "components/support/url-macro/tests", "components/support/viaduct-dev", "components/support/viaduct-hyper", - "components/support/viaduct-reqwest", "components/sync_manager", "components/sync15", "components/tabs", @@ -139,7 +138,6 @@ default-members = [ "components/support/types", "components/support/url-macro", "components/support/url-macro/tests", - "components/support/viaduct-reqwest", "components/sync_manager", "components/sync15", "components/tabs", diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index d9936f7552..fdafbb57c3 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -37,7 +37,6 @@ the details of which are reproduced below. * [MIT License: try-lock](#mit-license-try-lock) * [MIT License: want](#mit-license-want) * [MIT License: weedle2](#mit-license-weedle2) -* [MIT License: winreg](#mit-license-winreg) * [MIT License: xshell-venv](#mit-license-xshell-venv) * [CC0-1.0 License: base16](#cc0-10-license-base16) * [ISC License: libloading](#isc-license-libloading) @@ -49,7 +48,6 @@ the details of which are reproduced below. * [Unicode-3.0 License: icu_casemap, icu_casemap_data, icu_collections, icu_locale, icu_locale_core, icu_locale_data, icu_normalizer, icu_normalizer_data, icu_properties, icu_properties_data, icu_provider, icu_segmenter, icu_segmenter_data, litemap, potential_utf, tinystr, writeable, yoke, yoke-derive, zerofrom, zerofrom-derive, zerotrie, zerovec, zerovec-derive](#unicode-30-license-icu_casemap-icu_casemap_data-icu_collections-icu_locale-icu_locale_core-icu_locale_data-icu_normalizer-icu_normalizer_data-icu_properties-icu_properties_data-icu_provider-icu_segmenter-icu_segmenter_data-litemap-potential_utf-tinystr-writeable-yoke-yoke-derive-zerofrom-zerofrom-derive-zerotrie-zerovec-zerovec-derive) * [OpenSSL License](#openssl-license) * [Optional Notice: SQLite](#optional-notice-sqlite) -* [(Apache-2.0 OR MIT) AND BSD-3-Clause License: encoding_rs](#(apache-20-or-mit)-and-bsd-3-clause-license-encoding_rs) * [(MIT OR Apache-2.0) AND Unicode-3.0 License: unicode-ident](#(mit-or-apache-20)-and-unicode-30-license-unicode-ident) ------------- ## Mozilla Public License 2.0 @@ -496,7 +494,6 @@ The following text applies to code linked from these dependencies: [fs-err](https://github.com/andrewhickman/fs-err), [futures-channel](https://github.com/rust-lang/futures-rs), [futures-core](https://github.com/rust-lang/futures-rs), -[futures-io](https://github.com/rust-lang/futures-rs), [futures-sink](https://github.com/rust-lang/futures-rs), [futures-task](https://github.com/rust-lang/futures-rs), [futures-util](https://github.com/rust-lang/futures-rs), @@ -516,7 +513,6 @@ The following text applies to code linked from these dependencies: [idna_adapter](https://github.com/hsivonen/idna_adapter), [indexmap](https://github.com/indexmap-rs/indexmap), [io-lifetimes](https://github.com/sunfishcode/io-lifetimes), -[ipnet](https://github.com/krisprice/ipnet), [itertools](https://github.com/rust-itertools/itertools), [itoa](https://github.com/dtolnay/itoa), [jna](https://github.com/java-native-access/jna), @@ -527,7 +523,6 @@ The following text applies to code linked from these dependencies: [linux-raw-sys](https://github.com/sunfishcode/linux-raw-sys), [lock_api](https://github.com/Amanieu/parking_lot), [log](https://github.com/rust-lang/log), -[mime](https://github.com/hyperium/mime), [minimal-lexical](https://github.com/Alexhuszagh/minimal-lexical), [native-tls](https://github.com/sfackler/rust-native-tls), [num-traits](https://github.com/rust-num/num-traits), @@ -557,7 +552,6 @@ The following text applies to code linked from these dependencies: [regex-automata](https://github.com/rust-lang/regex/tree/master/regex-automata), [regex-syntax](https://github.com/rust-lang/regex/tree/master/regex-syntax), [regex](https://github.com/rust-lang/regex), -[reqwest](https://github.com/seanmonstar/reqwest), [rkv](https://github.com/mozilla/rkv), [rustc-hash](https://github.com/rust-lang/rustc-hash), [rustix](https://github.com/bytecodealliance/rustix), @@ -572,7 +566,6 @@ The following text applies to code linked from these dependencies: [serde_json](https://github.com/serde-rs/json), [serde_path_to_error](https://github.com/dtolnay/path-to-error), [serde_spanned](https://github.com/toml-rs/toml), -[serde_urlencoded](https://github.com/nox/serde_urlencoded), [sha2](https://github.com/RustCrypto/hashes), [shlex](https://github.com/comex/rust-shlex), [siphasher](https://github.com/jedisct1/rust-siphash), @@ -1743,34 +1736,6 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -``` -------------- -## MIT License: winreg - -The following text applies to code linked from these dependencies: -[winreg](https://github.com/gentoo90/winreg-rs) - -``` -Copyright (c) 2015 Igor Shaula - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ``` ------------- ## MIT License: xshell-venv @@ -2418,32 +2383,6 @@ The following text applies to code linked from these dependencies: ``` This software makes use of the 'SQLite' database engine, and we are very grateful to D. Richard Hipp and team for producing it. -``` -------------- -## (Apache-2.0 OR MIT) AND BSD-3-Clause License: encoding_rs - -The following text applies to code linked from these dependencies: -[encoding_rs](https://github.com/hsivonen/encoding_rs) - -``` -encoding_rs is copyright Mozilla Foundation. - -Licensed under the Apache License, Version 2.0 - or the MIT -license , -at your option. All files in the project carrying such -notice may not be copied, modified, or distributed except -according to those terms. - -This crate includes data derived from the data files supplied -with the WHATWG Encoding Standard, which, when incorporated into -source code, are licensed under the BSD 3-Clause License -. - -Test code within encoding_rs is dedicated to the Public Domain when so -designated (see the individual files for PD/CC0-dedicated sections). - ``` ------------- ## (MIT OR Apache-2.0) AND Unicode-3.0 License: unicode-ident diff --git a/components/ads-client/src/http_cache.rs b/components/ads-client/src/http_cache.rs index a27b3b84f7..192f65657e 100644 --- a/components/ads-client/src/http_cache.rs +++ b/components/ads-client/src/http_cache.rs @@ -122,7 +122,10 @@ mod tests { use viaduct::ClientSettings; fn make_client() -> Client { - Client::new(ClientSettings::default()) + Client::new(ClientSettings { + timeout: 60000, + ..ClientSettings::default() + }) } /// Test-only hashable wrapper around Request. diff --git a/components/ads-client/src/mars/transport.rs b/components/ads-client/src/mars/transport.rs index 594ca2a7a8..a9ea74e914 100644 --- a/components/ads-client/src/mars/transport.rs +++ b/components/ads-client/src/mars/transport.rs @@ -76,10 +76,14 @@ impl MARSTransport { } fn client_for(ohttp: bool) -> Result { + let settings = ClientSettings { + timeout: 60000, + ..ClientSettings::default() + }; if ohttp { - Client::with_ohttp_channel(OHTTP_CHANNEL_ID, ClientSettings::default()) + Client::with_ohttp_channel(OHTTP_CHANNEL_ID, settings) } else { - Ok(Client::new(ClientSettings::default())) + Ok(Client::new(settings)) } } } diff --git a/components/merino/src/suggest/http.rs b/components/merino/src/suggest/http.rs index e24971485e..c2b479af73 100644 --- a/components/merino/src/suggest/http.rs +++ b/components/merino/src/suggest/http.rs @@ -70,7 +70,11 @@ impl HttpClientTrait for HttpClient { ) -> Result> { let url = build_suggest_url(query, &options, endpoint_url); - let client = Client::with_ohttp_channel("merino", ClientSettings::default())?; + let settings = ClientSettings { + timeout: 60000, + ..ClientSettings::default() + }; + let client = Client::with_ohttp_channel("merino", settings)?; let mut request = Request::get(url); request = request.header("accept", "application/json")?; diff --git a/components/support/viaduct-reqwest/Cargo.toml b/components/support/viaduct-reqwest/Cargo.toml deleted file mode 100644 index c45dd0ccc9..0000000000 --- a/components/support/viaduct-reqwest/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "viaduct-reqwest" -version = "0.2.0" -authors = ["Sync Team "] -edition = "2021" -license = "MPL-2.0" - -[lib] -crate-type = ["lib"] - -[dependencies] -error-support = { path = "../error" } -viaduct = { path = "../../viaduct" } -reqwest = { version = "0.11", features = ["blocking", "native-tls-vendored"] } -once_cell = "1.5" diff --git a/components/support/viaduct-reqwest/src/lib.rs b/components/support/viaduct-reqwest/src/lib.rs deleted file mode 100644 index 85786b63b2..0000000000 --- a/components/support/viaduct-reqwest/src/lib.rs +++ /dev/null @@ -1,118 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use error_support::{error, warn}; -use once_cell::sync::Lazy; -use std::{io::Read, sync::Once}; -use viaduct::{settings::GLOBAL_SETTINGS, OldBackend as Backend}; - -// Note: we don't `use` things from reqwest or the viaduct crate because -// it would be rather confusing given that we have the same name for -// most things as them. - -static CLIENT: Lazy = Lazy::new(|| { - let settings = GLOBAL_SETTINGS.read(); - let mut builder = reqwest::blocking::ClientBuilder::new() - .timeout(settings.read_timeout) - .connect_timeout(settings.connect_timeout) - .redirect(if settings.follow_redirects { - reqwest::redirect::Policy::default() - } else { - reqwest::redirect::Policy::none() - }); - if cfg!(target_os = "ios") { - // The FxA servers rely on the UA agent to filter - // some push messages directed to iOS devices. - // This is obviously a terrible hack and we should - // probably do https://github.com/mozilla/application-services/issues/1326 - // instead, but this will unblock us for now. - builder = builder.user_agent("Firefox-iOS-FxA/24"); - } - // Note: no cookie or cache support. - builder - .build() - .expect("Failed to initialize global reqwest::Client") -}); - -#[allow(clippy::unnecessary_wraps)] // not worth the time to untangle -fn into_reqwest( - request: viaduct::Request, -) -> Result { - let method = match request.method { - viaduct::Method::Get => reqwest::Method::GET, - viaduct::Method::Head => reqwest::Method::HEAD, - viaduct::Method::Post => reqwest::Method::POST, - viaduct::Method::Put => reqwest::Method::PUT, - viaduct::Method::Delete => reqwest::Method::DELETE, - viaduct::Method::Connect => reqwest::Method::CONNECT, - viaduct::Method::Options => reqwest::Method::OPTIONS, - viaduct::Method::Trace => reqwest::Method::TRACE, - viaduct::Method::Patch => reqwest::Method::PATCH, - }; - let mut result = reqwest::blocking::Request::new(method, request.url); - for h in request.headers { - use reqwest::header::{HeaderName, HeaderValue}; - // Unwraps should be fine, we verify these in `Header` - let value = HeaderValue::from_str(h.value()).unwrap(); - result - .headers_mut() - .insert(HeaderName::from_bytes(h.name().as_bytes()).unwrap(), value); - } - *result.body_mut() = request.body.map(reqwest::blocking::Body::from); - Ok(result) -} - -pub struct ReqwestBackend; -impl Backend for ReqwestBackend { - fn send(&self, request: viaduct::Request) -> Result { - viaduct::note_backend("reqwest (untrusted)"); - let request_method = request.method; - let req = into_reqwest(request)?; - let mut resp = CLIENT - .execute(req) - .map_err(|e| viaduct::ViaductError::NetworkError(e.to_string()))?; - let status = resp.status().as_u16(); - let url = resp.url().clone(); - let mut body = Vec::with_capacity(resp.content_length().unwrap_or_default() as usize); - resp.read_to_end(&mut body).map_err(|e| { - error!("Failed to get body from response: {:?}", e); - viaduct::ViaductError::NetworkError(e.to_string()) - })?; - let mut headers = viaduct::Headers::with_capacity(resp.headers().len()); - for (k, v) in resp.headers() { - let val = String::from_utf8_lossy(v.as_bytes()).to_string(); - let hname = match viaduct::HeaderName::new(k.as_str().to_owned()) { - Ok(name) => name, - Err(e) => { - // Ignore headers with invalid names, since nobody can look for them anyway. - warn!("Server sent back invalid header name: '{}'", e); - continue; - } - }; - // Not using Header::new since the error it returns is for request headers. - headers.insert_header(viaduct::Header::new_unchecked(hname, val)); - } - Ok(viaduct::Response { - request_method, - url, - status, - headers, - body, - }) - } -} - -static INIT_REQWEST_BACKEND: Once = Once::new(); - -pub fn use_reqwest_backend() { - INIT_REQWEST_BACKEND.call_once(|| { - viaduct::set_backend(Box::leak(Box::new(ReqwestBackend))); - }) -} - -#[no_mangle] -#[cfg(target_os = "ios")] -pub extern "C" fn viaduct_use_reqwest_backend() { - use_reqwest_backend(); -} diff --git a/components/viaduct/Cargo.toml b/components/viaduct/Cargo.toml index 2c56132f6d..f7dc024095 100644 --- a/components/viaduct/Cargo.toml +++ b/components/viaduct/Cargo.toml @@ -25,6 +25,14 @@ uniffi = { version = "0.31" } bhttp = { version = "0.7.2", optional = true } ohttp = { version = "0.7.2", features = ["client", "server", "app-svc", "external-sqlite"], default-features = false, optional = true } +# Needed because we set the `ohttp/external-sqlite` flag which means that ohttp expects cargo to +# arrange for it to be linked to `libsqlite3`. This means we need to depend on rusqlite with the +# `bundled` feature to bring it in. +# +# Without this, builds will often succeed because other crates will bring in `rusqlite`, however +# some combinations will fail. `cargo -p ads-client -p context_id` is one example (2026/06/25). +rusqlite = { version = "0.37.0", features = [ "bundled" ] } + [features] default = [] ohttp = ["dep:bhttp", "dep:ohttp"] diff --git a/components/viaduct/README.md b/components/viaduct/README.md index 4bdbadbad8..96f1bbeeb5 100644 --- a/components/viaduct/README.md +++ b/components/viaduct/README.md @@ -1,72 +1,15 @@ # Viaduct -Viaduct is our HTTP request library, which can make requests either via a -rust-based (reqwest) networking stack (used on iOS and for local desktop use, -for tests and the like), or using a stack that calls a function passed into it -over the FFI (on android). - -For usage info, you can run `cargo +nightly doc -p viaduct` (the `+nightly` is -optional, however some intra-doc links require it), it has several examples. - -## Transition from the old to new backends - -`viaduct` is currently transitioning between the older, protobuf-based code and the newer, UniFFI-based codes. -The current plan is: - -* Move applications over to using the new backend. Components will continue to use the legacy API, - which is possible because we have code to implement the old backend with the new backend. -* Move components over to the new API (the `Client` type). -* Drop support for the old backend. This means we can drop the protobuf dependency - -Note: to keep things separate, the initialization functions for new backends are always named `init_backend_[name]` -(the old backends were named `use_[name]_backend`). - -## Android/FFI Backend overview - -On Android, the backend works as follows: - -1. During megazord initialization, we are passed a `Lazy` (`Client` comes - from the [concept-fetch](https://github.com/mozilla-mobile/android-components/tree/master/components/concept/fetch) - android component, and `Lazy` is from the Kotlin stdlib). - - - It also sets a flag that indicates that even if the FFI backend never gets - fully initialized (e.g. with a callback), we should error rather than use - the reqwest backend (which should not be compiled in, however we've had - trouble ensuring this in the past, although at this point we have checks - in CI to ensure it is not present). - -2. At this point, a JNA `Callback` instance is created and passed into Rust. - - This serves to proxy the request made by Rust to the `Client`. - - The `Callback` instance is never allowed to be GCed. - - To Rust, it's just a `extern "C"` function pointer that get's stored in an - atomic variable and never can be unset. - -3. When Rust makes a request: - 1. We serialize the request info into a protobuf record - 2. This record is passed into the function pointer we should have by this - point (erroring if it has not been set yet). - 3. The callback (on the Java side now) deserializes the protobuf record, - converts it to a concept-fetch Request instance, and passes it to the - client. - 4. The response (or error) is then converted into a protobuf record. The - java code then asks Rust for a buffer big enough to hold the serialized - response (or error). - 5. The response is written to the buffer, and returned to Rust. - 6. Rust then decodes the protobuf, and converts it to a - `viaduct::Response` object that it returns to the caller. - -Some notes: - -- This "request flow" is entirely synchronous, simplifying the implementation - considerably. - -- Cookies are explicitly not supported at the moment, adding them would - require a separate security review. - -- Generally, this is the way the FFI backend is expected to work on any - platform, but for concreteness (and because it's the only one currently using - the FFI backend), we explained it for Android. - -- Most of the code in `viaduct` is defining a ergonomic HTTP facade, and is - unrelated to this (or to the reqwest backend). This code is more or less - entirely (in the Kotlin layer and) in `src/backend/ffi.rs`. +Viaduct is our HTTP request library, which allows components to make HTTP request. +Normally this means bridging to the application HTTP library. + +How the request is handled depends on the viaduct backend that the application sets up. +This can either be a Rust crate or foreign code that implements the `Backend` interface. +Here's how it works for different application: + +| Application | Backend | Notes | +|-------------|---------|-------| +| Desktop | `viaduct-necko` | Lives in the moz-central repo and forwards requests to the `necko` libary | +| Android | Kotlin-implemented | Also handled by `necko`, but there's a longer chain of bridge code. Kotlin code implements a backend by forwarding requests to the `fetch` library, which then forwards to `GeckoView` and the end result is that `necko` handles the request.| +| iOS | `viaduct-hyper` | Forwards requests to the Rust `hyper` library. Creates and manages a thread to process the requests | +| testing | `viaduct-dev` | Forwards requests to `minireq` | diff --git a/components/viaduct/android/build.gradle b/components/viaduct/android/build.gradle index 93d3850e99..c354c1ab27 100644 --- a/components/viaduct/android/build.gradle +++ b/components/viaduct/android/build.gradle @@ -1,40 +1,11 @@ -plugins { - alias libs.plugins.protobuf.plugin -} - apply from: "$appServicesRootDir/build-scripts/component-common.gradle" apply from: "$appServicesRootDir/publish.gradle" -apply plugin: 'com.google.protobuf' - android { namespace 'org.mozilla.appservices.httpconfig' - sourceSets { - main { - proto { - srcDir '../src' - } - } - } -} - -protobuf { - protoc { - artifact = libs.protobuf.compiler.get().toString() // https://github.com/google/protobuf-gradle-plugin/issues/563 - } - generateProtoTasks { - all().each { task -> - task.builtins { - java { - option "lite" - } - } - } - } } dependencies { - implementation libs.protobuf.javalite implementation libs.kotlinx.coroutines if (gradle.hasProperty("mozconfig")) { api project(':components:concept-fetch') diff --git a/components/viaduct/android/src/main/java/mozilla/appservices/httpconfig/HttpConfig.kt b/components/viaduct/android/src/main/java/mozilla/appservices/httpconfig/HttpConfig.kt index ca59ff51b6..20f5ebfef1 100644 --- a/components/viaduct/android/src/main/java/mozilla/appservices/httpconfig/HttpConfig.kt +++ b/components/viaduct/android/src/main/java/mozilla/appservices/httpconfig/HttpConfig.kt @@ -4,7 +4,6 @@ package mozilla.appservices.httpconfig -import com.google.protobuf.ByteString import mozilla.appservices.viaduct.initBackend import mozilla.components.concept.fetch.Client import mozilla.components.concept.fetch.MutableHeaders @@ -49,44 +48,4 @@ object RustHttpConfig { fun allowAndroidEmulatorLoopback() { rustAllowAndroidEmulatorLoopback() } - - internal fun convertRequest(request: MsgTypes.Request): Request { - val headers = MutableHeaders() - for (h in request.headersMap) { - headers.append(h.key, h.value) - } - return Request( - url = request.url, - method = convertMethod(request.method), - headers = headers, - connectTimeout = Pair(request.connectTimeoutSecs.toLong(), TimeUnit.SECONDS), - readTimeout = Pair(request.readTimeoutSecs.toLong(), TimeUnit.SECONDS), - body = if (request.hasBody()) { - Request.Body(request.body.newInput()) - } else { - null - }, - redirect = if (request.followRedirects) { - Request.Redirect.FOLLOW - } else { - Request.Redirect.MANUAL - }, - cookiePolicy = Request.CookiePolicy.OMIT, - useCaches = request.useCaches, - ) - } -} - -internal fun convertMethod(m: MsgTypes.Request.Method): Request.Method { - return when (m) { - MsgTypes.Request.Method.GET -> Request.Method.GET - MsgTypes.Request.Method.POST -> Request.Method.POST - MsgTypes.Request.Method.HEAD -> Request.Method.HEAD - MsgTypes.Request.Method.OPTIONS -> Request.Method.OPTIONS - MsgTypes.Request.Method.DELETE -> Request.Method.DELETE - MsgTypes.Request.Method.PUT -> Request.Method.PUT - MsgTypes.Request.Method.TRACE -> Request.Method.TRACE - MsgTypes.Request.Method.CONNECT -> Request.Method.CONNECT - else -> throw UnsupportedRequestMethodError(m.toString()) - } } diff --git a/components/viaduct/src/backend.rs b/components/viaduct/src/backend.rs index cc0b409cff..60ff9650cf 100644 --- a/components/viaduct/src/backend.rs +++ b/components/viaduct/src/backend.rs @@ -1,44 +1,32 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this +* * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use crate::{info, settings::validate_request, trace}; -use ffi::FfiBackend; -use once_cell::sync::OnceCell; -mod ffi; +use std::sync::{Arc, OnceLock}; -pub fn note_backend(which: &str) { - // If trace logs are enabled: log on every request. Otherwise, just log on - // the first request at `info` level. We remember if the Once was triggered - // to avoid logging twice in the first case. - static NOTE_BACKEND_ONCE: std::sync::Once = std::sync::Once::new(); - let mut called = false; - NOTE_BACKEND_ONCE.call_once(|| { - info!("Using HTTP backend {}", which); - called = true; - }); - if !called { - trace!("Using HTTP backend {}", which); - } -} +use crate::{ClientSettings, Request, Response, Result, ViaductError}; +#[uniffi::export(with_foreign)] +#[async_trait::async_trait] pub trait Backend: Send + Sync + 'static { - fn send(&self, request: crate::Request) -> Result; + async fn send_request(&self, request: Request, settings: ClientSettings) -> Result; } -static BACKEND: OnceCell<&'static dyn Backend> = OnceCell::new(); +static REGISTERED_BACKEND: OnceLock> = OnceLock::new(); -pub fn set_backend(b: &'static dyn Backend) { - // Ignore errors when setting the OnceCell multiple times. - // `new_backend::init_backend` will catch and report these. - let _ = BACKEND.set(b); -} - -pub(crate) fn get_backend() -> &'static dyn Backend { - *BACKEND.get_or_init(|| Box::leak(Box::new(FfiBackend))) +#[uniffi::export] +pub fn init_backend(backend: Arc) { + if REGISTERED_BACKEND.set(backend).is_err() { + error_support::report_error!( + "viaduct-multiple-init-backend", + "init_backend called multiple times" + ); + } } -pub fn send(request: crate::Request) -> Result { - validate_request(&request)?; - get_backend().send(request) +pub fn get_backend() -> Result<&'static Arc> { + REGISTERED_BACKEND + .get() + .ok_or(ViaductError::BackendNotInitialized) } diff --git a/components/viaduct/src/backend/ffi.rs b/components/viaduct/src/backend/ffi.rs deleted file mode 100644 index c8b502e00f..0000000000 --- a/components/viaduct/src/backend/ffi.rs +++ /dev/null @@ -1,209 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -use crate::{ - backend::Backend, - settings::{allow_android_emulator_loopback, GLOBAL_SETTINGS}, -}; -use crate::{error, msg_types, warn, ViaductError}; -use ffi_support::{ByteBuffer, FfiStr}; - -ffi_support::implement_into_ffi_by_protobuf!(msg_types::Request); - -impl From for msg_types::Request { - fn from(request: crate::Request) -> Self { - let settings = GLOBAL_SETTINGS.read(); - msg_types::Request { - url: request.url.to_string(), - body: request.body, - // Real weird that this needs to be specified as an i32, but - // it certainly makes it convenient for us... - method: request.method as i32, - headers: request.headers.into(), - follow_redirects: settings.follow_redirects, - use_caches: settings.use_caches, - connect_timeout_secs: settings.connect_timeout.map_or(0, |d| d.as_secs() as i32), - read_timeout_secs: settings.read_timeout.map_or(0, |d| d.as_secs() as i32), - } - } -} - -macro_rules! backend_error { - ($($args:tt)*) => {{ - let msg = format!($($args)*); - error!("{}", msg); - ViaductError::BackendError(msg) - }}; -} - -pub struct FfiBackend; -impl Backend for FfiBackend { - fn send(&self, request: crate::Request) -> Result { - use ffi_support::IntoFfi; - use prost::Message; - super::note_backend("FFI (trusted)"); - - let method = request.method; - let fetch = callback_holder::get_callback().ok_or(ViaductError::BackendNotInitialized)?; - let proto_req: msg_types::Request = request.into(); - let buf = proto_req.into_ffi_value(); - let response = unsafe { fetch(buf) }; - // This way we'll Drop it if we panic, unlike if we just got a slice into - // it. Besides, we already own it. - let response_bytes = response.destroy_into_vec(); - - let response: msg_types::Response = match Message::decode(response_bytes.as_slice()) { - Ok(v) => v, - Err(e) => { - panic!( - "Failed to parse protobuf returned from fetch callback! {}", - e - ); - } - }; - - if let Some(exn) = response.exception_message { - return Err(ViaductError::NetworkError(format!("Java error: {:?}", exn))); - } - let status = response - .status - .ok_or_else(|| backend_error!("Missing HTTP status"))?; - - if status < 0 || status > i32::from(u16::MAX) { - return Err(backend_error!("Illegal HTTP status: {}", status)); - } - - let mut headers = crate::Headers::with_capacity(response.headers.len()); - for (name, val) in response.headers { - let hname = match crate::HeaderName::new(name) { - Ok(name) => name, - Err(e) => { - // Ignore headers with invalid names, since nobody can look for them anyway. - warn!("Server sent back invalid header name: '{}'", e); - continue; - } - }; - // Not using Header::new since the error it returns is for request headers. - headers.insert_header(crate::Header::new_unchecked(hname, val)); - } - - let url = url::Url::parse( - &response - .url - .ok_or_else(|| backend_error!("Response has no URL"))?, - ) - .map_err(|e| backend_error!("Response has illegal URL: {}", e))?; - - Ok(crate::Response { - url, - request_method: method, - body: response.body.unwrap_or_default(), - status: status as u16, - headers, - }) - } -} - -/// Type of the callback we need callers on the other side of the FFI to -/// provide. -/// -/// Takes and returns a ffi_support::ByteBuffer. (TODO: it would be nice if we could -/// make this take/return pointers, so that we could use JNA direct mapping. Maybe -/// we need some kind of ThinBuffer?) -/// -/// This is a bit weird, since it requires us to allow code on the other side of -/// the FFI to allocate a ByteBuffer from us, but it works. -/// -/// The code on the other side of the FFI is responsible for freeing the ByteBuffer -/// it's passed using `viaduct_destroy_bytebuffer`. -type FetchCallback = unsafe extern "C" fn(ByteBuffer) -> ByteBuffer; - -/// Module that manages get/set of the global fetch callback pointer. -mod callback_holder { - use super::FetchCallback; - use crate::error; - use std::sync::atomic::{AtomicUsize, Ordering}; - - /// Note: We only assign to this once. - static CALLBACK_PTR: AtomicUsize = AtomicUsize::new(0); - - // Overly-paranoid sanity checking to ensure that these types are - // convertible between each-other. `transmute` actually should check this for - // us too, but this helps document the invariants we rely on in this code. - // - // Note that these are guaranteed by - // https://rust-lang.github.io/unsafe-code-guidelines/layout/function-pointers.html - // and thus this is a little paranoid. - ffi_support::static_assert!( - STATIC_ASSERT_USIZE_EQ_FUNC_SIZE, - std::mem::size_of::() == std::mem::size_of::() - ); - - ffi_support::static_assert!( - STATIC_ASSERT_USIZE_EQ_OPT_FUNC_SIZE, - std::mem::size_of::() == std::mem::size_of::>() - ); - - /// Get the function pointer to the FetchCallback. Panics if the callback - /// has not yet been initialized. - pub(super) fn get_callback() -> Option { - let ptr_value = CALLBACK_PTR.load(Ordering::SeqCst); - unsafe { std::mem::transmute::>(ptr_value) } - } - - /// Set the function pointer to the FetchCallback. Returns false if we did nothing because the callback had already been initialized - pub(super) fn set_callback(h: FetchCallback) -> bool { - let as_usize = h as usize; - match CALLBACK_PTR.compare_exchange(0, as_usize, Ordering::SeqCst, Ordering::SeqCst) { - Ok(_) => true, - Err(_) => { - // This is an internal bug, the other side of the FFI should ensure - // it sets this only once. Note that this is actually going to be - // before logging is initialized in practice, so there's not a lot - // we can actually do here. - error!("Bug: Initialized CALLBACK_PTR multiple times"); - false - } - } - } -} - -/// Return a ByteBuffer of the requested size. This is used to store the -/// response from the callback. -#[no_mangle] -pub extern "C" fn viaduct_alloc_bytebuffer(sz: i32) -> ByteBuffer { - let mut error = ffi_support::ExternError::default(); - let buffer = - ffi_support::call_with_output(&mut error, || ByteBuffer::new_with_size(sz.max(0) as usize)); - error.consume_and_log_if_error(); - buffer -} - -#[no_mangle] -pub extern "C" fn viaduct_log_error(s: FfiStr<'_>) { - let mut error = ffi_support::ExternError::default(); - ffi_support::call_with_output(&mut error, || error!("Viaduct Ffi Error: {}", s.as_str())); - error.consume_and_log_if_error(); -} - -#[no_mangle] -pub extern "C" fn viaduct_initialize(callback: FetchCallback) -> u8 { - ffi_support::abort_on_panic::call_with_output(|| callback_holder::set_callback(callback)) -} - -/// Allows connections to the hard-coded address the Android Emulator uses for -/// localhost. It would be easy to support allowing the address to be passed in, -/// but we've made a decision to avoid that possible footgun. The expectation is -/// that this will only be called in debug builds or if the app can determine it -/// is in the emulator, but the Rust code doesn't know that, so we can't check. -#[no_mangle] -pub extern "C" fn viaduct_allow_android_emulator_loopback() { - let mut error = ffi_support::ExternError::default(); - ffi_support::call_with_output(&mut error, || { - allow_android_emulator_loopback(); - }); - error.consume_and_log_if_error(); -} - -ffi_support::define_bytebuffer_destructor!(viaduct_destroy_bytebuffer); diff --git a/components/viaduct/src/client.rs b/components/viaduct/src/client.rs index 5b40ddf1d2..6513da66e5 100644 --- a/components/viaduct/src/client.rs +++ b/components/viaduct/src/client.rs @@ -3,16 +3,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::{ + backend::get_backend, header_names::USER_AGENT, - new_backend::get_backend, settings::{validate_request, GLOBAL_SETTINGS}, Request, Response, Result, }; /// HTTP Client -/// -/// This represents the "new" API. -/// See `README.md` for details about the transition from the old to new API. #[derive(Default)] pub struct Client { settings: ClientSettings, diff --git a/components/viaduct/src/fetch_msg_types.proto b/components/viaduct/src/fetch_msg_types.proto deleted file mode 100644 index 96963cef42..0000000000 --- a/components/viaduct/src/fetch_msg_types.proto +++ /dev/null @@ -1,42 +0,0 @@ -syntax = "proto2"; - -// Note: this file name must be unique due to how the iOS megazord works :( - -package mozilla.appservices.httpconfig.protobuf; - -option java_package = "mozilla.appservices.httpconfig"; -option java_outer_classname = "MsgTypes"; -option swift_prefix = "MsgTypes_"; -option optimize_for = LITE_RUNTIME; - -message Request { - enum Method { - GET = 0; - HEAD = 1; - POST = 2; - PUT = 3; - DELETE = 4; - CONNECT = 5; - OPTIONS = 6; - TRACE = 7; - PATCH = 8; - } - required Method method = 1; - required string url = 2; - optional bytes body = 3; - map headers = 4; - required bool follow_redirects = 5; - required bool use_caches = 6; - required int32 connect_timeout_secs = 7; - required int32 read_timeout_secs = 8; -} - -message Response { - // If this is present, nothing else is. - optional string exception_message = 1; - optional string url = 2; - optional int32 status = 3; - optional bytes body = 4; - map headers = 5; -} - diff --git a/components/viaduct/src/lib.rs b/components/viaduct/src/lib.rs index a29d19f6ed..72315e853c 100644 --- a/components/viaduct/src/lib.rs +++ b/components/viaduct/src/lib.rs @@ -5,6 +5,11 @@ #![allow(unknown_lints)] #![warn(rust_2018_idioms)] +// Force linking to `rusqlite` even though we don't use it directly. +// See `Cargo.toml` for why this is needed. +#[allow(unused_extern_crates)] +extern crate rusqlite; + use url::Url; #[macro_use] mod headers; @@ -12,7 +17,6 @@ mod headers; mod backend; mod client; pub mod error; -mod new_backend; #[cfg(feature = "ohttp")] pub mod ohttp; #[cfg(feature = "ohttp")] @@ -22,19 +26,13 @@ pub use error::*; // reexport logging helpers. pub use error_support::{debug, error, info, trace, warn}; -pub use backend::{note_backend, set_backend, Backend as OldBackend}; +pub use backend::{init_backend, Backend}; pub use client::{Client, ClientSettings}; pub use headers::{consts as header_names, Header, HeaderName, Headers, InvalidHeaderName}; -pub use new_backend::{init_backend, Backend}; #[cfg(feature = "ohttp")] pub use ohttp::{clear_ohttp_channels, configure_ohttp_channel, list_ohttp_channels, OhttpConfig}; pub use settings::{allow_android_emulator_loopback, GLOBAL_SETTINGS}; -#[allow(clippy::derive_partial_eq_without_eq)] -pub(crate) mod msg_types { - include!("mozilla.appservices.httpconfig.protobuf.rs"); -} - /// HTTP Methods. /// /// The supported methods are the limited to what's supported by android-components. @@ -85,7 +83,7 @@ pub struct Request { impl Request { /// Construct a new request to the given `url` using the given `method`. - /// Note that the request is not made until `send()` is called. + /// Note that the request is not made until passed to [Client::send]. pub fn new(method: Method, url: Url) -> Self { Self { method, @@ -95,8 +93,12 @@ impl Request { } } + /// Send this request + /// + /// Note: newer code is encouraged to construct a `Client` instance and use that to send + /// requests. pub fn send(self) -> Result { - crate::backend::send(self) + Client::default().send_sync(self) } /// Alias for `Request::new(Method::Get, url)`, for convenience. diff --git a/components/viaduct/src/mozilla.appservices.httpconfig.protobuf.rs b/components/viaduct/src/mozilla.appservices.httpconfig.protobuf.rs deleted file mode 100644 index cee0cd2c75..0000000000 --- a/components/viaduct/src/mozilla.appservices.httpconfig.protobuf.rs +++ /dev/null @@ -1,101 +0,0 @@ -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Request { - #[prost(enumeration = "request::Method", required, tag = "1")] - pub method: i32, - #[prost(string, required, tag = "2")] - pub url: ::prost::alloc::string::String, - #[prost(bytes = "vec", optional, tag = "3")] - pub body: ::core::option::Option<::prost::alloc::vec::Vec>, - #[prost(map = "string, string", tag = "4")] - pub headers: ::std::collections::HashMap< - ::prost::alloc::string::String, - ::prost::alloc::string::String, - >, - #[prost(bool, required, tag = "5")] - pub follow_redirects: bool, - #[prost(bool, required, tag = "6")] - pub use_caches: bool, - #[prost(int32, required, tag = "7")] - pub connect_timeout_secs: i32, - #[prost(int32, required, tag = "8")] - pub read_timeout_secs: i32, -} -/// Nested message and enum types in `Request`. -pub mod request { - #[derive( - Clone, - Copy, - Debug, - PartialEq, - Eq, - Hash, - PartialOrd, - Ord, - ::prost::Enumeration - )] - #[repr(i32)] - pub enum Method { - Get = 0, - Head = 1, - Post = 2, - Put = 3, - Delete = 4, - Connect = 5, - Options = 6, - Trace = 7, - Patch = 8, - } - impl Method { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - Method::Get => "GET", - Method::Head => "HEAD", - Method::Post => "POST", - Method::Put => "PUT", - Method::Delete => "DELETE", - Method::Connect => "CONNECT", - Method::Options => "OPTIONS", - Method::Trace => "TRACE", - Method::Patch => "PATCH", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "GET" => Some(Self::Get), - "HEAD" => Some(Self::Head), - "POST" => Some(Self::Post), - "PUT" => Some(Self::Put), - "DELETE" => Some(Self::Delete), - "CONNECT" => Some(Self::Connect), - "OPTIONS" => Some(Self::Options), - "TRACE" => Some(Self::Trace), - "PATCH" => Some(Self::Patch), - _ => None, - } - } - } -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Response { - /// If this is present, nothing else is. - #[prost(string, optional, tag = "1")] - pub exception_message: ::core::option::Option<::prost::alloc::string::String>, - #[prost(string, optional, tag = "2")] - pub url: ::core::option::Option<::prost::alloc::string::String>, - #[prost(int32, optional, tag = "3")] - pub status: ::core::option::Option, - #[prost(bytes = "vec", optional, tag = "4")] - pub body: ::core::option::Option<::prost::alloc::vec::Vec>, - #[prost(map = "string, string", tag = "5")] - pub headers: ::std::collections::HashMap< - ::prost::alloc::string::String, - ::prost::alloc::string::String, - >, -} diff --git a/components/viaduct/src/new_backend.rs b/components/viaduct/src/new_backend.rs deleted file mode 100644 index 18ab822f7a..0000000000 --- a/components/viaduct/src/new_backend.rs +++ /dev/null @@ -1,61 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this -* - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// Right now we're in a transition period where we have 2 backend traits. The old `Backend` -// trait is defined in `backend.rs` and the new `Backend` trait is bdefined here -// -// The new backend trait has a few of improvements to the old backend trait: -// - UniFFI-compatible -// - async-based -// - Inputs per-request settings for things like timeouts, rather than using global values -// -// See `README.md` for details about the transition from the old to new API. - -use std::sync::{Arc, OnceLock}; - -use crate::{ - backend as old_backend, settings::GLOBAL_SETTINGS, ClientSettings, Request, Response, Result, - ViaductError, -}; - -#[uniffi::export(with_foreign)] -#[async_trait::async_trait] -pub trait Backend: Send + Sync + 'static { - async fn send_request(&self, request: Request, settings: ClientSettings) -> Result; -} - -static REGISTERED_BACKEND: OnceLock> = OnceLock::new(); - -#[uniffi::export] -pub fn init_backend(backend: Arc) { - old_backend::set_backend(Box::leak(Box::new(backend.clone()))); - if REGISTERED_BACKEND.set(backend).is_err() { - error_support::report_error!( - "viaduct-multiple-init-backend", - "init_backend called multiple times" - ); - } -} - -pub fn get_backend() -> Result<&'static Arc> { - REGISTERED_BACKEND - .get() - .ok_or(ViaductError::BackendNotInitialized) -} - -impl old_backend::Backend for Arc { - fn send(&self, request: crate::Request) -> Result { - let settings = GLOBAL_SETTINGS.read(); - let client_settings = ClientSettings { - timeout: match settings.read_timeout { - Some(d) => d.as_millis() as u32, - None => 0, - }, - redirect_limit: if settings.follow_redirects { 10 } else { 0 }, - ..ClientSettings::default() - }; - pollster::block_on(self.send_request(request, client_settings)) - } -} diff --git a/components/viaduct/src/ohttp.rs b/components/viaduct/src/ohttp.rs index f6b9dc43b0..41f088410c 100644 --- a/components/viaduct/src/ohttp.rs +++ b/components/viaduct/src/ohttp.rs @@ -11,25 +11,10 @@ use url::Url; use crate::{Headers, Method, Request, Response, Result, ViaductError}; -/// Send a request using either the new backend or the old backend. -/// -/// This function provides compatibility with both backend systems: -/// - If the new backend is initialized, it uses it with the provided settings -/// - Otherwise, it falls back to the old backend (which uses global settings) -/// -/// Note: When using the old backend, the `settings` parameter is ignored and -/// global settings from `GLOBAL_SETTINGS` are used instead. +/// Send an OHTTP-enabled request async fn send_request(request: Request, settings: crate::ClientSettings) -> Result { - // Try to use the new backend first - if let Ok(backend) = crate::new_backend::get_backend() { - return backend.send_request(request, settings).await; - } - - // Fall back to the old backend (synchronous, uses global settings) - crate::trace!( - "OHTTP: Using old backend (global settings will be used instead of per-request settings)" - ); - crate::backend::send(request) + let backend = crate::backend::get_backend()?; + backend.send_request(request, settings).await } /// Configuration for an OHTTP channel diff --git a/components/viaduct/src/settings.rs b/components/viaduct/src/settings.rs index 6367f21112..fcd3a60dfe 100644 --- a/components/viaduct/src/settings.rs +++ b/components/viaduct/src/settings.rs @@ -4,7 +4,6 @@ use once_cell::sync::Lazy; use parking_lot::RwLock; -use std::time::Duration; use url::Url; /// Note: reqwest allows these only to be specified per-Client. concept-fetch @@ -19,32 +18,13 @@ use url::Url; #[derive(Debug)] #[non_exhaustive] pub struct Settings { - pub read_timeout: Option, - pub connect_timeout: Option, - pub follow_redirects: bool, - pub use_caches: bool, pub default_user_agent: Option, - // For testing purposes, we allow exactly one additional Url which is - // allowed to not be https. - // - // Note: this is the only setting the new backend code uses. Once all applications have moved - // away from the legacy backend, we can delete all other fields. pub addn_allowed_insecure_url: Option, } -#[cfg(target_os = "ios")] -const TIMEOUT_DURATION: Duration = Duration::from_secs(7); - -#[cfg(not(target_os = "ios"))] -const TIMEOUT_DURATION: Duration = Duration::from_secs(10); - // The singleton instance of our settings. pub static GLOBAL_SETTINGS: Lazy> = Lazy::new(|| { RwLock::new(Settings { - read_timeout: Some(TIMEOUT_DURATION), - connect_timeout: Some(TIMEOUT_DURATION), - follow_redirects: true, - use_caches: false, default_user_agent: None, addn_allowed_insecure_url: None, }) diff --git a/examples/viaduct-cli/Cargo.toml b/examples/viaduct-cli/Cargo.toml index 6ca11ee1f4..c3c19e34c6 100644 --- a/examples/viaduct-cli/Cargo.toml +++ b/examples/viaduct-cli/Cargo.toml @@ -11,8 +11,7 @@ serde_json = "1" url = "2" viaduct = { path = "../../components/viaduct", features = ["ohttp"] } viaduct-hyper = { path = "../../components/support/viaduct-hyper" } -viaduct-reqwest = { path = "../../components/support/viaduct-reqwest" } -clap = {version = "4.2", default-features = false, features = ["std", "derive"]} +clap = {version = "4.2", default-features = false, features = ["std", "derive", "help"]} cli-support = { path = "../cli-support" } [features] diff --git a/examples/viaduct-cli/src/main.rs b/examples/viaduct-cli/src/main.rs index e221b90b6c..e3b2976267 100644 --- a/examples/viaduct-cli/src/main.rs +++ b/examples/viaduct-cli/src/main.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use clap::{Parser, Subcommand, ValueEnum}; +use clap::{Parser, Subcommand}; use url::Url; #[cfg(feature = "ohttp")] use viaduct::{configure_ohttp_channel, OhttpConfig}; @@ -15,10 +15,6 @@ struct Cli { #[arg(short, long)] verbose: bool, - /// Backend style - #[arg(short, long)] - backend: Option, - /// Set a request timeout (ms) #[arg(short, long)] timeout: Option, @@ -58,16 +54,6 @@ enum Commands { }, } -#[derive(Clone, Debug, ValueEnum)] -enum BackendStyle { - /// New backend: use the new async Backend trait - New, - /// Bridged backend: initialize the new backend, but use the old API - Bridged, - /// Old backend: use only the old sync Backend trait (reqwest-based) - Old, -} - fn main() -> Result<()> { let cli = Cli::parse(); @@ -79,7 +65,6 @@ fn main() -> Result<()> { }); println!("{cli:?}"); - let backend_style = cli.backend.unwrap_or(BackendStyle::New); match cli.command { Commands::Request { post } => { @@ -89,31 +74,13 @@ fn main() -> Result<()> { make_request()? }; - match backend_style { - BackendStyle::New => { - viaduct_hyper::viaduct_init_backend_hyper(); - let settings = ClientSettings { - timeout: cli.timeout.unwrap_or(0) as u32, - ..ClientSettings::default() - }; - let client = Client::new(settings); - print_response(client.send_sync(req)); - } - BackendStyle::Bridged => { - viaduct_hyper::viaduct_init_backend_hyper(); - if let Some(t) = cli.timeout { - set_old_global_timeout(t); - } - print_response(req.send()); - } - BackendStyle::Old => { - viaduct_reqwest::use_reqwest_backend(); - if let Some(t) = cli.timeout { - set_old_global_timeout(t); - } - print_response(req.send()); - } - } + viaduct_hyper::viaduct_init_backend_hyper(); + let settings = ClientSettings { + timeout: cli.timeout.unwrap_or(0) as u32, + ..ClientSettings::default() + }; + let client = Client::new(settings); + print_response(client.send_sync(req)); } #[cfg(feature = "ohttp")] Commands::Ohttp { @@ -121,7 +88,7 @@ fn main() -> Result<()> { gateway_host, channel, } => { - return run_ohttp_example(relay_url, gateway_host, channel, backend_style); + return run_ohttp_example(relay_url, gateway_host, channel); } } @@ -129,28 +96,10 @@ fn main() -> Result<()> { } #[cfg(feature = "ohttp")] -fn run_ohttp_example( - relay_url: String, - gateway_host: String, - channel: String, - backend_style: BackendStyle, -) -> Result<()> { +fn run_ohttp_example(relay_url: String, gateway_host: String, channel: String) -> Result<()> { // Step 1: Initialize viaduct backend println!("Initializing viaduct backend..."); - - match backend_style { - BackendStyle::New | BackendStyle::Bridged => { - println!("Using new/bridged backend (hyper-based)"); - viaduct_hyper::viaduct_init_backend_hyper(); - } - BackendStyle::Old => { - println!("Using old backend (reqwest-based, global settings will be used)"); - viaduct_reqwest::use_reqwest_backend(); - // Set reasonable global settings for OHTTP - set_old_global_timeout(30000); // 30 second timeout - } - } - + viaduct_hyper::viaduct_init_backend_hyper(); println!("Backend initialized successfully"); // Step 2: Configure the OHTTP channel @@ -183,14 +132,8 @@ fn run_ohttp_example( Ok(()) } -fn set_old_global_timeout(timeout: u64) { - let mut s = viaduct::settings::GLOBAL_SETTINGS.write(); - s.connect_timeout = Some(std::time::Duration::from_millis(timeout)); - s.read_timeout = Some(std::time::Duration::from_millis(timeout)); -} - fn make_request() -> Result { - let url = Url::parse("https://httpbun.org/anything")?; + let url = Url::parse("https://httpbun.com/anything")?; let mut req = Request::new(Method::Get, url); req = req.header(header_names::USER_AGENT, "viaduct-cli")?; Ok(req) @@ -203,7 +146,7 @@ struct TestPostData { } fn make_post_request() -> Result { - let url = Url::parse("https://httpbun.org/anything")?; + let url = Url::parse("https://httpbun.com/anything")?; let mut req = Request::new(Method::Post, url); req = req.header(header_names::USER_AGENT, "viaduct-cli")?; let req = req.json(&TestPostData { diff --git a/megazords/ios-rust/Cargo.toml b/megazords/ios-rust/Cargo.toml index ccb475cca6..a44e55f4fc 100644 --- a/megazords/ios-rust/Cargo.toml +++ b/megazords/ios-rust/Cargo.toml @@ -12,7 +12,6 @@ crate-type = ["staticlib", "rlib"] 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" } fxa-client = { path = "../../components/fxa-client" } diff --git a/megazords/ios-rust/DEPENDENCIES.md b/megazords/ios-rust/DEPENDENCIES.md index 6eacc6f285..ed72e59f00 100644 --- a/megazords/ios-rust/DEPENDENCIES.md +++ b/megazords/ios-rust/DEPENDENCIES.md @@ -44,7 +44,6 @@ the details of which are reproduced below. * [Zlib License: foldhash](#zlib-license-foldhash) * [Unicode-3.0 License: icu_casemap, icu_casemap_data, icu_collections, icu_locale, icu_locale_core, icu_locale_data, icu_normalizer, icu_normalizer_data, icu_properties, icu_properties_data, icu_provider, icu_segmenter, icu_segmenter_data, litemap, potential_utf, tinystr, writeable, yoke, yoke-derive, zerofrom, zerofrom-derive, zerotrie, zerovec, zerovec-derive](#unicode-30-license-icu_casemap-icu_casemap_data-icu_collections-icu_locale-icu_locale_core-icu_locale_data-icu_normalizer-icu_normalizer_data-icu_properties-icu_properties_data-icu_provider-icu_segmenter-icu_segmenter_data-litemap-potential_utf-tinystr-writeable-yoke-yoke-derive-zerofrom-zerofrom-derive-zerotrie-zerovec-zerovec-derive) * [Optional Notice: SQLite](#optional-notice-sqlite) -* [(Apache-2.0 OR MIT) AND BSD-3-Clause License: encoding_rs](#(apache-20-or-mit)-and-bsd-3-clause-license-encoding_rs) * [(MIT OR Apache-2.0) AND Unicode-3.0 License: unicode-ident](#(mit-or-apache-20)-and-unicode-30-license-unicode-ident) ------------- ## Mozilla Public License 2.0 @@ -487,7 +486,6 @@ The following text applies to code linked from these dependencies: [fs-err](https://github.com/andrewhickman/fs-err), [futures-channel](https://github.com/rust-lang/futures-rs), [futures-core](https://github.com/rust-lang/futures-rs), -[futures-io](https://github.com/rust-lang/futures-rs), [futures-sink](https://github.com/rust-lang/futures-rs), [futures-task](https://github.com/rust-lang/futures-rs), [futures-util](https://github.com/rust-lang/futures-rs), @@ -507,7 +505,6 @@ The following text applies to code linked from these dependencies: [idna_adapter](https://github.com/hsivonen/idna_adapter), [indexmap](https://github.com/indexmap-rs/indexmap), [io-lifetimes](https://github.com/sunfishcode/io-lifetimes), -[ipnet](https://github.com/krisprice/ipnet), [itertools](https://github.com/rust-itertools/itertools), [itoa](https://github.com/dtolnay/itoa), [lalrpop-util](https://github.com/lalrpop/lalrpop), @@ -516,7 +513,6 @@ The following text applies to code linked from these dependencies: [libm](https://github.com/rust-lang/libm), [lock_api](https://github.com/Amanieu/parking_lot), [log](https://github.com/rust-lang/log), -[mime](https://github.com/hyperium/mime), [minimal-lexical](https://github.com/Alexhuszagh/minimal-lexical), [native-tls](https://github.com/sfackler/rust-native-tls), [num-traits](https://github.com/rust-num/num-traits), @@ -542,7 +538,6 @@ The following text applies to code linked from these dependencies: [regex-automata](https://github.com/rust-lang/regex/tree/master/regex-automata), [regex-syntax](https://github.com/rust-lang/regex/tree/master/regex-syntax), [regex](https://github.com/rust-lang/regex), -[reqwest](https://github.com/seanmonstar/reqwest), [rkv](https://github.com/mozilla/rkv), [rustc-hash](https://github.com/rust-lang/rustc-hash), [rustix](https://github.com/bytecodealliance/rustix), @@ -557,7 +552,6 @@ The following text applies to code linked from these dependencies: [serde_json](https://github.com/serde-rs/json), [serde_path_to_error](https://github.com/dtolnay/path-to-error), [serde_spanned](https://github.com/toml-rs/toml), -[serde_urlencoded](https://github.com/nox/serde_urlencoded), [sha2](https://github.com/RustCrypto/hashes), [shlex](https://github.com/comex/rust-shlex), [siphasher](https://github.com/jedisct1/rust-siphash), @@ -2143,32 +2137,6 @@ The following text applies to code linked from these dependencies: ``` This software makes use of the 'SQLite' database engine, and we are very grateful to D. Richard Hipp and team for producing it. -``` -------------- -## (Apache-2.0 OR MIT) AND BSD-3-Clause License: encoding_rs - -The following text applies to code linked from these dependencies: -[encoding_rs](https://github.com/hsivonen/encoding_rs) - -``` -encoding_rs is copyright Mozilla Foundation. - -Licensed under the Apache License, Version 2.0 - or the MIT -license , -at your option. All files in the project carrying such -notice may not be copied, modified, or distributed except -according to those terms. - -This crate includes data derived from the data files supplied -with the WHATWG Encoding Standard, which, when incorporated into -source code, are licensed under the BSD 3-Clause License -. - -Test code within encoding_rs is dedicated to the Public Domain when so -designated (see the individual files for PD/CC0-dedicated sections). - ``` ------------- ## (MIT OR Apache-2.0) AND Unicode-3.0 License: unicode-ident diff --git a/megazords/ios-rust/focus/Cargo.toml b/megazords/ios-rust/focus/Cargo.toml index 8fc3ce3cbc..2fe34bce1f 100644 --- a/megazords/ios-rust/focus/Cargo.toml +++ b/megazords/ios-rust/focus/Cargo.toml @@ -12,7 +12,6 @@ crate-type = ["staticlib"] 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" } remote_settings = { path = "../../../components/remote_settings" } diff --git a/megazords/ios-rust/focus/DEPENDENCIES.md b/megazords/ios-rust/focus/DEPENDENCIES.md index 880a267de0..bd68c2865d 100644 --- a/megazords/ios-rust/focus/DEPENDENCIES.md +++ b/megazords/ios-rust/focus/DEPENDENCIES.md @@ -40,7 +40,6 @@ the details of which are reproduced below. * [Zlib License: foldhash](#zlib-license-foldhash) * [Unicode-3.0 License: icu_collections, icu_locale, icu_locale_core, icu_locale_data, icu_normalizer, icu_normalizer_data, icu_properties, icu_properties_data, icu_provider, icu_segmenter, icu_segmenter_data, litemap, potential_utf, tinystr, writeable, yoke, yoke-derive, zerofrom, zerofrom-derive, zerotrie, zerovec, zerovec-derive](#unicode-30-license-icu_collections-icu_locale-icu_locale_core-icu_locale_data-icu_normalizer-icu_normalizer_data-icu_properties-icu_properties_data-icu_provider-icu_segmenter-icu_segmenter_data-litemap-potential_utf-tinystr-writeable-yoke-yoke-derive-zerofrom-zerofrom-derive-zerotrie-zerovec-zerovec-derive) * [Optional Notice: SQLite](#optional-notice-sqlite) -* [(Apache-2.0 OR MIT) AND BSD-3-Clause License: encoding_rs](#(apache-20-or-mit)-and-bsd-3-clause-license-encoding_rs) * [(MIT OR Apache-2.0) AND Unicode-3.0 License: unicode-ident](#(mit-or-apache-20)-and-unicode-30-license-unicode-ident) ------------- ## Mozilla Public License 2.0 @@ -444,7 +443,6 @@ The following text applies to code linked from these dependencies: [askama_parser](https://github.com/askama-rs/askama), [async-trait](https://github.com/dtolnay/async-trait), [autocfg](https://github.com/cuviper/autocfg), -[base64](https://github.com/marshallpierce/rust-base64), [basic-toml](https://github.com/dtolnay/basic-toml), [bhttp](https://github.com/martinthomson/ohttp), [bitflags](https://github.com/bitflags/bitflags), @@ -476,7 +474,6 @@ The following text applies to code linked from these dependencies: [fs-err](https://github.com/andrewhickman/fs-err), [futures-channel](https://github.com/rust-lang/futures-rs), [futures-core](https://github.com/rust-lang/futures-rs), -[futures-io](https://github.com/rust-lang/futures-rs), [futures-sink](https://github.com/rust-lang/futures-rs), [futures-task](https://github.com/rust-lang/futures-rs), [futures-util](https://github.com/rust-lang/futures-rs), @@ -496,16 +493,15 @@ The following text applies to code linked from these dependencies: [idna_adapter](https://github.com/hsivonen/idna_adapter), [indexmap](https://github.com/indexmap-rs/indexmap), [io-lifetimes](https://github.com/sunfishcode/io-lifetimes), -[ipnet](https://github.com/krisprice/ipnet), [itertools](https://github.com/rust-itertools/itertools), [itoa](https://github.com/dtolnay/itoa), [lalrpop-util](https://github.com/lalrpop/lalrpop), [lazy_static](https://github.com/rust-lang-nursery/lazy-static.rs), [libc](https://github.com/rust-lang/libc), [libm](https://github.com/rust-lang/libm), +[linux-raw-sys](https://github.com/sunfishcode/linux-raw-sys), [lock_api](https://github.com/Amanieu/parking_lot), [log](https://github.com/rust-lang/log), -[mime](https://github.com/hyperium/mime), [minimal-lexical](https://github.com/Alexhuszagh/minimal-lexical), [native-tls](https://github.com/sfackler/rust-native-tls), [num-traits](https://github.com/rust-num/num-traits), @@ -527,7 +523,6 @@ The following text applies to code linked from these dependencies: [regex-automata](https://github.com/rust-lang/regex/tree/master/regex-automata), [regex-syntax](https://github.com/rust-lang/regex/tree/master/regex-syntax), [regex](https://github.com/rust-lang/regex), -[reqwest](https://github.com/seanmonstar/reqwest), [rkv](https://github.com/mozilla/rkv), [rustc-hash](https://github.com/rust-lang/rustc-hash), [rustix](https://github.com/bytecodealliance/rustix), @@ -541,7 +536,6 @@ The following text applies to code linked from these dependencies: [serde_derive](https://github.com/serde-rs/serde), [serde_json](https://github.com/serde-rs/json), [serde_spanned](https://github.com/toml-rs/toml), -[serde_urlencoded](https://github.com/nox/serde_urlencoded), [sha2](https://github.com/RustCrypto/hashes), [shlex](https://github.com/comex/rust-shlex), [siphasher](https://github.com/jedisct1/rust-siphash), @@ -1830,32 +1824,6 @@ The following text applies to code linked from these dependencies: ``` This software makes use of the 'SQLite' database engine, and we are very grateful to D. Richard Hipp and team for producing it. -``` -------------- -## (Apache-2.0 OR MIT) AND BSD-3-Clause License: encoding_rs - -The following text applies to code linked from these dependencies: -[encoding_rs](https://github.com/hsivonen/encoding_rs) - -``` -encoding_rs is copyright Mozilla Foundation. - -Licensed under the Apache License, Version 2.0 - or the MIT -license , -at your option. All files in the project carrying such -notice may not be copied, modified, or distributed except -according to those terms. - -This crate includes data derived from the data files supplied -with the WHATWG Encoding Standard, which, when incorporated into -source code, are licensed under the BSD 3-Clause License -. - -Test code within encoding_rs is dedicated to the Public Domain when so -designated (see the individual files for PD/CC0-dedicated sections). - ``` ------------- ## (MIT OR Apache-2.0) AND Unicode-3.0 License: unicode-ident diff --git a/megazords/ios-rust/focus/src/lib.rs b/megazords/ios-rust/focus/src/lib.rs index 7b66a0361c..432c74189e 100644 --- a/megazords/ios-rust/focus/src/lib.rs +++ b/megazords/ios-rust/focus/src/lib.rs @@ -11,4 +11,3 @@ pub use nimbus; pub use remote_settings; pub use rust_log_forwarder; pub use viaduct; -pub use viaduct_reqwest; diff --git a/megazords/ios-rust/src/lib.rs b/megazords/ios-rust/src/lib.rs index 051f6f8cf3..0580781e78 100644 --- a/megazords/ios-rust/src/lib.rs +++ b/megazords/ios-rust/src/lib.rs @@ -29,4 +29,3 @@ pub use tabs; pub use tracing_support; pub use viaduct; pub use viaduct_hyper; -pub use viaduct_reqwest;