apollo-router-plugin-creator
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseApollo Router Plugin Creator
Apollo Router 插件创建器
Create native Rust plugins for Apollo Router.
为Apollo Router创建原生Rust插件。
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) │
└────────┘ └────────────────┘ └────────────────────┘ └───────────────────┘ └─────────────────────┘┌────────┐ ┌────────────────┐ ┌────────────────────┐ ┌───────────────────┐ ┌─────────────────────┐
│ 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:
rust
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| 服务名称 | 描述 |
|---|---|
| 在HTTP请求生命周期的最开始和最末尾运行。例如,JWT认证在RouterService中执行。如果你的定制需要与HTTP上下文和头信息交互,请定义router_service。它不支持访问body属性 |
| 在GraphQL请求生命周期的最开始和最末尾运行。如果你的定制需要与GraphQL请求或GraphQL响应交互,请定义supergraph_service。例如,你可以添加匿名查询检查。 |
| 在查询计划生成后处理其执行的初始化。如果你的定制包含控制执行的逻辑(例如,你想要根据策略决策阻止特定查询),请定义execution_service。 |
| 处理路由与子图之间的通信。请定义subgraph_service来配置此通信(例如,动态添加要传递给子图的HTTP头)。与其他每个客户端请求调用一次的服务不同,此服务在解析客户端请求所需的每个子图请求时调用一次。每次调用都会传入一个subgraph参数,指示对应子图的名称。 |
签名:
rust
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::BoxServiceIndividual Hooks (Tower Layers)
独立钩子(Tower Layers)
Use to compose these hooks within any service:
ServiceBuilder| 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 | - |
使用在任意服务中组合这些钩子:
ServiceBuilder| 钩子名称 | 用途 | 同步/异步 |
|---|---|---|
| 在继续处理前转换请求 | 同步 |
| 在返回前转换响应 | 同步 |
| 验证/过滤,可提前终止请求流程 | 同步 |
| 异步验证,可提前终止请求流程 | 异步 |
| 启用服务克隆(异步场景所需) | - |
| 在服务周围添加追踪 span | - |
| 控制请求吞吐量 | - |
| 设置操作时间限制 | - |
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 → request
router_service - After parsing, before planning → request
supergraph_service - After planning, before execution → request
execution_service - Before/after each subgraph call →
subgraph_service - Final response to client → response
router_service
See references/service-hooks.md for implementation patterns.
按所需数据选择:
- 仅需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。
Quick Start
快速开始
Step 1: Create Plugin File
步骤1:创建插件文件
Create a new file with required imports:
src/plugins/my_plugin.rsrust
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";创建新文件并添加必要的导入:
src/plugins/my_plugin.rsrust
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
步骤2:定义配置结构体
Every plugin needs a configuration struct with and derives. The enables configuration validation in editors:
DeserializeJsonSchemaJsonSchemarust
#[derive(Debug, Clone, Default, Deserialize, JsonSchema)]
struct MyPluginConfig {
/// Enable the plugin
enabled: bool,
// Add other configuration fields as needed
}每个插件都需要一个带有和派生宏的配置结构体。可在编辑器中实现配置验证:
DeserializeJsonSchemaJsonSchemarust
#[derive(Debug, Clone, Default, Deserialize, JsonSchema)]
struct MyPluginConfig {
/// 启用插件
enabled: bool,
// 根据需要添加其他配置字段
}Step 3: Define Plugin Struct
步骤3:定义插件结构体
rust
#[derive(Debug)]
struct MyPlugin {
configuration: MyPluginConfig,
}rust
#[derive(Debug)]
struct MyPlugin {
configuration: MyPluginConfig,
}Step 4: Implement Plugin Trait
步骤4:实现Plugin trait
Implement the trait with the required type and constructor:
PluginConfignewrust
#[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)
}使用所需的类型和构造函数实现 trait:
ConfignewPluginrust
#[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 })
}
// 根据需求添加服务钩子(请参阅“选择服务钩子”章节)
}Step 5: Add Service Hooks
步骤5:添加服务钩子
Choose which service(s) to hook based on your requirements, see Service Overview for details.
Example service hook:
rust
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()
}根据你的需求选择要挂钩的服务,详情请参阅服务概述。
示例服务钩子:
rust
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()
}Step 6: Register Plugin
步骤6:注册插件
At the bottom of your plugin file, register it with the router:
rust
register_plugin!("acme", "my_plugin", MyPlugin);在插件文件的底部,将其注册到路由:
rust
register_plugin!("acme", "my_plugin", MyPlugin);Step 7: Add Module to mod.rs
步骤7:在YAML中配置
In , add your module:
src/plugins/mod.rsrust
pub mod my_plugin;在路由配置中启用你的插件:
yaml
plugins:
acme.my_plugin:
enabled: trueStep 8: Configure in YAML
常见模式
Enable your plugin in the router configuration:
yaml
plugins:
acme.my_plugin:
enabled: true有关实现模式和代码示例,请参阅references/service-hooks.md:
- 启用/禁用模式
- 请求/响应转换(、
map_request)map_response - Checkpoint(提前返回/终止流程)
- 钩子间上下文传递
- 异步操作(、
checkpoint_async)buffered - 错误响应构建器
Common Patterns
示例
—
Apollo Router 示例
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
| 插件名称 | 服务钩子 | 模式 | 描述 |
|---|---|---|---|
| | checkpoint | 对查询计划的简单限制 |
| execution + supergraph | 上下文传递 | 多服务协调 |
| | HTTP层处理 | 在HTTP层处理CORS |
| | 层组合 | 复杂的头信息处理 |
有关完整代码示例和测试模式,请参阅references/examples.md。
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.
建议安装rust-best-practices技能,以便在开发路由插件时编写符合规范的Rust代码。如果已安装,请在生成或修改插件代码时遵循这些最佳实践。
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.
- references/service-hooks.md - 详细的服务钩子实现
- references/existing-plugins.md - 现有插件索引
- references/examples.md - 完整代码示例和测试模式
- Apollo Router插件:https://github.com/apollographql/router/tree/dev/apollo-router/src/plugins
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
—