关于 apollo-router-plugin-creator
这是用于为 Apollo Router 创建原生 Rust 插件的指南,说明如何选择请求生命周期钩子。它介绍请求与响应处理、验证、追踪、速率限制和超时的组合方式。
主要功能
- 01Router 生命周期服务钩子
- 02请求与响应转换
- 03同步与异步检查点
- 04追踪、速率限制与超时
- 05插件配置与注册
适用场景
- 01在 HTTP 层添加身份验证
- 02在规划前验证 GraphQL 请求
- 03控制查询计划的执行
- 04自定义子图调用的请求头
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ apollographql/ skills --skill apollo-router-plugin-creator安装后在 Claude Code 中输入/apollo-router-plugin-creator确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/examples.mdexisting-plugins.mdservice-hooks.md详细介绍
Apollo Router 插件创建器
为 Apollo Router 创建原生 Rust 插件。
请求生命周期
┌────────┐ ┌────────────────┐ ┌────────────────────┐ ┌───────────────────┐ ┌─────────────────────┐
│ 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) │
└────────┘ └────────────────┘ └────────────────────┘ └───────────────────┘ └─────────────────────┘
服务钩子
服务概览
| 服务 | 说明 |
|---|---|
router_service | 在 HTTP 请求生命周期的最开始和最后运行。例如,JWT 身份验证在 RouterService 中执行。如果自定义逻辑需要与 HTTP 上下文和标头交互,请定义 router_service。它不支持访问 body 属性 |
supergraph_service | 在 GraphQL 请求生命周期的最开始和最后运行。如果自定义逻辑需要与 GraphQL 请求或 GraphQL 响应交互,请定义 supergraph_service。例如,可以添加对匿名查询的检查。 |
execution_service | 在查询计划生成后,负责启动其执行。如果自定义逻辑包含用于控制执行的逻辑(例如,想根据策略决策阻止特定查询),请定义 execution_service。 |
subgraph_service | 负责处理路由器与子图之间的通信。定义 subgraph_service 可配置此通信(例如,动态添加要传递给子图的 HTTP 标头)。其他服务每个客户端请求调用一次,而此服务则会针对解析客户端请求所需的每个子图请求调用一次。每次调用都会传入一个 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
单独的钩子(Tower 层)
使用 ServiceBuilder 在任意服务中组合这些钩子:
| 钩子 | 用途 | 同步/异步 |
|---|---|---|
map_request(fn) | 在继续处理前转换请求 | 同步 |
map_response(fn) | 在返回前转换响应 | 同步 |
checkpoint(fn) | 验证/筛选,可短路处理 | 同步 |
checkpoint_async(fn) | 异步验证,可短路处理 | 异步 |
buffered() | 启用服务克隆(异步处理所需) | - |
instrument(span) | 在服务周围添加跟踪 span | - |
rate_limit(num, period) | 控制请求吞吐量 | - |
timeout(duration) | 设置操作时限 | - |
选择服务钩子
按所需数据选择:
- 仅 HTTP 标头 →
router_service - GraphQL 查询/变量 →
supergraph_service - 查询计划 →
execution_service - 控制各个子图 →
subgraph_service
按时机选择:
- GraphQL 解析前 →
router_service请求 - 解析后、规划前 →
supergraph_service请求 - 规划后、执行前 →
execution_service请求 - 每次调用子图前后 →
subgraph_service - 返回给客户端的最终响应 →
router_service响应
有关实现模式,请参阅 references/service-hooks.md。
快速入门
步骤 1:创建插件文件
创建新文件 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";
步骤 2:定义配置结构体
每个插件都需要一个带有 Deserialize 和 JsonSchema 派生项的配置结构体。JsonSchema 可在编辑器中启用配置验证:
#[derive(Debug, Clone, Default, Deserialize, JsonSchema)]
struct MyPluginConfig {
/// Enable the plugin
enabled: bool,
// Add other configuration fields as needed
}
步骤 3:定义插件结构体
#[derive(Debug)]
struct MyPlugin {
configuration: MyPluginConfig,
}
步骤 4:实现插件 trait
实现 Plugin trait,并提供所需的 Config 类型和 new 构造函数:
#[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)
}
步骤 5:添加服务钩子
根据需求选择要挂接的服务,详情请参阅服务概览。
服务钩子示例:
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()
}
步骤 6:注册插件
在插件文件底部,将插件注册到路由器:
register_plugin!("acme", "my_plugin", MyPlugin);
步骤 7:将模块添加到 mod.rs
在 src/plugins/mod.rs 中添加你的模块:
pub mod my_plugin;
步骤 8:在 YAML 中配置
在路由器配置中启用插件:
plugins:
acme.my_plugin:
enabled: true
常见模式
有关实现模式和代码示例,请参阅 references/service-hooks.md:
- 启用/禁用模式
- 请求/响应转换(
map_request、map_response) - 检查点(提前返回/短路)
- 在钩子之间传递上下文
- 异步操作(
checkpoint_async、buffered) - 错误响应构造器
示例
Apollo Router 示例
| 插件 | 服务钩子 | 模式 | 描述 |
|---|---|---|---|
forbid_mutations.rs | execution_service | 检查点 | 对查询计划实施简单门控 |
expose_query_plan.rs | execution + supergraph | 上下文传递 | 多服务协调 |
cors.rs | router_service | HTTP 层 | 在 HTTP 层处理 CORS |
headers/ | subgraph_service | 层组合 | 复杂的标头操作 |
完整的代码示例和测试模式,请参阅 references/examples.md。
前提条件
建议安装 rust-best-practices 技能,以便在开发路由器插件时编写符合 Rust 惯例的代码。如果已安装,请在生成或修改插件代码时遵循其中的最佳实践。
资源
- references/service-hooks.md - 详细的服务钩子实现
- references/existing-plugins.md - 现有插件索引
- references/examples.md - 完整代码示例和测试模式
- Apollo Router 插件:https://github.com/apollographql/router/tree/dev/apollo-router/src/plugins
评论
支持 Markdown