perfect-postcode/server-rs/src/routes/travel_time.rs
2026-02-15 22:39:53 +00:00

58 lines
1.5 KiB
Rust

use serde::{Deserialize, Serialize};
use tracing::warn;
#[derive(Serialize)]
struct TravelTimeRequest {
origins: Vec<[f64; 2]>,
destination: [f64; 2],
mode: String,
}
#[derive(Deserialize)]
struct TravelTimeResponse {
travel_times: Vec<Option<f64>>,
}
/// Call the R5 service to compute many-to-one travel times.
///
/// Returns a Vec of travel times in minutes (one per origin), with None for unreachable origins.
pub async fn fetch_travel_times(
client: &reqwest::Client,
r5_url: &str,
origins: Vec<[f64; 2]>,
destination: [f64; 2],
mode: &str,
) -> Result<Vec<Option<f64>>, String> {
let url = format!("{}/travel-times", r5_url);
let request_body = TravelTimeRequest {
origins,
destination,
mode: mode.to_string(),
};
let resp = client
.post(&url)
.json(&request_body)
.timeout(std::time::Duration::from_secs(60))
.send()
.await
.map_err(|e| {
warn!("R5 request failed: {}", e);
format!("R5 service error: {}", e)
})?;
if !resp.status().is_success() {
let status = resp.status();
let body = resp.text().await.unwrap_or_default();
warn!("R5 returned {}: {}", status, body);
return Err(format!("R5 service returned {}: {}", status, body));
}
let body: TravelTimeResponse = resp.json().await.map_err(|e| {
warn!("Failed to parse R5 response: {}", e);
format!("Failed to parse R5 response: {}", e)
})?;
Ok(body.travel_times)
}