apollo-router-plugin-creator by apollographql/skills
npx skills add https://github.com/apollographql/skills --skill apollo-router-plugin-creator为 Apollo Router 创建原生 Rust 插件。
┌────────┐ ┌────────────────┐ ┌────────────────────┐ ┌───────────────────┐ ┌─────────────────────┐
│ Client │ │ Router Service │ │ Supergraph Service │ │ Execution Service │ │ Subgraph Service(s) │
└────┬───┘ └────────┬───────┘ └──────────┬─────────┘ └─────────┬─────────┘ └──────────┬──────────┘
│ │ │ │ │
│ 发送请求 │ │ │ │
│──────────────────────────▶ │ │ │
│ │ │ │ │
│ │ 将原始 HTTP 请求转换为 GraphQL/JSON 请求 │ │ │
│ │──────────────────────────────────────────────────────▶ │ │
│ │ │ │ │
│ │ │ 启动查询计划执行 │ │
│ │ │───────────────────────────────────▶ │
│ │ │ │ │
│ │ │ ┌par [启动子操作]───────┐
│ │ │ │ │ │ │
│ │ │ │ │ 启动子操作 │ │
│ │ │ │ │────────────────────────────▶ │
│ │ │ │ │ │ │
│ │ │ ├[启动子操作]╌╌╌╌╌╌╌╌╌╌╌┤
│ │ │ │ │ │ │
│ │ │ │ │ 启动子操作 │ │
│ │ │ │ │────────────────────────────▶ │
│ │ │ │ │ │ │
│ │ │ ├[启动子操作]╌╌╌╌╌╌╌╌╌╌╌┤
│ │ │ │ │ │ │
│ │ │ │ │ 启动子操作 │ │
│ │ │ │ │────────────────────────────▶ │
│ │ │ │ │ │ │
│ │ │ └────────────────────────────────────┘
│ │ │ │ │
│ │ │ 组装并返回响应 │ │
│ │ ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│ │
│ │ │ │ │
│ │ 返回 GraphQL/JSON 响应 │ │ │
│ ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│ │ │
│ │ │ │ │
│ 返回 HTTP 响应 │ │ │ │
◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│ │ │ │
│ │ │ │ │
┌────┴───┐ ┌────────┴───────┐ ┌──────────┴─────────┐ ┌─────────┴─────────┐ ┌──────────┴──────────┐
│ Client │ │ Router Service │ │ Supergraph Service │ │ Execution Service │ │ Subgraph Service(s) │
└────────┘ └────────────────┘ └────────────────────┘ └───────────────────┘ └─────────────────────┘
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 服务 | 描述 |
|---|---|
router_service | 在 HTTP 请求生命周期的开始和结束时运行。例如,JWT 身份验证在 RouterService 中执行。如果你的自定义需要与 HTTP 上下文和标头交互,请定义 router_service。它不支持访问 body 属性。 |
supergraph_service | 在 GraphQL 请求生命周期的开始和结束时运行。如果你的自定义需要与 GraphQL 请求或 GraphQL 响应交互,请定义 supergraph_service。例如,你可以添加对匿名查询的检查。 |
execution_service | 处理查询计划生成后启动其执行。如果你的自定义包含控制执行的逻辑(例如,如果你想基于策略决策阻止特定查询),请定义 execution_service。 |
subgraph_service | 处理路由器和你的子图之间的通信。要配置此通信(例如,动态添加要传递给子图的 HTTP 标头),请定义 subgraph_service。其他服务每个客户端请求调用一次,而此服务在解析客户端请求所需的每个子图请求时调用一次。每次调用都会传递一个 subgraph 参数,指示相应子图的名称。 |
签名:
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
使用 ServiceBuilder 在任何服务中组合这些钩子:
| 钩子 | 目的 | 同步/异步 |
|---|---|---|
map_request(fn) | 在继续之前转换请求 | 同步 |
map_response(fn) | 在返回之前转换响应 | 同步 |
checkpoint(fn) | 验证/过滤,可以短路 | 同步 |
checkpoint_async(fn) | 异步验证,可以短路 | 异步 |
buffered() | 启用服务克隆(异步所需) | - |
instrument(span) | 围绕服务添加追踪跨度 | - |
rate_limit(num, period) | 控制请求吞吐量 | - |
timeout(duration) | 设置操作时间限制 | - |
根据所需数据:
router_servicesupergraph_serviceexecution_servicesubgraph_service根据时机:
router_service 请求supergraph_service 请求execution_service 请求subgraph_servicerouter_service 响应有关实现模式,请参阅 references/service-hooks.md。
创建新文件 src/plugins/my_plugin.rs 并包含必要的导入:
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";
每个插件都需要一个带有 Deserialize 和 JsonSchema 派生的配置结构体。JsonSchema 支持在编辑器中进行配置验证:
#[derive(Debug, Clone, Default, Deserialize, JsonSchema)]
struct MyPluginConfig {
/// 启用插件
enabled: bool,
// 根据需要添加其他配置字段
}
#[derive(Debug)]
struct MyPlugin {
configuration: MyPluginConfig,
}
使用所需的 Config 类型和 new 构造函数实现 Plugin 特征:
#[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 })
}
// 根据你的需求添加服务钩子(参见“选择服务钩子”部分)
}
根据你的需求选择要挂钩的服务,详细信息请参阅服务概述。
服务钩子示例:
fn supergraph_service(&self, service: supergraph::BoxService) -> supergraph::BoxService {
if !self.configuration.enabled {
return service;
}
ServiceBuilder::new()
.map_request(|req| { /* 转换请求 */ req })
.map_response(|res| { /* 转换响应 */ res })
.service(service)
.boxed()
}
在插件文件的底部,将其注册到路由器:
register_plugin!("acme", "my_plugin", MyPlugin);
在 src/plugins/mod.rs 中,添加你的模块:
pub mod my_plugin;
在路由器配置中启用你的插件:
plugins:
acme.my_plugin:
enabled: true
有关实现模式和代码示例,请参阅 references/service-hooks.md:
map_request, map_response)checkpoint_async, buffered)| 插件 | 服务钩子 | 模式 | 描述 |
|---|---|---|---|
forbid_mutations.rs | execution_service | checkpoint | 查询计划的简单门控 |
expose_query_plan.rs | execution + supergraph | Context passing | 多服务协调 |
cors.rs | router_service | HTTP layer | HTTP 级别的 CORS 处理 |
headers/ | subgraph_service | Layer composition | 复杂的标头操作 |
有关完整的代码示例和测试模式,请参阅 references/examples.md。
建议在开发路由器插件时安装 rust-best-practices 技能,以编写符合 Rust 惯用法的代码。如果已安装,请在生成或修改插件代码时遵循这些最佳实践。
每周安装次数
99
代码仓库
GitHub 星标数
33
首次出现
2026年2月20日
安全审计
安装于
codex96
opencode94
gemini-cli94
amp94
github-copilot94
kimi-cli94
Create native Rust plugins for Apollo Router.
┌────────┐ ┌────────────────┐ ┌────────────────────┐ ┌───────────────────┐ ┌─────────────────────┐
│ 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 | Description |
|---|---|
router_service | 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 |
supergraph_service | 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. |
execution_service | 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). |
subgraph_service | 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
Use ServiceBuilder to compose these hooks within any service:
| Hook | Purpose | Sync/Async |
|---|---|---|
map_request(fn) | Transform request before proceeding | Sync |
map_response(fn) | Transform response before returning | Sync |
checkpoint(fn) | Validate/filter, can short-circuit | Sync |
checkpoint_async(fn) | Async validation, can short-circuit | Async |
buffered() | Enable service cloning (needed for async) |
By data needed:
router_servicesupergraph_serviceexecution_servicesubgraph_serviceBy timing:
router_service requestsupergraph_service requestexecution_service requestsubgraph_servicerouter_service responseSee references/service-hooks.md for implementation patterns.
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";
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
}
#[derive(Debug)]
struct MyPlugin {
configuration: MyPluginConfig,
}
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)
}
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()
}
At the bottom of your plugin file, register it with the router:
register_plugin!("acme", "my_plugin", MyPlugin);
In src/plugins/mod.rs, add your module:
pub mod my_plugin;
Enable your plugin in the router configuration:
plugins:
acme.my_plugin:
enabled: true
For implementation patterns and code examples, see references/service-hooks.md:
map_request, map_response)checkpoint_async, buffered)Located in the Apollo Router plugins directory:
| Plugin | Service Hook | Pattern | Description |
|---|---|---|---|
forbid_mutations.rs | execution_service | checkpoint | Simple gate on query plan |
expose_query_plan.rs | execution + supergraph | Context passing | Multi-service coordination |
cors.rs | router_service | HTTP layer | CORS handling at HTTP level |
For full code examples and testing patterns, see references/examples.md.
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.
Weekly Installs
99
Repository
GitHub Stars
33
First Seen
Feb 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex96
opencode94
gemini-cli94
amp94
github-copilot94
kimi-cli94
agent-browser 浏览器自动化工具 - Vercel Labs 命令行网页操作与测试
157,400 周安装
| - |
instrument(span) | Add tracing span around service | - |
rate_limit(num, period) | Control request throughput | - |
timeout(duration) | Set operation time limit | - |
headers/subgraph_service |
| Layer composition |
| Complex header manipulation |