viaduct/
client.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 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use crate::{new_backend::get_backend, settings::validate_request, Request, Response, Result};
6
7/// HTTP Client
8///
9/// This represents the "new" API.
10/// See `README.md` for details about the transition from the old to new API.
11#[derive(Default)]
12pub struct Client {
13    settings: ClientSettings,
14}
15
16impl Client {
17    pub fn new(settings: ClientSettings) -> Self {
18        Self { settings }
19    }
20
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
39    pub async fn send(&self, request: Request) -> Result<Response> {
40        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");
55        get_backend()?
56            .send_request(request, self.settings.clone())
57            .await
58    }
59
60    pub fn send_sync(&self, request: Request) -> Result<Response> {
61        pollster::block_on(self.send(request))
62    }
63}
64
65#[derive(Debug, uniffi::Record, Clone)]
66#[repr(C)]
67pub struct ClientSettings {
68    // Timeout for the entire request in ms (0 indicates no timeout).
69    #[uniffi(default = 0)]
70    pub timeout: u32,
71    // Maximum amount of redirects to follow (0 means redirects are not allowed)
72    #[uniffi(default = 10)]
73    pub redirect_limit: u32,
74    // OHTTP channel to use for all requests (if any)
75    #[cfg(feature = "ohttp")]
76    pub ohttp_channel: Option<String>,
77}
78
79impl Default for ClientSettings {
80    fn default() -> Self {
81        Self {
82            #[cfg(target_os = "ios")]
83            timeout: 7000,
84            #[cfg(not(target_os = "ios"))]
85            timeout: 10000,
86            redirect_limit: 10,
87            #[cfg(feature = "ohttp")]
88            ohttp_channel: None,
89        }
90    }
91}