Apollo Router Plugin Creator

作者 apollographqlc288eb80629dMIT117 个星标收录于 2026年10月8日更新于 2026年10月8日仓库今天更新

Guide for writing Apollo Router native Rust plugins. Use this skill when: (1) users want to create a new router plugin, (2) users want to add service hooks (router_service, supergraph_service, execution_service, subgraph_service), (3) users want to modify an existing router plugin, (4) users need to understand router plugin patterns or the request lifecycle. (5) triggers on requests like "create a new plugin", "add a router plugin", "modify the X plugin", or "add subgraph_service hook".

AI 生成的概览

指导为 Apollo Router 编写原生 Rust 插件,涵盖服务钩子、请求生命周期与注册流程。

功能
该技能提供创建和修改 Apollo Router 原生 Rust 插件的指导。它讲解请求生命周期、四种服务钩子(router、supergraph、execution、subgraph)、Tower 层钩子,以及启用/禁用、请求与响应转换、检查点、上下文传递和异步操作等常见模式。它给出分步快速上手流程,包括创建插件文件、配置结构体、实现 Plugin trait、添加服务钩子、注册插件、接入模块以及在 YAML 中配置,并指向随附的参考文件以获取示例和现有插件。
适用场景
适用于创建新的 Apollo Router 插件、添加或修改 router_service 或 subgraph_service 等服务钩子、修改现有路由插件,或需要理解路由插件模式与请求生命周期时。
运行要求
需要支持原生插件的 Apollo Router 项目和 Rust 工具链;该技能本身仅为说明文档,不附带脚本,但引用随附的 Markdown 文件。它建议安装 rust-best-practices 技能以编写符合习惯的 Rust 代码。

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:

rust
fn router_service(&self, service: router::BoxService) -> router::BoxServicefn supergraph_service(&self, service: supergraph::BoxService) -> supergraph::BoxServicefn execution_service(&self, service: execution::BoxService) -> execution::BoxServicefn 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 [blocked] for implementation patterns.

Quick Start

Step 1: Create Plugin File

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";

Step 2: Define Configuration Struct

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}

Step 3: Define Plugin Struct

rust
#[derive(Debug)]struct MyPlugin {  configuration: MyPluginConfig,}

Step 4: Implement 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)}

Step 5: Add Service Hooks

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()}

Step 6: Register Plugin

At the bottom of your plugin file, register it with the router:

rust
register_plugin!("acme", "my_plugin", MyPlugin);

Step 7: Add Module to mod.rs

In src/plugins/mod.rs, add your module:

rust
pub mod my_plugin;

Step 8: Configure in YAML

Enable your plugin in the router configuration:

yaml
plugins:  acme.my_plugin:    enabled: true

Common Patterns

For implementation patterns and code examples, see references/service-hooks.md [blocked]:

  • 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 [blocked].

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/skills位于skills/apollo-router-plugin-creator提交c288eb8

许可证: MIT

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架