viaduct/
new_backend.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3*
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6// Right now we're in a transition period where we have 2 backend traits.  The old `Backend`
7// trait is defined in `backend.rs` and the new `Backend` trait is bdefined here
8//
9// The new backend trait has a few of improvements to the old backend trait:
10//   - UniFFI-compatible
11//   - async-based
12//   - Inputs per-request settings for things like timeouts, rather than using global values
13//
14// See `README.md` for details about the transition from the old to new API.
15
16use std::sync::{Arc, OnceLock};
17
18use crate::{
19    backend as old_backend, settings::GLOBAL_SETTINGS, ClientSettings, Request, Response, Result,
20    ViaductError,
21};
22
23#[uniffi::export(with_foreign)]
24#[async_trait::async_trait]
25pub trait Backend: Send + Sync + 'static {
26    async fn send_request(&self, request: Request, settings: ClientSettings) -> Result<Response>;
27}
28
29static REGISTERED_BACKEND: OnceLock<Arc<dyn Backend>> = OnceLock::new();
30
31#[uniffi::export]
32pub fn init_backend(backend: Arc<dyn Backend>) -> Result<()> {
33    old_backend::set_backend(Box::leak(Box::new(backend.clone())))?;
34    REGISTERED_BACKEND
35        .set(backend)
36        .map_err(|_| ViaductError::BackendAlreadyInitialized)
37}
38
39pub fn get_backend() -> Result<&'static Arc<dyn Backend>> {
40    REGISTERED_BACKEND
41        .get()
42        .ok_or(ViaductError::BackendNotInitialized)
43}
44
45impl old_backend::Backend for Arc<dyn Backend> {
46    fn send(&self, request: crate::Request) -> Result<crate::Response, crate::ViaductError> {
47        let settings = GLOBAL_SETTINGS.read();
48        let client_settings = ClientSettings {
49            timeout: match settings.read_timeout {
50                Some(d) => d.as_millis() as u32,
51                None => 0,
52            },
53            redirect_limit: if settings.follow_redirects { 10 } else { 0 },
54            #[cfg(feature = "ohttp")]
55            ohttp_channel: None,
56        };
57        pollster::block_on(self.send_request(request, client_settings))
58    }
59}