Skip to content

Commit

Permalink
Add support for gRPC-web module to bridge gRPC-web client requests to…
Browse files Browse the repository at this point in the history
… gRPC server requests
  • Loading branch information
andrewhavck committed Sep 16, 2024
1 parent 3d42cf0 commit b7ea433
Show file tree
Hide file tree
Showing 11 changed files with 623 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .bleep
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9b92c0fed7b703c61415414c69ff196e9deb11eb
761f676b044dcf0d34205f96921e3385ffac7810
80 changes: 80 additions & 0 deletions pingora-core/src/modules/http/grpc_web.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2024 Cloudflare, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use super::*;
use crate::protocols::http::bridge::grpc_web::GrpcWebCtx;
use std::ops::{Deref, DerefMut};

/// gRPC-web bridge module, this will convert
/// HTTP/1.1 gRPC-web requests to H2 gRPC requests
#[derive(Default)]
pub struct GrpcWebBridge(GrpcWebCtx);

impl Deref for GrpcWebBridge {
type Target = GrpcWebCtx;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for GrpcWebBridge {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

#[async_trait]
impl HttpModule for GrpcWebBridge {
fn as_any(&self) -> &dyn std::any::Any {
self
}

fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}

async fn request_header_filter(&mut self, req: &mut RequestHeader) -> Result<()> {
self.0.request_header_filter(req);
Ok(())
}

async fn response_header_filter(
&mut self,
resp: &mut ResponseHeader,
_end_of_stream: bool,
) -> Result<()> {
self.0.response_header_filter(resp);
Ok(())
}

fn response_trailer_filter(
&mut self,
trailers: &mut Option<Box<HeaderMap>>,
) -> Result<Option<Bytes>> {
if let Some(trailers) = trailers {
return self.0.response_trailer_filter(trailers);
}
Ok(None)
}
}

/// The builder for gRPC-web bridge module
pub struct GrpcWeb;

impl HttpModuleBuilder for GrpcWeb {
fn init(&self) -> Module {
Box::new(GrpcWebBridge::default())
}
}
30 changes: 30 additions & 0 deletions pingora-core/src/modules/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
//! See the [ResponseCompression] module for an example of how to implement a basic module.

pub mod compression;
pub mod grpc_web;

use async_trait::async_trait;
use bytes::Bytes;
use http::HeaderMap;
use once_cell::sync::OnceCell;
use pingora_error::Result;
use pingora_http::{RequestHeader, ResponseHeader};
Expand Down Expand Up @@ -61,6 +63,13 @@ pub trait HttpModule {
Ok(())
}

fn response_trailer_filter(
&mut self,
_trailers: &mut Option<Box<HeaderMap>>,
) -> Result<Option<Bytes>> {
Ok(None)
}

fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
Expand Down Expand Up @@ -226,6 +235,27 @@ impl HttpModuleCtx {
}
Ok(())
}

/// Run the `response_trailer_filter` for all the modules according to their orders.
///
/// Returns an `Option<Bytes>` which can be used to write response trailers into
/// the response body. Note, if multiple modules attempt to write trailers into
/// the body the last one will be used.
///
/// Implementors that intend to write trailers into the body need to ensure their filter
/// is using an encoding that supports this.
pub fn response_trailer_filter(
&mut self,
trailers: &mut Option<Box<HeaderMap>>,
) -> Result<Option<Bytes>> {
let mut encoded = None;
for filter in self.module_ctx.iter_mut() {
if let Some(buf) = filter.response_trailer_filter(trailers)? {
encoded = Some(buf);
}
}
Ok(encoded)
}
}

#[cfg(test)]
Expand Down
Loading

0 comments on commit b7ea433

Please sign in to comment.