lychee_lib/types/
resolver.rs1use super::{FileType, InputContent, ResolvedInputSource};
2use crate::utils::request;
3use crate::{BasicAuthExtractor, ErrorKind, Result, Uri};
4use http::HeaderMap;
5use reqwest::{Client, Request, Url};
6
7#[derive(Debug, Default, Clone)]
9pub struct UrlContentResolver {
10 pub basic_auth_extractor: Option<BasicAuthExtractor>,
11 pub headers: HeaderMap,
12 pub client: reqwest::Client,
13}
14
15impl UrlContentResolver {
16 pub async fn url_contents(&self, url: Url) -> Result<InputContent> {
21 let file_type = match url.path() {
23 path if path.is_empty() || path == "/" => FileType::Html,
24 _ => FileType::from(url.as_str()),
25 };
26
27 let credentials = request::extract_credentials(
28 self.basic_auth_extractor.as_ref(),
29 &Uri { url: url.clone() },
30 );
31
32 let request = self.build_request(&url, credentials)?;
33 let content = get_request_body_text(&self.client, request).await?;
34
35 let input_content = InputContent {
36 source: ResolvedInputSource::RemoteUrl(Box::new(url.clone())),
37 file_type,
38 content,
39 };
40
41 Ok(input_content)
42 }
43
44 fn build_request(
45 &self,
46 url: &Url,
47 credentials: Option<super::BasicAuthCredentials>,
48 ) -> Result<Request> {
49 let mut request = self
50 .client
51 .request(reqwest::Method::GET, url.clone())
52 .build()
53 .map_err(ErrorKind::BuildRequestClient)?;
54
55 request.headers_mut().extend(self.headers.clone());
56 if let Some(credentials) = credentials {
57 credentials.append_to_request(&mut request);
58 }
59
60 Ok(request)
61 }
62}
63
64async fn get_request_body_text(client: &Client, request: Request) -> Result<String> {
65 client
66 .execute(request)
67 .await
68 .map_err(ErrorKind::NetworkRequest)?
69 .text()
70 .await
71 .map_err(ErrorKind::ReadResponseBody)
72}