Skip to content

Commit 0981e2d

Browse files
authored
Adding OHTTP to viaduct (#6935)
* New viaduct backend Added a new viaduct backend trait. The new backend is UniFFI and async-based and handles settings slightly differently. See the `new_backend` module for the transition plan. Added the `hyper` backend to `viaduct` directly. I don't think we really need to have different crates for each backend, we can use feature flags instead. This replaces `viaduct-dev` which I did that for all the CLI crates and the plan is to move iOS from `viaduct-reqwest` to the hyper backend. Made some tweaks to `Error` so that it's UniFFI compatible. Also, renamed it to `ViaductError` to avoid name conflicts on Swift. * Bug 1987449: Adding OHTTP to viaduct * Bug 1987449: Adding OHTTP to viaduct - Additional, adding libclang-dev to Dockerfile for ohttp crate to be built
1 parent 2042b47 commit 0981e2d

File tree

20 files changed

+1340
-82
lines changed

20 files changed

+1340
-82
lines changed

Cargo.lock

Lines changed: 176 additions & 50 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

DEPENDENCIES.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ The following text applies to code linked from these dependencies:
459459
[askama](https://github.com/askama-rs/askama),
460460
[askama_derive](https://github.com/askama-rs/askama),
461461
[askama_parser](https://github.com/askama-rs/askama),
462+
[async-lock](https://github.com/smol-rs/async-lock),
462463
[async-trait](https://github.com/dtolnay/async-trait),
463464
[autocfg](https://github.com/cuviper/autocfg),
464465
[base64](https://github.com/marshallpierce/rust-base64),
@@ -473,9 +474,11 @@ The following text applies to code linked from these dependencies:
473474
[cfg-if](https://github.com/alexcrichton/cfg-if),
474475
[chrono](https://github.com/chronotope/chrono),
475476
[clang-sys](https://github.com/KyleMayes/clang-sys),
477+
[concurrent-queue](https://github.com/smol-rs/concurrent-queue),
476478
[core-foundation-sys](https://github.com/servo/core-foundation-rs),
477479
[core-foundation](https://github.com/servo/core-foundation-rs),
478480
[cpufeatures](https://github.com/RustCrypto/utils),
481+
[crossbeam-utils](https://github.com/crossbeam-rs/crossbeam),
479482
[crypto-common](https://github.com/RustCrypto/traits),
480483
[digest](https://github.com/RustCrypto/traits),
481484
[displaydoc](https://github.com/yaahc/displaydoc),
@@ -484,6 +487,8 @@ The following text applies to code linked from these dependencies:
484487
[env_logger](https://github.com/rust-cli/env_logger),
485488
[equivalent](https://github.com/cuviper/equivalent),
486489
[errno](https://github.com/lambda-fairy/rust-errno),
490+
[event-listener-strategy](https://github.com/smol-rs/event-listener-strategy),
491+
[event-listener](https://github.com/smol-rs/event-listener),
487492
[fallible-iterator](https://github.com/sfackler/rust-fallible-iterator),
488493
[fallible-streaming-iterator](https://github.com/sfackler/fallible-streaming-iterator),
489494
[fastrand](https://github.com/smol-rs/fastrand),
@@ -537,6 +542,7 @@ The following text applies to code linked from these dependencies:
537542
[openssl-probe](https://github.com/alexcrichton/openssl-probe),
538543
[openssl-src](https://github.com/alexcrichton/openssl-src-rs),
539544
[openssl](https://github.com/sfackler/rust-openssl),
545+
[parking](https://github.com/smol-rs/parking),
540546
[parking_lot](https://github.com/Amanieu/parking_lot),
541547
[parking_lot_core](https://github.com/Amanieu/parking_lot),
542548
[paste](https://github.com/dtolnay/paste),
@@ -570,6 +576,7 @@ The following text applies to code linked from these dependencies:
570576
[serde_derive](https://github.com/serde-rs/serde),
571577
[serde_json](https://github.com/serde-rs/json),
572578
[serde_path_to_error](https://github.com/dtolnay/path-to-error),
579+
[serde_spanned](https://github.com/toml-rs/toml),
573580
[serde_urlencoded](https://github.com/nox/serde_urlencoded),
574581
[sha2](https://github.com/RustCrypto/hashes),
575582
[shlex](https://github.com/comex/rust-shlex),
@@ -587,6 +594,10 @@ The following text applies to code linked from these dependencies:
587594
[tinyvec](https://github.com/Lokathor/tinyvec),
588595
[tinyvec_macros](https://github.com/Soveu/tinyvec_macros),
589596
[toml](https://github.com/alexcrichton/toml-rs),
597+
[toml](https://github.com/toml-rs/toml),
598+
[toml_datetime](https://github.com/toml-rs/toml),
599+
[toml_parser](https://github.com/toml-rs/toml),
600+
[toml_writer](https://github.com/toml-rs/toml),
590601
[typenum](https://github.com/paholg/typenum),
591602
[unicase](https://github.com/seanmonstar/unicase),
592603
[unicode-normalization](https://github.com/unicode-rs/unicode-normalization),

components/init_rust_components/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ license = "MPL-2.0"
77
exclude = ["/android"]
88

99
[features]
10+
default = []
1011
keydb = ["nss/keydb"]
12+
ohttp = ["viaduct/ohttp"]
1113

1214
[dependencies]
1315
uniffi = { version = "0.29.0" }
1416
nss = { path = "../support/rc_crypto/nss" }
17+
viaduct = { path = "../viaduct", optional = true }

components/init_rust_components/src/lib.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
use nss::ensure_initialized as ensure_nss_initialized;
88
#[cfg(feature = "keydb")]
99
use nss::ensure_initialized_with_profile_dir as ensure_nss_initialized_with_profile_dir;
10-
10+
#[cfg(feature = "ohttp")]
11+
use viaduct::ohttp::configure_default_ohttp_channels;
1112
uniffi::setup_scaffolding!();
1213

1314
/// Global initialization routines for Rust components. Must be called before any other calls to
@@ -20,6 +21,12 @@ uniffi::setup_scaffolding!();
2021
#[uniffi::export]
2122
pub fn initialize() {
2223
ensure_nss_initialized();
24+
25+
#[cfg(feature = "ohttp")]
26+
{
27+
configure_default_ohttp_channels()
28+
.expect("We pass down hard coded Strings for the relays, if this fails, we have a typo in the config we pass down.");
29+
}
2330
}
2431

2532
/// Global initialization routines for Rust components, when `logins/keydb` feature is activated. Must be
@@ -34,4 +41,10 @@ pub fn initialize() {
3441
#[uniffi::export]
3542
pub fn initialize(profile_path: String) {
3643
ensure_nss_initialized_with_profile_dir(profile_path);
44+
45+
#[cfg(feature = "ohttp")]
46+
{
47+
configure_default_ohttp_channels()
48+
.expect("We pass down hard coded Strings for the relays, if this fails, we have a typo in the config we pass down.");
49+
}
3750
}

components/support/viaduct-dev/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ pub fn init_backend_dev() {
4949

5050
#[async_trait::async_trait]
5151
impl Backend for HyperBackend {
52-
async fn send_request(&self, request: Request, settings: ClientSettings) -> Result<Response> {
52+
async fn send_request(
53+
&self,
54+
request: Request,
55+
settings: ClientSettings,
56+
) -> Result<Response, ViaductError> {
5357
let handle = self.runtime.handle().clone();
5458
let client = self.client.clone();
5559
match handle

components/viaduct/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ crate-type = ["lib"]
1111

1212
[dependencies]
1313
async-trait = "0.1"
14+
async-lock = "3.3"
1415
error-support = { path = "../support/error" }
1516
url = "2"
1617
serde = "1"
@@ -22,3 +23,12 @@ prost = "0.12"
2223
ffi-support = "0.4"
2324
thiserror = "2"
2425
uniffi = { version = "0.29.0" }
26+
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
27+
hyper = { version = "0.14", features = ["client", "http1", "http2", "tcp"], optional = true }
28+
bhttp = { git = "https://github.com/martinthomson/ohttp.git", rev = "c6131ace4e4e82a4269afac3cb0524541d2cd315", optional = true }
29+
ohttp = { git = "https://github.com/martinthomson/ohttp.git", rev = "c6131ace4e4e82a4269afac3cb0524541d2cd315", features = ["client", "server", "app-svc", "external-sqlite"], default-features = false, optional = true }
30+
31+
[features]
32+
default = ["ohttp"]
33+
backend-dev = ["dep:tokio", "dep:hyper"]
34+
ohttp = ["dep:bhttp", "dep:ohttp"]

components/viaduct/src/client.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,40 @@ impl Client {
1818
Self { settings }
1919
}
2020

21+
/// Create a client that uses OHTTP with the specified channel for all requests
22+
#[cfg(feature = "ohttp")]
23+
pub fn with_ohttp_channel(
24+
channel: &str,
25+
settings: ClientSettings,
26+
) -> Result<Self, crate::ViaductError> {
27+
if !crate::ohttp::is_ohttp_channel_configured(channel) {
28+
return Err(crate::ViaductError::OhttpChannelNotConfigured(
29+
channel.to_string(),
30+
));
31+
}
32+
let mut client_settings = settings;
33+
client_settings.ohttp_channel = Some(channel.to_string());
34+
Ok(Self {
35+
settings: client_settings,
36+
})
37+
}
38+
2139
pub async fn send(&self, request: Request) -> Result<Response> {
2240
validate_request(&request)?;
41+
42+
// Check if this client should use OHTTP for all requests
43+
#[cfg(feature = "ohttp")]
44+
if let Some(channel) = &self.settings.ohttp_channel {
45+
crate::debug!(
46+
"Client configured for OHTTP channel '{}', processing request via OHTTP",
47+
channel
48+
);
49+
return crate::ohttp::process_ohttp_request(request, channel, self.settings.clone())
50+
.await;
51+
}
52+
53+
// For non-OHTTP requests, use the normal backend
54+
crate::debug!("Processing request via standard backend");
2355
get_backend()?
2456
.send_request(request, self.settings.clone())
2557
.await
@@ -39,6 +71,9 @@ pub struct ClientSettings {
3971
// Maximum amount of redirects to follow (0 means redirects are not allowed)
4072
#[uniffi(default = 10)]
4173
pub redirect_limit: u32,
74+
// OHTTP channel to use for all requests (if any)
75+
#[cfg(feature = "ohttp")]
76+
pub ohttp_channel: Option<String>,
4277
}
4378

4479
impl Default for ClientSettings {
@@ -49,6 +84,8 @@ impl Default for ClientSettings {
4984
#[cfg(not(target_os = "ios"))]
5085
timeout: 10000,
5186
redirect_limit: 10,
87+
#[cfg(feature = "ohttp")]
88+
ohttp_channel: None,
5289
}
5390
}
5491
}

components/viaduct/src/error.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@ pub enum ViaductError {
3131

3232
#[error("[no-sentry] Validation error: URL does not use TLS protocol.")]
3333
NonTlsUrl,
34+
35+
#[error("OHTTP channel '{0}' is not configured")]
36+
OhttpChannelNotConfigured(String),
37+
38+
#[error("Failed to fetch OHTTP config: {0}")]
39+
OhttpConfigFetchFailed(String),
40+
41+
#[error("OHTTP request error: {0}")]
42+
OhttpRequestError(String),
43+
44+
#[error("OHTTP response error: {0}")]
45+
OhttpResponseError(String),
46+
47+
#[error("OHTTP support is not enabled in this build")]
48+
OhttpNotSupported,
3449
}
3550

3651
impl ViaductError {

components/viaduct/src/headers.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,18 @@ impl Headers {
115115
Default::default()
116116
}
117117

118+
/// Create headers from a HashMap of name-value pairs
119+
///
120+
/// # Errors
121+
/// Returns an error if any header name or value is invalid
122+
pub fn try_from_hashmap(map: HashMap<String, String>) -> Result<Self, crate::ViaductError> {
123+
let mut headers = Headers::new();
124+
for (name, value) in map {
125+
headers.insert(name, value)?;
126+
}
127+
Ok(headers)
128+
}
129+
118130
/// Initialize an empty list of headers backed by a vector with the provided
119131
/// capacity.
120132
pub fn with_capacity(c: usize) -> Self {

components/viaduct/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ mod backend;
1313
mod client;
1414
pub mod error;
1515
mod new_backend;
16+
#[cfg(feature = "ohttp")]
17+
pub mod ohttp;
18+
#[cfg(feature = "ohttp")]
19+
mod ohttp_client;
1620
pub mod settings;
1721
pub use error::*;
1822
// reexport logging helpers.
@@ -22,6 +26,8 @@ pub use backend::{note_backend, set_backend, Backend as OldBackend};
2226
pub use client::{Client, ClientSettings};
2327
pub use headers::{consts as header_names, Header, HeaderName, Headers, InvalidHeaderName};
2428
pub use new_backend::{init_backend, Backend};
29+
#[cfg(feature = "ohttp")]
30+
pub use ohttp::{clear_ohttp_channels, configure_ohttp_channel, list_ohttp_channels, OhttpConfig};
2531
pub use settings::{allow_android_emulator_loopback, GLOBAL_SETTINGS};
2632

2733
#[allow(clippy::derive_partial_eq_without_eq)]

0 commit comments

Comments
 (0)