timvw_rust_runtime/
reqwest_service.rs1use std::task::{Context, Poll};
2
3use tower::Service;
4
5use crate::maybe::BoxFuture;
6use crate::{Body, BoxError};
7
8#[derive(Clone, Debug, Default)]
16pub struct ReqwestService {
17 client: reqwest::Client,
18}
19
20impl ReqwestService {
21 pub fn new(client: reqwest::Client) -> Self {
23 Self { client }
24 }
25
26 pub fn client(&self) -> &reqwest::Client {
28 &self.client
29 }
30}
31
32#[cfg(not(target_family = "wasm"))]
33impl Service<http::Request<Body>> for ReqwestService {
34 type Response = http::Response<reqwest::Body>;
35 type Error = BoxError;
36 type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
37
38 fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
39 Poll::Ready(Ok(()))
40 }
41
42 fn call(&mut self, request: http::Request<Body>) -> Self::Future {
43 let client = self.client.clone();
44 Box::pin(async move {
45 let request = request.map(|body| match body.as_bytes() {
46 Some(bytes) => reqwest::Body::from(bytes::Bytes::copy_from_slice(bytes)),
47 None => reqwest::Body::wrap(body),
48 });
49 let request = reqwest::Request::try_from(request)?;
50 let response = client.execute(request).await?;
51 Ok(http::Response::from(response))
52 })
53 }
54}
55
56#[cfg(target_family = "wasm")]
57impl Service<http::Request<Body>> for ReqwestService {
58 type Response = http::Response<Body>;
59 type Error = BoxError;
60 type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
61
62 fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
63 Poll::Ready(Ok(()))
64 }
65
66 fn call(&mut self, request: http::Request<Body>) -> Self::Future {
67 let client = self.client.clone();
68 Box::pin(async move {
69 let (parts, body) = request.into_parts();
70 let body = body.collect_bytes().await?;
71 let request = http::Request::from_parts(parts, reqwest::Body::from(body));
72 let request = reqwest::Request::try_from(request)?;
73 let mut response = client.execute(request).await?;
74 let mut builder = http::Response::builder().status(response.status());
75 if let Some(headers) = builder.headers_mut() {
76 *headers = std::mem::take(response.headers_mut());
77 }
78 Ok(builder.body(Body::wrap_stream(response.bytes_stream()))?)
79 })
80 }
81}