mcpField
A
apollo-router-plugin-creator

apollo-router-plugin-creator

github.com/apollographql開発1211.6k 回インストール1 日前に更新
リポジトリ

apollo-router-plugin-creator について

Apollo Router向けのネイティブRustプラグインを作成するためのスキルです。リクエストライフサイクルのフック選択と、変換、検証、トレース、レート制限、タイムアウトの組み合わせ方を説明します。

主な機能

  1. 01Routerのライフサイクルサービスフック
  2. 02リクエストとレスポンスの変換
  3. 03同期・非同期チェックポイント
  4. 04トレース、レート制限、タイムアウト
  5. 05プラグインの設定と登録

活用シーン

  1. 01HTTP層への認証追加
  2. 02計画前のGraphQLリクエスト検証
  3. 03クエリプランの実行制御
  4. 04サブグラフ呼び出しのヘッダー変更

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/apollo-router-plugin-creatorを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
examples.md
existing-plugins.md
service-hooks.md

詳細

Apollo Router プラグイン作成ツール

Apollo Router 用のネイティブな Rust プラグインを作成します。

リクエストのライフサイクル

┌────────┐             ┌────────────────┐                                   ┌────────────────────┐               ┌───────────────────┐       ┌─────────────────────┐
│ 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) │
└────────┘             └────────────────┘                                   └────────────────────┘               └───────────────────┘       └─────────────────────┘

サービスフック

サービスの概要
サービス説明
router_serviceHTTP リクエストのライフサイクルの開始直後と終了直前に実行されます。たとえば、JWT 認証は RouterService 内で行われます。カスタマイズで HTTP コンテキストやヘッダーを操作する必要がある場合は、router_service を定義します。body プロパティには対応していません。
supergraph_serviceGraphQL リクエストのライフサイクルの開始直後と終了直前に実行されます。カスタマイズで GraphQL リクエストまたは GraphQL レスポンスを操作する必要がある場合は、supergraph_service を定義します。たとえば、匿名クエリをチェックできます。
execution_serviceクエリプランの生成後、その実行開始を処理します。カスタマイズに実行を制御するロジック(たとえば、ポリシーの判断に基づいて特定のクエリをブロックする場合など)が含まれる場合は、execution_service を定義します。
subgraph_serviceRouter とサブグラフ間の通信を処理します。この通信を設定するには、subgraph_service を定義します(たとえば、サブグラフに渡す HTTP ヘッダーを動的に追加する場合など)。ほかのサービスはクライアントリクエストごとに 1 回呼び出されますが、このサービスはクライアントのリクエストを解決するために必要なサブグラフリクエストごとに 1 回呼び出されます。各呼び出しには、対応するサブグラフの名前を示すサブグラフパラメーターが渡されます。

シグネチャ:

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
個別のフック(Tower レイヤー)

ServiceBuilder を使って、これらのフックを任意のサービス内で組み合わせます。

フック目的同期/非同期
map_request(fn)処理を続行する前にリクエストを変換する同期
map_response(fn)返却前にレスポンスを変換する同期
checkpoint(fn)検証/フィルタリングを行い、短絡できる同期
checkpoint_async(fn)非同期検証を行い、短絡できる非同期
buffered()サービスの複製を有効にする(非同期処理に必要)-
instrument(span)サービスの周囲にトレーススパンを追加する-
rate_limit(num, period)リクエストのスループットを制御する-
timeout(duration)操作の制限時間を設定する-
サービスフックの選択

必要なデータ別:

  • 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 を参照してください。

クイックスタート

ステップ 1:プラグインファイルを作成する

必要なインポートを含む新しいファイル src/plugins/my_plugin.rs を作成します。

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";
ステップ 2:設定構造体を定義する

各プラグインには、Deserialize と JsonSchema の derive を指定した設定構造体が必要です。JsonSchema により、エディターで設定を検証できます。

#[derive(Debug, Clone, Default, Deserialize, JsonSchema)]
struct MyPluginConfig {
  /// Enable the plugin
  enabled: bool,
  // Add other configuration fields as needed
}
ステップ 3:プラグイン構造体を定義する
#[derive(Debug)]
struct MyPlugin {
  configuration: MyPluginConfig,
}
ステップ 4:プラグインのトレイトを実装する

必要な Config 型と new コンストラクターを指定して、Plugin トレイトを実装します。

#[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)
}
ステップ 5:サービスフックを追加する

要件に応じてフックするサービスを選択してください。詳しくはサービスの概要を参照してください。

サービスフックの例:

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()
}
ステップ 6:プラグインを登録する

プラグインファイルの末尾で、ルーターに登録します。

register_plugin!("acme", "my_plugin", MyPlugin);
ステップ 7:mod.rs にモジュールを追加する

src/plugins/mod.rs にモジュールを追加します。

pub mod my_plugin;
ステップ 8:YAML で設定する

ルーターの設定でプラグインを有効にします。

plugins:
  acme.my_plugin:
    enabled: true

よくあるパターン

実装パターンとコード例については、references/service-hooks.md を参照してください。

  • 有効化/無効化のパターン
  • リクエスト/レスポンスの変換(map_request、map_response)
  • チェックポイント(早期リターン/ショートサーキット)
  • フック間でのコンテキストの受け渡し
  • 非同期操作(checkpoint_async、buffered)
  • エラーレスポンスビルダー

例

Apollo Router の例

Apollo Router のプラグインディレクトリにあります。

プラグインサービスフックパターン説明
forbid_mutations.rsexecution_serviceチェックポイントクエリプランに対するシンプルなゲート
expose_query_plan.rsexecution + supergraphコンテキストの受け渡し複数サービス間の連携
cors.rsrouter_serviceHTTP レイヤーHTTP レベルでの CORS 処理
headers/subgraph_serviceレイヤーの構成複雑なヘッダー操作

コード例とテストパターンの全体については、references/examples.md を参照してください。

前提条件

ルータープラグインの開発時に慣用的な Rust コードを書くため、rust-best-practices スキルをインストールすることを推奨します。インストール済みの場合は、プラグインコードを生成または変更する際に、これらのベストプラクティスに従ってください。

リソース

コメント