keket_http/
lib.rs

1use keket::{
2    database::path::AssetPath,
3    fetch::{AssetBytesAreReadyToProcess, AssetFetch},
4    third_party::anput::bundle::DynamicBundle,
5};
6use reqwest::Url;
7use std::error::Error;
8
9pub mod third_party {
10    pub use reqwest;
11}
12
13/// A marker component indicating that an asset was loaded from an HTTP request.
14/// It does not contain asset data but is used to mark assets fetched from an HTTP URL.
15pub struct AssetFromHttp;
16
17/// `HttpAssetFetch` is a struct that enables fetching assets from an HTTP endpoint.
18/// The root URL represents the base URL to join with paths to form full asset URLs.
19pub struct HttpAssetFetch {
20    root: Url,
21}
22
23impl HttpAssetFetch {
24    #[allow(rustdoc::bare_urls)]
25    /// Creates a new `HttpAssetFetch` with a provided root URL.
26    ///
27    /// # Arguments
28    /// - `root`: A string representing the root URL for the HTTP request (e.g., "https://example.com").
29    ///
30    /// # Returns
31    /// - `Ok(HttpAssetFetch)`: If the root URL is valid and successfully parsed.
32    /// - `Err(Box<dyn Error>)`: If the URL is invalid or any error occurs while parsing.
33    pub fn new(root: &str) -> Result<Self, Box<dyn Error>> {
34        Ok(Self {
35            root: root.parse()?,
36        })
37    }
38}
39
40impl AssetFetch for HttpAssetFetch {
41    fn load_bytes(&self, path: AssetPath) -> Result<DynamicBundle, Box<dyn Error>> {
42        let url = self.root.join(path.path()).map_err(|error| {
43            format!(
44                "Failed to join root URL: `{}` with path: `{}`. Error: {}",
45                self.root,
46                path.path_with_meta(),
47                error
48            )
49        })?;
50        let mut response = reqwest::blocking::get(url.clone())
51            .map_err(|error| format!("Failed to get HTTP content from: `{url}`. Error: {error}"))?;
52        let mut bytes = vec![];
53        response.copy_to(&mut bytes).map_err(|error| {
54            format!("Failed to read bytes response from: `{url}`. Error: {error}")
55        })?;
56        let mut bundle = DynamicBundle::default();
57        let _ = bundle.add_component(AssetBytesAreReadyToProcess(bytes));
58        let _ = bundle.add_component(AssetFromHttp);
59        let _ = bundle.add_component(url);
60        Ok(bundle)
61    }
62}