apollo-router-plugin-creator

作者: apollographql

为Apollo Router创建原生Rust插件。

npx skills add https://github.com/apollographql/skills --skill apollo-router-plugin-creator

Apollo 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

ServiceDescription
router_serviceRuns 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_serviceRuns 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_serviceHandles 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_serviceHandles 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:

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-

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.

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:

PluginService HookPatternDescription
forbid_mutations.rsexecution_servicecheckpointSimple gate on query plan
expose_query_plan.rsexecution + supergraphContext passingMulti-service coordination
cors.rsrouter_serviceHTTP layerCORS handling at HTTP level
headers/subgraph_serviceLayer compositionComplex 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

来自 apollographql 的更多技能

apollo-client
apollographql
Apollo Client 是一个全面的 JavaScript 状态管理库,使您能够通过 GraphQL 管理本地和远程数据。4.x 版本带来了改进的缓存、更好的 TypeScript 支持以及 React 19 兼容性。
official
apollo-client
apollographql
全面指南,涵盖使用Apollo Client 4.x构建React应用的查询、变更、缓存和状态管理。支持多种React框架和配置:客户端应用(Vite、CRA)、带React服务端组件的Next.js App Router、带流式SSR的React Router 7,以及TanStack Start。包含查询(useQuery、useLazyQuery)、变更(useMutation)的钩子,以及基于Suspense的模式(useSuspenseQuery、useBackgroundQuery),适用于现代React 18+和19...
official
apollo-connectors
apollographql
使用@source和@connect指令将REST API集成到GraphQL超级图中。提供结构化的5步流程:研究API结构、使用指令实现模式、通过rover supergraph compose验证、执行连接器以及测试覆盖。支持请求配置,包括标头、请求体负载、N+1模式的批处理以及通过$env注入环境变量。处理响应映射,包括字段选择、别名、嵌套数据的子选择以及实体...
official
apollo-federation
apollographql
Apollo Federation 支持将多个 GraphQL API(子图)组合成一个统一的超级图。
official
apollo-ios
apollographql
Apollo iOS 是一个面向 Apple 平台的强类型 GraphQL 客户端。它从你的 GraphQL 操作和模式生成 Swift 类型,并附带一个 async/await 客户端、一个规范化缓存(内存或 SQLite 支持)、一个可插拔的基于拦截器的 HTTP 传输层(处理查询、变更和多部分订阅),以及一个可选的 WebSocket 传输层(graphql-transport-ws),可承载任何操作类型。
official
apollo-kotlin
apollographql
Apollo Kotlin 是一个强类型的 GraphQL 客户端,能够根据你的 GraphQL 操作和模式生成 Kotlin 模型,可用于 Android、JVM 和 Kotlin 多平台项目。
official
apollo-mcp-server
apollographql
通过模型上下文协议将AI智能体连接到GraphQL API,内置内省与操作工具。将GraphQL操作暴露为MCP工具;支持三种操作来源:本地文件、GraphOS Studio集合和持久化查询清单。提供四种内省工具(introspect、search、validate、execute)用于模式探索和临时查询测试;压缩模式通过紧凑符号减少令牌使用。可通过静态标头配置身份验证...
official
apollo-router
apollographql
Apollo Router 是一个用 Rust 编写的高性能图形路由器,用于运行 Apollo Federation 2 超级图。它位于子图前端,负责查询规划、执行和响应组合。
official