Skillshub apollo-router-plugin-creator
git clone https://github.com/ComeOnOliver/skillshub
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/apollographql/skills/apollo-router-plugin-creator" ~/.claude/skills/comeonoliver-skillshub-apollo-router-plugin-creator && rm -rf "$T"
skills/apollographql/skills/apollo-router-plugin-creator/SKILL.mdApollo Router Plugin Creator
Create native Rust plugins for Apollo Router.
Request Lifecycle
┌────────┐ ┌────────────────┐ ┌────────────────────┐ ┌───────────────────┐ ┌─────────────────────┐ │ Client │ │ Router Service │ │ Supergraph Service │ │ Execution Service │ │ Subgraph Service(s) │ └────┬───┘ └────────┬───────┘ └──────────┬─────────┘ └─────────┬─────────┘ └──────────┬──────────┘ │ │ │ │ │ │ Sends request │ │ │ │ │──────────────────────────▶ │ │ │ │ │ │ │ │ │ │ Converts raw HTTP request to GraphQL/JSON request │ │ │ │ │──────────────────────────────────────────────────────▶ │ │ │ │ │ │ │ │ │ │ Initiates query plan execution │ │ │ │ │───────────────────────────────────▶ │ │ │ │ │ │ │ │ │ ┌par [Initiates sub-operation]───────┐ │ │ │ │ │ │ │ │ │ │ │ │ Initiates sub-operation │ │ │ │ │ │ │────────────────────────────▶ │ │ │ │ │ │ │ │ │ │ │ ├[Initiates sub-operation]╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ │ │ │ │ │ │ │ │ │ Initiates sub-operation │ │ │ │ │ │ │────────────────────────────▶ │ │ │ │ │ │ │ │ │ │ │ ├[Initiates sub-operation]╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ │ │ │ │ │ │ │ │ │ Initiates sub-operation │ │ │ │ │ │ │────────────────────────────▶ │ │ │ │ │ │ │ │ │ │ │ └────────────────────────────────────┘ │ │ │ │ │ │ │ │ Assembles and returns response │ │ │ │ ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│ │ │ │ │ │ │ │ │ Returns GraphQL/JSON response │ │ │ │ ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│ │ │ │ │ │ │ │ │ Returns HTTP response │ │ │ │ ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│ │ │ │ │ │ │ │ │ ┌────┴───┐ ┌────────┴───────┐ ┌──────────┴─────────┐ ┌─────────┴─────────┐ ┌──────────┴──────────┐ │ Client │ │ Router Service │ │ Supergraph Service │ │ Execution Service │ │ Subgraph Service(s) │ └────────┘ └────────────────┘ └────────────────────┘ └───────────────────┘ └─────────────────────┘
Service Hooks
Service Overview
| Service | Description |
|---|---|
| Runs at the very beginning and very end of the HTTP request lifecycle.For example, JWT authentication is performed within the RouterService.Define router_service if your customization needs to interact with HTTP context and headers. It doesn't support access to the body property |
| Runs at the very beginning and very end of the GraphQL request lifecycle.Define supergraph_service if your customization needs to interact with the GraphQL request or the GraphQL response. For example, you can add a check for anonymous queries. |
| Handles initiating the execution of a query plan after it's been generated.Define execution_service if your customization includes logic to govern execution (for example, if you want to block a particular query based on a policy decision). |
| Handles communication between the router and your subgraphs.Define subgraph_service to configure this communication (for example, to dynamically add HTTP headers to pass to a subgraph).Whereas other services are called once per client request, this service is called once per subgraph request that's required to resolve the client's request. Each call is passed a subgraph parameter that indicates the name of the corresponding subgraph. |
Signatures:
fn router_service(&self, service: router::BoxService) -> router::BoxService fn supergraph_service(&self, service: supergraph::BoxService) -> supergraph::BoxService fn execution_service(&self, service: execution::BoxService) -> execution::BoxService fn subgraph_service(&self, name: &str, service: subgraph::BoxService) -> subgraph::BoxService
Individual Hooks (Tower Layers)
Use
ServiceBuilder to compose these hooks within any service:
| Hook | Purpose | Sync/Async |
|---|---|---|
| Transform request before proceeding | Sync |
| Transform response before returning | Sync |
| Validate/filter, can short-circuit | Sync |
| Async validation, can short-circuit | Async |
| Enable service cloning (needed for async) | - |
| Add tracing span around service | - |
| Control request throughput | - |
| Set operation time limit | - |
Choosing a Service Hook
By data needed:
- HTTP headers only →
router_service - GraphQL query/variables →
supergraph_service - Query plan →
execution_service - Per-subgraph control →
subgraph_service
By timing:
- Before GraphQL parsing →
requestrouter_service - After parsing, before planning →
requestsupergraph_service - After planning, before execution →
requestexecution_service - Before/after each subgraph call →
subgraph_service - Final response to client →
responserouter_service
See references/service-hooks.md for implementation patterns.
Quick Start
Step 1: Create Plugin File
Create a new file
src/plugins/my_plugin.rs with required imports:
use std::ops::ControlFlow; use apollo_router::plugin::{Plugin, PluginInit}; use apollo_router::register_plugin; use apollo_router::services::{router, subgraph, supergraph}; use schemars::JsonSchema; use serde::Deserialize; use tower::{BoxError, ServiceBuilder, ServiceExt}; const PLUGIN_NAME: &str = "my_plugin";
Step 2: Define Configuration Struct
Every plugin needs a configuration struct with
Deserialize and JsonSchema derives. The JsonSchema enables configuration validation in editors:
#[derive(Debug, Clone, Default, Deserialize, JsonSchema)] struct MyPluginConfig { /// Enable the plugin enabled: bool, // Add other configuration fields as needed }
Step 3: Define Plugin Struct
#[derive(Debug)] struct MyPlugin { configuration: MyPluginConfig, }
Step 4: Implement Plugin Trait
Implement the
Plugin trait with the required Config type and new constructor:
#[async_trait::async_trait] impl Plugin for MyPlugin { type Config = MyPluginConfig; async fn new(init: PluginInit<Self::Config>) -> Result<Self, BoxError> { Ok(MyPlugin { configuration: init.config }) } // Add service hooks based on your needs (see "Choosing a Service Hook" section) }
Step 5: Add Service Hooks
Choose which service(s) to hook based on your requirements, see Service Overview for details.
Example service hook:
fn supergraph_service(&self, service: supergraph::BoxService) -> supergraph::BoxService { if !self.configuration.enabled { return service; } ServiceBuilder::new() .map_request(|req| { /* transform request */ req }) .map_response(|res| { /* transform response */ res }) .service(service) .boxed() }
Step 6: Register Plugin
At the bottom of your plugin file, register it with the router:
register_plugin!("acme", "my_plugin", MyPlugin);
Step 7: Add Module to mod.rs
In
src/plugins/mod.rs, add your module:
pub mod my_plugin;
Step 8: Configure in YAML
Enable your plugin in the router configuration:
plugins: acme.my_plugin: enabled: true
Common Patterns
For implementation patterns and code examples, see references/service-hooks.md:
- Enable/disable pattern
- Request/response transformation (
,map_request
)map_response - Checkpoint (early return/short-circuit)
- Context passing between hooks
- Async operations (
,checkpoint_async
)buffered - Error response builders
Examples
Apollo Router Examples
Located in the Apollo Router plugins directory:
| Plugin | Service Hook | Pattern | Description |
|---|---|---|---|
| | checkpoint | Simple gate on query plan |
| execution + supergraph | Context passing | Multi-service coordination |
| | HTTP layer | CORS handling at HTTP level |
| | Layer composition | Complex header manipulation |
For full code examples and testing patterns, see references/examples.md.
Prerequisites
It is advised to have the rust-best-practices skill installed for writing idiomatic Rust code when developing router plugins. If installed, follow those best practices when generating or modifying plugin code.
Resources
- references/service-hooks.md - Detailed service hook implementations
- references/existing-plugins.md - Index of existing plugins
- references/examples.md - Full code examples and testing patterns
- Apollo Router plugins: https://github.com/apollographql/router/tree/dev/apollo-router/src/plugins