alloy_transport_http/
reqwest_transport.rs1use crate::{Http, HttpConnect};
2use alloy_json_rpc::{RequestPacket, ResponsePacket};
3use alloy_transport::{
4 utils::guess_local_url, BoxTransport, TransportConnect, TransportError, TransportErrorKind,
5 TransportFut, TransportResult,
6};
7use std::task;
8use tower::Service;
9use tracing::{debug, debug_span, trace, Instrument};
10use url::Url;
11
12pub use reqwest::Client;
14
15pub type ReqwestTransport = Http<Client>;
17
18pub type ReqwestConnect = HttpConnect<ReqwestTransport>;
20
21impl TransportConnect for ReqwestConnect {
22 fn is_local(&self) -> bool {
23 guess_local_url(self.url.as_str())
24 }
25
26 async fn get_transport(&self) -> Result<BoxTransport, TransportError> {
27 Ok(BoxTransport::new(Http::with_client(Client::new(), self.url.clone())))
28 }
29}
30
31impl Http<Client> {
32 pub fn new(url: Url) -> Self {
34 Self { client: Default::default(), url }
35 }
36
37 async fn do_reqwest(self, req: RequestPacket) -> TransportResult<ResponsePacket> {
38 let resp = self
39 .client
40 .post(self.url)
41 .json(&req)
42 .send()
43 .await
44 .map_err(TransportErrorKind::custom)?;
45 let status = resp.status();
46
47 debug!(%status, "received response from server");
48
49 let body = resp.bytes().await.map_err(TransportErrorKind::custom)?;
53
54 debug!(bytes = body.len(), "retrieved response body. Use `trace` for full body");
55 trace!(body = %String::from_utf8_lossy(&body), "response body");
56
57 if !status.is_success() {
58 return Err(TransportErrorKind::http_error(
59 status.as_u16(),
60 String::from_utf8_lossy(&body).into_owned(),
61 ));
62 }
63
64 serde_json::from_slice(&body)
68 .map_err(|err| TransportError::deser_err(err, String::from_utf8_lossy(&body)))
69 }
70}
71
72impl Service<RequestPacket> for Http<reqwest::Client> {
73 type Response = ResponsePacket;
74 type Error = TransportError;
75 type Future = TransportFut<'static>;
76
77 #[inline]
78 fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> task::Poll<Result<(), Self::Error>> {
79 task::Poll::Ready(Ok(()))
81 }
82
83 #[inline]
84 fn call(&mut self, req: RequestPacket) -> Self::Future {
85 let this = self.clone();
86 let span = debug_span!("ReqwestTransport", url = %this.url);
87 Box::pin(this.do_reqwest(req).instrument(span))
88 }
89}