Skip to content

Commit

Permalink
feat(web): Relax GrpcWebService request body type
Browse files Browse the repository at this point in the history
  • Loading branch information
tottoto committed Nov 7, 2024
1 parent 0846e6e commit e5d6d5d
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 10 deletions.
17 changes: 12 additions & 5 deletions tonic-web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ const DEFAULT_ALLOW_HEADERS: [HeaderName; 4] = [
since = "0.12.4",
note = "compose the `GrpcWebLayer` with the cors layer of your choice"
)]
pub fn enable<S>(service: S) -> CorsGrpcWeb<S>
pub fn enable<S, B>(service: S) -> CorsGrpcWeb<S>
where
S: Service<http::Request<BoxBody>, Response = http::Response<BoxBody>>,
S: Service<B>,
{
let cors = CorsLayer::new()
.allow_origin(AllowOrigin::mirror_request())
Expand All @@ -160,19 +160,24 @@ where
#[derive(Debug, Clone)]
pub struct CorsGrpcWeb<S>(tower_http::cors::Cors<GrpcWebService<S>>);

impl<S> Service<http::Request<BoxBody>> for CorsGrpcWeb<S>
impl<S, B> Service<http::Request<B>> for CorsGrpcWeb<S>
where
S: Service<http::Request<BoxBody>, Response = http::Response<BoxBody>>,
B: http_body::Body<Data = bytes::Bytes> + Send + 'static,
B::Error: Into<BoxError> + std::fmt::Display,
{
type Response = S::Response;
type Error = S::Error;
type Future = CorsGrpcWebResponseFuture<S::Future>;

fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.0.poll_ready(cx)
<tower_http::cors::Cors<GrpcWebService<S>> as Service<http::Request<B>>>::poll_ready(
&mut self.0,
cx,
)
}

fn call(&mut self, req: http::Request<BoxBody>) -> Self::Future {
fn call(&mut self, req: http::Request<B>) -> Self::Future {
CorsGrpcWebResponseFuture(self.0.call(req))
}
}
Expand Down Expand Up @@ -207,6 +212,8 @@ where
const NAME: &'static str = S::NAME;
}

type BoxError = Box<dyn std::error::Error + Send + Sync>;

pub(crate) mod util {
pub(crate) mod base64 {
use base64::{
Expand Down
21 changes: 16 additions & 5 deletions tonic-web/src/service.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use core::fmt;
use std::future::Future;
use std::pin::Pin;
use std::task::{ready, Context, Poll};
Expand Down Expand Up @@ -61,9 +62,11 @@ where
}
}

impl<S> Service<Request<BoxBody>> for GrpcWebService<S>
impl<S, B> Service<Request<B>> for GrpcWebService<S>
where
S: Service<Request<BoxBody>, Response = Response<BoxBody>>,
B: http_body::Body<Data = bytes::Bytes> + Send + 'static,
B::Error: Into<crate::BoxError> + fmt::Display,
{
type Response = S::Response;
type Error = S::Error;
Expand All @@ -73,7 +76,7 @@ where
self.inner.poll_ready(cx)
}

fn call(&mut self, req: Request<BoxBody>) -> Self::Future {
fn call(&mut self, req: Request<B>) -> Self::Future {
match RequestKind::new(req.headers(), req.method(), req.version()) {
// A valid grpc-web request, regardless of HTTP version.
//
Expand Down Expand Up @@ -113,7 +116,7 @@ where
debug!(kind = "other h2", content_type = ?req.headers().get(header::CONTENT_TYPE));
ResponseFuture {
case: Case::Other {
future: self.inner.call(req),
future: self.inner.call(req.map(tonic::body::boxed)),
},
}
}
Expand Down Expand Up @@ -194,7 +197,11 @@ impl<'a> RequestKind<'a> {
// Mutating request headers to conform to a gRPC request is not really
// necessary for us at this point. We could remove most of these except
// maybe for inserting `header::TE`, which tonic should check?
fn coerce_request(mut req: Request<BoxBody>, encoding: Encoding) -> Request<BoxBody> {
fn coerce_request<B>(mut req: Request<B>, encoding: Encoding) -> Request<BoxBody>
where
B: http_body::Body<Data = bytes::Bytes> + Send + 'static,
B::Error: Into<crate::BoxError> + fmt::Display,
{
req.headers_mut().remove(header::CONTENT_LENGTH);

req.headers_mut()
Expand All @@ -211,7 +218,11 @@ fn coerce_request(mut req: Request<BoxBody>, encoding: Encoding) -> Request<BoxB
req.map(|b| GrpcWebCall::request(b, encoding).boxed_unsync())
}

fn coerce_response(res: Response<BoxBody>, encoding: Encoding) -> Response<BoxBody> {
fn coerce_response<B>(res: Response<B>, encoding: Encoding) -> Response<BoxBody>
where
B: http_body::Body<Data = bytes::Bytes> + Send + 'static,
B::Error: Into<crate::BoxError> + fmt::Display,
{
let mut res = res
.map(|b| GrpcWebCall::response(b, encoding))
.map(BoxBody::new);
Expand Down

0 comments on commit e5d6d5d

Please sign in to comment.