use anyhow::{Context, Result};
use serde_json::Value;
use super::{Transport, is_notification};
pub struct HttpTransport {
client: reqwest::Client,
url: String,
}
impl HttpTransport {
pub fn new(url: String) -> Self {
Self {
client: reqwest::Client::new(),
url,
}
}
}
#[async_trait::async_trait]
impl Transport for HttpTransport {
async fn send(&self, request: Value) -> Result<Value> {
let notif = is_notification(&request);
let resp = self
.client
.post(&self.url)
.json(&request)
.send()
.await
.with_context(|| format!("POST {} failed", self.url))?;
let status = resp.status();
let body = resp.text().await.context("reading HTTP response body")?;
if notif {
return Ok(Value::Null);
}
if !status.is_success() {
anyhow::bail!("HTTP {status}: {body}");
}
if body.trim().is_empty() {
return Ok(Value::Null);
}
let val: Value = serde_json::from_str(&body)
.with_context(|| format!("parsing JSON response: {body}"))?;
Ok(val)
}
}