apollo-router-plugin-creator

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Apollo 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

服务概述

ServiceDescription
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:
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
服务名称描述
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参数,指示对应子图的名称。
签名:
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

Individual Hooks (Tower Layers)

独立钩子(Tower Layers)

Use
ServiceBuilder
to compose these hooks within any service:
HookPurposeSync/Async
map_request(fn)
Transform request before proceedingSync
map_response(fn)
Transform response before returningSync
checkpoint(fn)
Validate/filter, can short-circuitSync
checkpoint_async(fn)
Async validation, can short-circuitAsync
buffered()
Enable service cloning (needed for async)-
instrument(span)
Add tracing span around service-
rate_limit(num, period)
Control request throughput-
timeout(duration)
Set operation time limit-
使用
ServiceBuilder
在任意服务中组合这些钩子:
钩子名称用途同步/异步
map_request(fn)
在继续处理前转换请求同步
map_response(fn)
在返回前转换响应同步
checkpoint(fn)
验证/过滤,可提前终止请求流程同步
checkpoint_async(fn)
异步验证,可提前终止请求流程异步
buffered()
启用服务克隆(异步场景所需)-
instrument(span)
在服务周围添加追踪 span-
rate_limit(num, period)
控制请求吞吐量-
timeout(duration)
设置操作时间限制-

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 →
    router_service
    request
  • After parsing, before planning →
    supergraph_service
    request
  • After planning, before execution →
    execution_service
    request
  • Before/after each subgraph call →
    subgraph_service
  • Final response to client →
    router_service
    response
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
src/plugins/my_plugin.rs
with required imports:
rust
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.rs
并添加必要的导入:
rust
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
Deserialize
and
JsonSchema
derives. The
JsonSchema
enables configuration validation in editors:
rust
#[derive(Debug, Clone, Default, Deserialize, JsonSchema)]
struct MyPluginConfig {
  /// Enable the plugin
  enabled: bool,
  // Add other configuration fields as needed
}
每个插件都需要一个带有
Deserialize
JsonSchema
派生宏的配置结构体。
JsonSchema
可在编辑器中实现配置验证:
rust
#[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
Plugin
trait with the required
Config
type and
new
constructor:
rust
#[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)
}
使用所需的
Config
类型和
new
构造函数实现
Plugin
trait:
rust
#[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
src/plugins/mod.rs
, add your module:
rust
pub mod my_plugin;
在路由配置中启用你的插件:
yaml
plugins:
  acme.my_plugin:
    enabled: true

Step 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
插件名称服务钩子模式描述
forbid_mutations.rs
execution_service
checkpoint对查询计划的简单限制
expose_query_plan.rs
execution + supergraph上下文传递多服务协调
cors.rs
router_service
HTTP层处理在HTTP层处理CORS
headers/
subgraph_service
层组合复杂的头信息处理
有关完整代码示例和测试模式,请参阅references/examples.md

Examples

前置条件

Apollo Router Examples

PluginService HookPatternDescription
forbid_mutations.rs
execution_service
checkpointSimple gate on query plan
expose_query_plan.rs
execution + supergraphContext passingMulti-service coordination
cors.rs
router_service
HTTP layerCORS handling at HTTP level
headers/
subgraph_service
Layer compositionComplex 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.

Resources