jsonrpsee_server/middleware/http/
proxy_get_request.rs1use crate::transport::http;
30use crate::{HttpBody, HttpRequest, HttpResponse};
31
32use http_body_util::BodyExt;
33use hyper::body::Bytes;
34use hyper::header::{ACCEPT, CONTENT_TYPE};
35use hyper::http::HeaderValue;
36use hyper::{Method, Uri};
37use jsonrpsee_core::BoxError;
38use jsonrpsee_types::{Id, RequestSer};
39use std::future::Future;
40use std::pin::Pin;
41use std::sync::Arc;
42use std::task::{Context, Poll};
43use tower::{Layer, Service};
44
45#[derive(Debug, thiserror::Error)]
47#[error("ProxyGetRequestLayer path must start with `/`, got `{0}`")]
48pub struct InvalidPath(String);
49
50#[derive(Debug, Clone)]
55pub struct ProxyGetRequestLayer {
56 path: String,
57 method: String,
58}
59
60impl ProxyGetRequestLayer {
61 pub fn new(path: impl Into<String>, method: impl Into<String>) -> Result<Self, InvalidPath> {
65 let path = path.into();
66 if !path.starts_with('/') {
67 return Err(InvalidPath(path));
68 }
69
70 Ok(Self { path, method: method.into() })
71 }
72}
73impl<S> Layer<S> for ProxyGetRequestLayer {
74 type Service = ProxyGetRequest<S>;
75
76 fn layer(&self, inner: S) -> Self::Service {
77 ProxyGetRequest::new(inner, &self.path, &self.method)
78 .expect("Path already validated in ProxyGetRequestLayer; qed")
79 }
80}
81
82#[derive(Debug, Clone)]
95pub struct ProxyGetRequest<S> {
96 inner: S,
97 path: Arc<str>,
98 method: Arc<str>,
99}
100
101impl<S> ProxyGetRequest<S> {
102 pub fn new(inner: S, path: &str, method: &str) -> Result<Self, InvalidPath> {
107 if !path.starts_with('/') {
108 return Err(InvalidPath(path.to_string()));
109 }
110
111 Ok(Self { inner, path: Arc::from(path), method: Arc::from(method) })
112 }
113}
114
115impl<S, B> Service<HttpRequest<B>> for ProxyGetRequest<S>
116where
117 S: Service<HttpRequest, Response = HttpResponse>,
118 S::Response: 'static,
119 S::Error: Into<BoxError> + 'static,
120 S::Future: Send + 'static,
121 B: http_body::Body<Data = Bytes> + Send + 'static,
122 B::Data: Send,
123 B::Error: Into<BoxError>,
124{
125 type Response = S::Response;
126 type Error = BoxError;
127 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>;
128
129 #[inline]
130 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
131 self.inner.poll_ready(cx).map_err(Into::into)
132 }
133
134 fn call(&mut self, mut req: HttpRequest<B>) -> Self::Future {
135 let modify = self.path.as_ref() == req.uri() && req.method() == Method::GET;
136
137 let req = if modify {
139 *req.method_mut() = Method::POST;
141 *req.uri_mut() = Uri::from_static("/");
143
144 req.headers_mut().insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
146 req.headers_mut().insert(ACCEPT, HeaderValue::from_static("application/json"));
147
148 let bytes = serde_json::to_vec(&RequestSer::borrowed(&Id::Number(0), &self.method, None))
150 .expect("Valid request; qed");
151
152 let body = HttpBody::from(bytes);
153
154 req.map(|_| body)
155 } else {
156 req.map(HttpBody::new)
157 };
158
159 let fut = self.inner.call(req);
161
162 let res_fut = async move {
164 let res = fut.await.map_err(|err| err.into())?;
165
166 if !modify {
168 return Ok(res);
169 }
170
171 let mut body = http_body_util::BodyStream::new(res.into_body());
172 let mut bytes = Vec::new();
173
174 while let Some(frame) = body.frame().await {
175 let data = frame?.into_data().map_err(|e| format!("{e:?}"))?;
176 bytes.extend(data);
177 }
178
179 #[derive(serde::Deserialize, Debug)]
180 struct RpcPayload<'a> {
181 #[serde(borrow)]
182 result: &'a serde_json::value::RawValue,
183 }
184
185 let response = if let Ok(payload) = serde_json::from_slice::<RpcPayload>(&bytes) {
186 http::response::ok_response(payload.result.to_string())
187 } else {
188 http::response::internal_error()
189 };
190
191 Ok(response)
192 };
193
194 Box::pin(res_fut)
195 }
196}