Skip to main content

blitz_net/
provider_api.rs

1//! Stable 0.6 API over the policy-aware implementation.
2
3use blitz_traits::net::{Bytes, NetHandler, NetProvider, NetWaker, Request};
4use blitz_traits::platform::{
5    FetchError, FetchHandler, FetchProvider, FetchRequest, FetchResponse, StatusCode,
6};
7use std::sync::Arc;
8
9/// The browser's document and script network provider.
10pub struct Provider(crate::core::Provider);
11
12impl Provider {
13    /// Bind a browser-issued principal before handing networking to a document.
14    pub fn for_scope(
15        self: &Arc<Self>,
16        initiator: blitz_traits::net::Initiator,
17    ) -> Arc<crate::ScopedProvider> {
18        Arc::new(crate::ScopedProvider::new(Arc::clone(self), initiator))
19    }
20
21    pub fn new(waker: Option<Arc<dyn NetWaker>>) -> Self {
22        Self(crate::core::Provider::new(waker))
23    }
24
25    pub fn with_user_agent(waker: Option<Arc<dyn NetWaker>>, user_agent: &str) -> Self {
26        Self(crate::core::Provider::with_user_agent(waker, user_agent))
27    }
28
29    #[cfg(feature = "cookies")]
30    pub fn with_user_agent_and_cookie_provider<C>(
31        waker: Option<Arc<dyn NetWaker>>,
32        user_agent: &str,
33        cookie_provider: Arc<C>,
34    ) -> Self
35    where
36        C: crate::CookieJar,
37    {
38        Self(crate::core::Provider::with_user_agent_and_cookie_provider(
39            waker,
40            user_agent,
41            cookie_provider,
42        ))
43    }
44
45    #[cfg(all(feature = "cache", not(target_arch = "wasm32")))]
46    pub fn with_cache(self, cache: Arc<crate::PrivateCache>) -> Self {
47        Self(self.0.with_cache(cache))
48    }
49
50    #[cfg(all(feature = "cache", not(target_arch = "wasm32")))]
51    pub async fn with_cache_directory(
52        self,
53        directory: impl AsRef<std::path::Path>,
54    ) -> std::io::Result<Self> {
55        self.0.with_cache_directory(directory).await.map(Self)
56    }
57
58    pub fn shared(waker: Option<Arc<dyn NetWaker>>) -> Arc<dyn NetProvider> {
59        crate::core::Provider::shared(waker)
60    }
61
62    pub fn shared_with_user_agent(
63        waker: Option<Arc<dyn NetWaker>>,
64        user_agent: &str,
65    ) -> Arc<dyn NetProvider> {
66        crate::core::Provider::shared_with_user_agent(waker, user_agent)
67    }
68
69    pub fn user_agent(&self) -> &str {
70        self.0.user_agent()
71    }
72    pub fn is_empty(&self) -> bool {
73        self.0.is_empty()
74    }
75    pub fn count(&self) -> usize {
76        self.0.count()
77    }
78
79    #[cfg(all(feature = "cache", not(target_arch = "wasm32")))]
80    pub async fn clear_cache(&self) {
81        self.0.clear_cache().await;
82    }
83
84    #[allow(clippy::type_complexity)]
85    pub fn fetch_with_callback(
86        &self,
87        request: Request,
88        callback: Box<dyn FnOnce(Result<(String, Bytes), ProviderError>) + Send + Sync + 'static>,
89    ) {
90        self.0.fetch_with_callback(
91            request,
92            Box::new(move |result| {
93                callback(result.map_err(ProviderError::from));
94            }),
95        );
96    }
97
98    pub async fn fetch_async(&self, request: Request) -> Result<(String, Bytes), ProviderError> {
99        self.0
100            .fetch_async(request)
101            .await
102            .map_err(ProviderError::from)
103    }
104
105    pub async fn fetch_response_async(
106        &self,
107        request: Request,
108    ) -> Result<FetchResponse, ProviderError> {
109        self.0
110            .fetch_response_async(request)
111            .await
112            .map_err(ProviderError::from)
113    }
114
115    pub async fn fetch_platform_async(
116        &self,
117        request: FetchRequest,
118    ) -> Result<FetchResponse, FetchError> {
119        self.0.fetch_platform_async(request).await
120    }
121}
122
123impl FetchProvider for Provider {
124    fn fetch(&self, request: FetchRequest, handler: Box<dyn FetchHandler>) {
125        FetchProvider::fetch(&self.0, request, handler);
126    }
127}
128
129impl NetProvider for Provider {
130    fn fetch(&self, doc_id: usize, request: Request, handler: Box<dyn NetHandler>) {
131        NetProvider::fetch(&self.0, doc_id, request, handler);
132    }
133}
134
135/// Preserve the exhaustive public 0.6 error vocabulary. Policy diagnostics
136/// appear in Network; the platform API retains its existing typed Blocked.
137#[derive(Debug)]
138pub enum ProviderError {
139    Abort,
140    Io(std::io::Error),
141    DataUrl(data_url::DataUrlError),
142    DataUrlBase64(data_url::forgiving_base64::InvalidBase64),
143    Network(String),
144    TlsPolicy(crate::TlsPolicyError),
145    InvalidRequest(String),
146    UnsupportedScheme(String),
147    HttpStatus { status: StatusCode, url: String },
148}
149
150impl From<crate::core::ProviderError> for ProviderError {
151    fn from(error: crate::core::ProviderError) -> Self {
152        use crate::core::ProviderError as Core;
153        match error {
154            Core::Abort => Self::Abort,
155            Core::Io(error) => Self::Io(error),
156            Core::DataUrl(error) => Self::DataUrl(error),
157            Core::DataUrlBase64(error) => Self::DataUrlBase64(error),
158            Core::Network(error) => Self::Network(error),
159            Core::Blocked(reason) => Self::Network(format!("blocked: {reason}")),
160            Core::TlsPolicy(reason) => Self::TlsPolicy(reason),
161            Core::InvalidRequest(error) => Self::InvalidRequest(error),
162            Core::UnsupportedScheme(scheme) => Self::UnsupportedScheme(scheme),
163            Core::HttpStatus { status, url } => Self::HttpStatus { status, url },
164        }
165    }
166}
167
168impl std::fmt::Display for ProviderError {
169    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170        match self {
171            Self::Abort => write!(formatter, "request aborted"),
172            Self::Io(error) => write!(formatter, "io error: {error}"),
173            Self::DataUrl(error) => write!(formatter, "data url error: {error:?}"),
174            Self::DataUrlBase64(error) => write!(formatter, "data url base64 error: {error:?}"),
175            Self::Network(error) => write!(formatter, "network error: {error}"),
176            Self::TlsPolicy(reason) => write!(formatter, "TLS policy: {reason}"),
177            Self::InvalidRequest(error) => write!(formatter, "invalid request: {error}"),
178            Self::UnsupportedScheme(scheme) => {
179                write!(formatter, "unsupported URL scheme: {scheme}")
180            }
181            Self::HttpStatus { status, url } => write!(formatter, "HTTP {status} for {url}"),
182        }
183    }
184}
185
186impl std::error::Error for ProviderError {}
187
188impl From<std::io::Error> for ProviderError {
189    fn from(error: std::io::Error) -> Self {
190        Self::Io(error)
191    }
192}
193
194impl From<data_url::DataUrlError> for ProviderError {
195    fn from(error: data_url::DataUrlError) -> Self {
196        Self::DataUrl(error)
197    }
198}
199
200impl From<data_url::forgiving_base64::InvalidBase64> for ProviderError {
201    fn from(error: data_url::forgiving_base64::InvalidBase64) -> Self {
202        Self::DataUrlBase64(error)
203    }
204}