maplibre/platform/noweb/
http_client.rs

1use std::path::PathBuf;
2
3use async_trait::async_trait;
4use http_cache_reqwest::{CACacheManager, Cache, CacheMode, HttpCache, HttpCacheOptions};
5use reqwest::{Client, StatusCode};
6use reqwest_middleware::ClientWithMiddleware;
7
8use crate::io::source_client::{HttpClient, SourceFetchError};
9
10#[derive(Clone)]
11pub struct ReqwestHttpClient {
12    client: ClientWithMiddleware,
13}
14
15impl From<reqwest::Error> for SourceFetchError {
16    fn from(err: reqwest::Error) -> Self {
17        SourceFetchError(Box::new(err))
18    }
19}
20
21impl From<reqwest_middleware::Error> for SourceFetchError {
22    fn from(err: reqwest_middleware::Error) -> Self {
23        SourceFetchError(Box::new(err))
24    }
25}
26
27impl ReqwestHttpClient {
28    /// cache_path: Under which path should we cache requests.
29    pub fn new<P>(cache_path: Option<P>) -> Self
30    where
31        P: Into<PathBuf>,
32    {
33        let mut builder = reqwest_middleware::ClientBuilder::new(Client::new());
34
35        if let Some(cache_path) = cache_path {
36            builder = builder.with(Cache(HttpCache {
37                mode: CacheMode::Default,
38                manager: CACacheManager {
39                    path: cache_path.into(),
40                },
41                options: HttpCacheOptions::default(),
42            }))
43        }
44        let client = builder.build();
45
46        Self { client }
47    }
48}
49
50#[cfg_attr(not(feature = "thread-safe-futures"), async_trait(?Send))]
51#[cfg_attr(feature = "thread-safe-futures", async_trait)]
52impl HttpClient for ReqwestHttpClient {
53    async fn fetch(&self, url: &str) -> Result<Vec<u8>, SourceFetchError> {
54        let response = self.client.get(url).send().await?;
55        match response.error_for_status() {
56            Ok(response) => {
57                if response.status() == StatusCode::NOT_MODIFIED {
58                    log::info!("Using data from cache");
59                }
60
61                let body = response.bytes().await?;
62
63                Ok(Vec::from(body.as_ref()))
64            }
65            Err(e) => Err(SourceFetchError(Box::new(e))),
66        }
67    }
68}