Skip to main content

xsd_parser/pipeline/parser/resolver/
web_resolver.rs

1use std::io::BufReader;
2
3use reqwest::{
4    blocking::{Client, Response},
5    Error,
6};
7use url::Url;
8
9use super::{strip_name_ext, ResolveRequest, ResolveResult, Resolver};
10
11/// Implements a [`Resolver`] that resolves `http` and `https` resources.
12#[must_use]
13#[derive(Default, Debug)]
14pub struct WebResolver {
15    client: Option<Client>,
16}
17
18impl WebResolver {
19    /// Create a new [`WebResolver`] instance.
20    pub fn new() -> Self {
21        Self::default()
22    }
23}
24
25impl Resolver for WebResolver {
26    type Buffer = BufReader<Response>;
27    type Error = Error;
28
29    fn resolve(&mut self, req: &ResolveRequest) -> ResolveResult<Self> {
30        let url = if let Some(current) = &req.current_location {
31            current.join(&req.requested_location)
32        } else {
33            Url::parse(&req.requested_location)
34        };
35
36        let Ok(url) = url else {
37            return Ok(None);
38        };
39
40        if !matches!(url.scheme(), "http" | "https") {
41            return Ok(None);
42        }
43
44        let client = self.client.get_or_insert_with(Client::new);
45
46        let res = client.get(url.clone()).send()?;
47        let buffer = BufReader::new(res);
48
49        let name = url
50            .as_str()
51            .split(['\\', '/'])
52            .next_back()
53            .map(strip_name_ext)
54            .map(ToOwned::to_owned);
55
56        Ok(Some((name, url, buffer)))
57    }
58}