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 從公開儲存庫中收錄這些內容。

檢舉或申請下架