use async_trait::async_trait; use domain::{FetchError, TabFetcherPort, TabSource}; pub struct UgTabFetcher { client: reqwest::Client, } impl UgTabFetcher { pub fn new() -> Self { Self { client: reqwest::Client::new(), } } } impl Default for UgTabFetcher { fn default() -> Self { Self::new() } } #[async_trait] impl TabFetcherPort for UgTabFetcher { async fn fetch(&self, source: TabSource) -> Result { match source { TabSource::File(path) => Ok(tokio::fs::read_to_string(&path).await?), TabSource::Url(url) => { let resp = self .client .get(&url) .send() .await .map_err(|e| FetchError::Network(e.to_string()))?; let content_type = resp .headers() .get(reqwest::header::CONTENT_TYPE) .and_then(|v| v.to_str().ok()) .unwrap_or(""); if !content_type.contains("text/html") { return Err(FetchError::InvalidContentType); } resp.text() .await .map_err(|e| FetchError::Network(e.to_string())) } } } } #[cfg(test)] #[path = "tests/fetcher.rs"] mod tests;