alloy_transport_http/
reqwest_transport.rsuse crate::{Http, HttpConnect};
use alloy_json_rpc::{RequestPacket, ResponsePacket};
use alloy_transport::{
utils::guess_local_url, TransportConnect, TransportError, TransportErrorKind, TransportFut,
};
use std::task;
use tower::Service;
use tracing::{debug, debug_span, trace, Instrument};
use url::Url;
pub use reqwest::Client;
pub type ReqwestTransport = Http<Client>;
pub type ReqwestConnect = HttpConnect<ReqwestTransport>;
impl TransportConnect for ReqwestConnect {
type Transport = ReqwestTransport;
fn is_local(&self) -> bool {
guess_local_url(self.url.as_str())
}
fn get_transport<'a: 'b, 'b>(
&'a self,
) -> alloy_transport::Pbf<'b, Self::Transport, TransportError> {
Box::pin(async move { Ok(Http::with_client(Client::new(), self.url.clone())) })
}
}
impl Http<Client> {
pub fn new(url: Url) -> Self {
Self { client: Default::default(), url }
}
fn request_reqwest(&self, req: RequestPacket) -> TransportFut<'static> {
let this = self.clone();
let span: tracing::Span = debug_span!("ReqwestTransport", url = %self.url);
Box::pin(
async move {
let resp = this
.client
.post(this.url)
.json(&req)
.send()
.await
.map_err(TransportErrorKind::custom)?;
let status = resp.status();
debug!(%status, "received response from server");
let body = resp.bytes().await.map_err(TransportErrorKind::custom)?;
debug!(bytes = body.len(), "retrieved response body. Use `trace` for full body");
trace!(body = %String::from_utf8_lossy(&body), "response body");
if status != reqwest::StatusCode::OK {
return Err(TransportErrorKind::http_error(
status.as_u16(),
String::from_utf8_lossy(&body).into_owned(),
));
}
serde_json::from_slice(&body)
.map_err(|err| TransportError::deser_err(err, String::from_utf8_lossy(&body)))
}
.instrument(span),
)
}
}
impl Service<RequestPacket> for Http<reqwest::Client> {
type Response = ResponsePacket;
type Error = TransportError;
type Future = TransportFut<'static>;
#[inline]
fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> task::Poll<Result<(), Self::Error>> {
task::Poll::Ready(Ok(()))
}
#[inline]
fn call(&mut self, req: RequestPacket) -> Self::Future {
self.request_reqwest(req)
}
}
impl Service<RequestPacket> for &Http<reqwest::Client> {
type Response = ResponsePacket;
type Error = TransportError;
type Future = TransportFut<'static>;
#[inline]
fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> task::Poll<Result<(), Self::Error>> {
task::Poll::Ready(Ok(()))
}
#[inline]
fn call(&mut self, req: RequestPacket) -> Self::Future {
self.request_reqwest(req)
}
}