ralph_workflow/io/
http_fetch.rs1use std::time::Duration;
2
3fn build_agent() -> ureq::Agent {
4 ureq::Agent::new_with_config(
5 ureq::config::Config::builder()
6 .timeout_global(Some(Duration::from_secs(10)))
7 .http_status_as_error(false)
8 .build(),
9 )
10}
11
12fn check_http_status(status: ureq::http::StatusCode, body: &str) -> Result<(), String> {
13 if status.is_client_error() || status.is_server_error() {
14 if body.is_empty() {
15 return Err(format!("status {}", status.as_u16()));
16 }
17 return Err(format!("status {}: {}", status.as_u16(), body));
18 }
19 Ok(())
20}
21
22pub fn fetch_url(url: &str) -> Result<String, String> {
23 let agent = build_agent();
24 let mut response = agent
25 .get(url)
26 .call()
27 .map_err(|e: ureq::Error| e.to_string())?;
28
29 let status = response.status();
30 let body = response
31 .body_mut()
32 .read_to_string()
33 .map_err(|e| e.to_string())?;
34
35 check_http_status(status, &body)?;
36 Ok(body)
37}
38
39pub trait HttpFetcher: Send + Sync {
40 fn fetch(&self, url: &str) -> Result<String, String>;
41}
42
43#[derive(Debug, Clone, Default)]
44pub struct RealHttpFetcher;
45
46impl HttpFetcher for RealHttpFetcher {
47 fn fetch(&self, url: &str) -> Result<String, String> {
48 fetch_url(url)
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55 use mockito::Server;
56
57 #[test]
58 fn fetch_url_returns_mocked_body() {
59 let mut server = Server::new();
60 let _mock = server
61 .mock("GET", "/test")
62 .with_status(200)
63 .with_body("test content")
64 .create();
65
66 let url = format!("{}/test", server.url());
67 let result = fetch_url(&url).unwrap();
68
69 assert_eq!(result, "test content");
70 }
71
72 #[test]
73 fn fetch_url_propagates_error_status() {
74 let mut server = Server::new();
75 let _mock = server
76 .mock("GET", "/error")
77 .with_status(500)
78 .with_body("server error")
79 .create();
80
81 let url = format!("{}/error", server.url());
82 let error = fetch_url(&url).unwrap_err();
83
84 assert!(error.contains("500"));
85 assert!(error.contains("server error"));
86 }
87}