ralph-workflow 0.7.18

PROMPT-driven multi-agent orchestrator for git repos
Documentation
use std::time::Duration;

fn build_agent() -> ureq::Agent {
    ureq::Agent::new_with_config(
        ureq::config::Config::builder()
            .timeout_global(Some(Duration::from_secs(10)))
            .http_status_as_error(false)
            .build(),
    )
}

fn check_http_status(status: ureq::http::StatusCode, body: &str) -> Result<(), String> {
    if status.is_client_error() || status.is_server_error() {
        if body.is_empty() {
            return Err(format!("status {}", status.as_u16()));
        }
        return Err(format!("status {}: {}", status.as_u16(), body));
    }
    Ok(())
}

pub fn fetch_url(url: &str) -> Result<String, String> {
    let agent = build_agent();
    let mut response = agent
        .get(url)
        .call()
        .map_err(|e: ureq::Error| e.to_string())?;

    let status = response.status();
    let body = response
        .body_mut()
        .read_to_string()
        .map_err(|e| e.to_string())?;

    check_http_status(status, &body)?;
    Ok(body)
}

pub trait HttpFetcher: Send + Sync {
    fn fetch(&self, url: &str) -> Result<String, String>;
}

#[derive(Debug, Clone, Default)]
pub struct RealHttpFetcher;

impl HttpFetcher for RealHttpFetcher {
    fn fetch(&self, url: &str) -> Result<String, String> {
        fetch_url(url)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use mockito::Server;

    #[test]
    fn fetch_url_returns_mocked_body() {
        let mut server = Server::new();
        let _mock = server
            .mock("GET", "/test")
            .with_status(200)
            .with_body("test content")
            .create();

        let url = format!("{}/test", server.url());
        let result = fetch_url(&url).unwrap();

        assert_eq!(result, "test content");
    }

    #[test]
    fn fetch_url_propagates_error_status() {
        let mut server = Server::new();
        let _mock = server
            .mock("GET", "/error")
            .with_status(500)
            .with_body("server error")
            .create();

        let url = format!("{}/error", server.url());
        let error = fetch_url(&url).unwrap_err();

        assert!(error.contains("500"));
        assert!(error.contains("server error"));
    }
}