-
Notifications
You must be signed in to change notification settings - Fork 168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: http_only
compression middleware
#1133
Comments
Did a quick workaround by creating another middleware referencing ProxyGetRequestLayer. // compression_layer.rs
use flate2::write::GzEncoder;
use flate2::Compression;
use hyper::body::Bytes;
use hyper::{Body, Request, Response};
use jsonrpsee::core::error::Error as RpcError;
use std::error::Error;
use std::future::Future;
use std::io::Write;
use std::pin::Pin;
use std::task::{Context, Poll};
use tower::{Layer, Service};
#[derive(Debug, Clone)]
pub struct CompressionLayer {}
impl CompressionLayer {
pub fn new() -> Result<Self, RpcError> {
Ok(Self {})
}
}
impl<S> Layer<S> for CompressionLayer {
type Service = CompressionRequest<S>;
fn layer(&self, inner: S) -> Self::Service {
CompressionRequest::new(inner).expect("Path already validated in CompressionLayer; qed")
}
}
#[derive(Debug, Clone)]
pub struct CompressionRequest<S> {
inner: S,
}
impl<S> CompressionRequest<S> {
pub fn new(inner: S) -> Result<Self, RpcError> {
Ok(Self { inner })
}
}
impl<S> Service<Request<Body>> for CompressionRequest<S>
where
S: Service<Request<Body>, Response = Response<Body>>,
S::Response: 'static,
S::Error: Into<Box<dyn Error + Send + Sync>> + 'static,
S::Future: Send + 'static,
{
type Response = S::Response;
type Error = Box<dyn Error + Send + Sync + 'static>;
type Future =
Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>;
#[inline]
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx).map_err(Into::into)
}
fn call(&mut self, req: Request<Body>) -> Self::Future {
let fut = self.inner.call(req);
let res_fut = async move {
let res = fut.await.map_err(|err| err.into())?;
let body = res.into_body();
let bytes = hyper::body::to_bytes(body).await?;
let new_res = hyper::Response::builder()
.status(hyper::StatusCode::OK)
.header(
"content-type",
hyper::header::HeaderValue::from_static("application/json"),
)
.header(
"content-encoding",
hyper::header::HeaderValue::from_static("gzip"),
)
.body(hyper::Body::from(compress_body(bytes).await?))
.expect("Unable to parse response body for type conversion");
Ok(new_res)
};
Box::pin(res_fut)
}
}
async fn compress_body(bytes: Bytes) -> anyhow::Result<Vec<u8>> {
let compressed_body = tokio::spawn(async move {
let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
encoder.write_all(&bytes).unwrap();
encoder.finish().unwrap()
})
.await?;
Ok(compressed_body)
} |
All right, thanks for reporting. I think the jsonrpsee's trait bounds are too strict which assumes So it won't work without the |
If the layers are placed differently i'll get a different error // CompressionLayer first before ProxyGetRequestLayer
let service_builder = ServiceBuilder::new()
.layer(CompressionLayer::new())
.layer(ProxyGetRequestLayer::new("/health", "system_health")?); Build error error[E0277]: the size for values of type `(dyn StdError + std::marker::Send + std::marker::Sync + 'static)` cannot be known at compilation time
|
56 | let handle = server.start(module)?;
| ^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn StdError + std::marker::Send + std::marker::Sync + 'static)`
= help: the trait `StdError` is implemented for `Box<T>`
= note: required for `Box<(dyn StdError + std::marker::Send + std::marker::Sync + 'static)>` to implement `StdError`
note: required by a bound in `jsonrpsee::jsonrpsee_server::Server::<S, L>::start`
|
99 | <B as HttpBody>::Error: Send + Sync + StdError,
| ^^^^^^^^ required by this bound in `Server::<S, L>::start` |
Yeah, error type is probably not |
Currently using jsonrpsee http_only server and wanted to compress the response before returning to the client using tower-http CompressionLayer.
referencing: CorsLayer
After adding CompressionLayer it throw the following errors
The text was updated successfully, but these errors were encountered: