GraphQL では、Query と Mutation はスキーマ上でははっきり分かれていますが、
「実行時にどちらが呼ばれたのか?」を判別したいケースがあります。
たとえば以下のようなケースが考えられます:
Apollo Server の plugin 内で、リクエストが Query か Mutation かを判定したい
Logging / Tracing / Metrics 用に操作の種類を知りたい
Query だけ rate limit を変えたい、Mutation だけアクセス制御したい など
しかし、GraphQL の実行時コンテキスト(GraphQLResolveInfo など)には
「これは Query/Muation です」と直接分かるプロパティがありません。
解決策:info.operation.operation を使う
GraphQL のリゾルバは、第四引数として GraphQLResolveInfo(info)を受け取ります。
resolve(parent, args, context, info) {
console.log(info.operation.operation);
}
ここで info.operation.operation には以下の値が入っています:
操作種別 取得できる値
Query "query"
Mutation "mutation"
Subscription "subscription"
つまり、実行時に これだけでリクエストの種別を判定できるということです。
Apollo Server Plugin での実用例
GraphQL では、
Query は Query 型のフィールド
Mutation は Mutation 型のフィールド
としてスキーマ上に定義されます。
Apollo Server の plugin で実際に判定するには、requestDidStart フックを使います。
const plugin = {
async requestDidStart() {
return {
async executionDidStart(requestContext) {
const op = requestContext.operation?.operation;
console.log("Operation type: ", op);
},
};
}
};
ここでも operation.operation を参照するだけで Query/Muation を区別できます。
注意点
GraphQL の クライアントが operation name を省略していても判別可能
Schema の Query / Mutation のフィールドレベルでは区別できない
→ operation(=リクエスト)単位での判定のみ可能
operation はパース直後の AST (OperationDefinitionNode) に基づくため、極めて確実
まとめ
StackOverflow の回答のポイントは以下です:
GraphQL はリクエスト (operation) に対して query / mutation / subscription の情報を保持している
その情報は info.operation.operation または requestContext.operation.operation で取得できる
よって、実行時でも Query と Mutation を安全に区別できる
GraphQL のミドルウェア、ログ、権限管理などで役立つテクニックです。