use super::*;
use crate::error::TransportError;
use reqwest::Client;
use std::sync::Arc;
use tokio::sync::Mutex;
use tracing::{debug, trace};
pub struct HttpTransport {
client: Client,
endpoint: String,
stats: Arc<Mutex<TransportStats>>,
}
impl HttpTransport {
pub async fn new(endpoint: &str) -> Result<Self> {
let client = Client::new();
let response = client.get(endpoint).send().await.map_err(|e| {
TransportError::ConnectionFailed(format!("Failed to connect to HTTP endpoint: {e}"))
})?;
if !response.status().is_success() {
return Err(TransportError::ConnectionFailed(format!(
"HTTP endpoint returned status: {}",
response.status()
))
.into());
}
let stats = TransportStats {
connection_time: Some(chrono::Utc::now()),
..Default::default()
};
Ok(Self {
client,
endpoint: endpoint.to_string(),
stats: Arc::new(Mutex::new(stats)),
})
}
pub fn endpoint(&self) -> &str {
&self.endpoint
}
pub async fn stats(&self) -> TransportStats {
self.stats.lock().await.clone()
}
}
#[async_trait]
impl Transport for HttpTransport {
async fn send(&mut self, message: &str) -> Result<()> {
trace!("Sending message via HTTP: {}", message);
let response = self
.client
.post(&self.endpoint)
.header("Content-Type", "application/json")
.body(message.to_string())
.send()
.await
.map_err(|e| TransportError::SendFailed(format!("Failed to send HTTP request: {e}")))?;
if !response.status().is_success() {
return Err(TransportError::SendFailed(format!(
"HTTP request failed with status: {}",
response.status()
))
.into());
}
let mut stats = self.stats.lock().await;
stats.messages_sent += 1;
stats.bytes_sent += message.len() as u64;
stats.last_activity = Some(chrono::Utc::now());
debug!("Message sent successfully via HTTP");
Ok(())
}
async fn receive(&mut self) -> Result<Option<String>> {
trace!("HTTP transport receive called - not implemented for simple HTTP");
Ok(None)
}
async fn close(&mut self) -> Result<()> {
debug!("Closing HTTP transport (no-op)");
Ok(())
}
fn is_connected(&self) -> bool {
true
}
fn transport_type(&self) -> &'static str {
"http"
}
}