use axum::{extract::Path, http::StatusCode, response::{IntoResponse, Response}, routing::get, Router}; use std::net::SocketAddr; use std::sync::Arc; use tracing::{info, warn}; use uuid::Uuid; use crate::persist::Persist; #[derive(Clone)] pub struct HttpState { persist: Arc, } pub fn build_router(persist: Arc) -> Router { let state = HttpState { persist }; Router::new() .route("/jobs/{request_id}/logs", get(get_logs_moved)) .with_state(state) } async fn get_logs_moved( Path(request_id): Path, _state: axum::extract::State, ) -> Response { let base = std::env::var("LOGS_BASE_URL").ok(); let msg = if let Some(b) = base.as_ref() { format!("Logs have moved: {}/jobs/{}/logs", b.trim_end_matches('/'), request_id) } else { "Logs endpoint moved to logs-service; set LOGS_BASE_URL to enable 302 redirects".to_string() }; if let Some(b) = base { let loc = format!("{}/jobs/{}/logs", b.trim_end_matches('/'), request_id); return ( StatusCode::MOVED_PERMANENTLY, [(axum::http::header::LOCATION, loc.as_str())], msg, ).into_response(); } (StatusCode::GONE, msg).into_response() } pub async fn serve(addr: SocketAddr, persist: Arc, shutdown: impl std::future::Future) { let app = build_router(persist); info!(%addr, "http server starting"); let listener = tokio::net::TcpListener::bind(addr).await.expect("bind http"); let server = axum::serve(listener, app); let _ = tokio::select! { _ = server => {}, _ = shutdown => {}, }; }