maplibre/platform/noweb/
http_client.rs1use 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 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}