apollo-router-plugin-creator について
Apollo Router向けのネイティブRustプラグインを作成するためのスキルです。リクエストライフサイクルのフック選択と、変換、検証、トレース、レート制限、タイムアウトの組み合わせ方を説明します。
主な機能
- 01Routerのライフサイクルサービスフック
- 02リクエストとレスポンスの変換
- 03同期・非同期チェックポイント
- 04トレース、レート制限、タイムアウト
- 05プラグインの設定と登録
活用シーン
- 01HTTP層への認証追加
- 02計画前のGraphQLリクエスト検証
- 03クエリプランの実行制御
- 04サブグラフ呼び出しのヘッダー変更
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ apollographql/ skills --skill apollo-router-plugin-creatorインストール後、Claude Code で/apollo-router-plugin-creatorを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/examples.mdexisting-plugins.mdservice-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_service | HTTP リクエストのライフサイクルの開始直後と終了直前に実行されます。たとえば、JWT 認証は RouterService 内で行われます。カスタマイズで HTTP コンテキストやヘッダーを操作する必要がある場合は、router_service を定義します。body プロパティには対応していません。 |
supergraph_service | GraphQL リクエストのライフサイクルの開始直後と終了直前に実行されます。カスタマイズで GraphQL リクエストまたは GraphQL レスポンスを操作する必要がある場合は、supergraph_service を定義します。たとえば、匿名クエリをチェックできます。 |
execution_service | クエリプランの生成後、その実行開始を処理します。カスタマイズに実行を制御するロジック(たとえば、ポリシーの判断に基づいて特定のクエリをブロックする場合など)が含まれる場合は、execution_service を定義します。 |
subgraph_service | Router とサブグラフ間の通信を処理します。この通信を設定するには、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.rs | execution_service | チェックポイント | クエリプランに対するシンプルなゲート |
expose_query_plan.rs | execution + supergraph | コンテキストの受け渡し | 複数サービス間の連携 |
cors.rs | router_service | HTTP レイヤー | HTTP レベルでの CORS 処理 |
headers/ | subgraph_service | レイヤーの構成 | 複雑なヘッダー操作 |
コード例とテストパターンの全体については、references/examples.md を参照してください。
前提条件
ルータープラグインの開発時に慣用的な Rust コードを書くため、rust-best-practices スキルをインストールすることを推奨します。インストール済みの場合は、プラグインコードを生成または変更する際に、これらのベストプラクティスに従ってください。
リソース
- references/service-hooks.md - サービスフックの詳細な実装
- references/existing-plugins.md - 既存プラグインの一覧
- references/examples.md - コード例とテストパターンの全体
- Apollo Router のプラグイン:https://github.com/apollographql/router/tree/dev/apollo-router/src/plugins