Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Plugin System

The gRPC-GraphQL Gateway includes a powerful plugin system that allows you to extend the gateway’s functionality by hooking into key lifecycle events.

Creating a Plugin

To create a plugin, implement the Plugin trait:

use grpc_graphql_gateway::plugin::Plugin;
use grpc_graphql_gateway::middleware::Context;
use async_graphql::{Request, Response};
use async_trait::async_trait;

pub struct MyPlugin;

#[async_trait]
impl Plugin for MyPlugin {
    type Error = Box<dyn std::error::Error + Send + Sync>;

    fn name(&self) -> &str {
        "MyPlugin"
    }

    async fn on_request(&self, _ctx: &Context, req: &Request) -> Result<(), Self::Error> {
        println!("Request received: {:?}", req.query);
        Ok(())
    }

    async fn on_response(&self, _ctx: &Context, res: &Response) -> Result<(), Self::Error> {
        println!("Response sent");
        Ok(())
    }

    async fn on_subgraph_request(&self, service_name: &str, metadata: &mut tonic::metadata::MetadataMap) -> Result<(), Self::Error> {
        println!("Sending request to subgraph: {}", service_name);
        metadata.insert("x-custom-header", "value".parse().unwrap());
        Ok(())
    }
    
    async fn on_schema_build(&self, builder: &mut grpc_graphql_gateway::schema::SchemaBuilder) -> Result<(), Self::Error> {
        // Modify schema builder here
        Ok(())
    }
}

Hook Points

The following hooks are available:

  • on_request: Called before the GraphQL request is executed.
  • on_response: Called after the GraphQL request is executed.
  • on_schema_build: Called during schema construction (allows modifying the schema).
  • on_subgraph_request: Called before a gRPC request is sent to a subgraph service.

Registering Plugins

Register plugins using GatewayBuilder:

let gateway = Gateway::builder()
    .register_plugin(MyPlugin)
    .build()?;

Dynamic Loading via Feature Flags

You can use Cargo features to conditionally compile and enable plugins.

In Cargo.toml:

[features]
my-plugin = []

In your code:

#[cfg(feature = "my-plugin")]
builder = builder.register_plugin(MyPlugin);