GraphQL ASTから実行まで:parse・validation・resolver
parse後の実行順序を追い、HTTP transport、認可、DataLoaderの範囲を区別します。
発行・訂正窓口:infostoa · 編集基準
この記事の個別の執筆者・専門査読者の情報は提供されていません。
GraphQL requestは未検査の文字列をそのまま実行するものではありません。serverはdocumentをtokenとabstract syntax tree(AST)へparseし、schemaに照らしてvalidationし、選択されたoperationを実行します。GraphQL Specificationは言語と実行規則を、別のGraphQL over HTTP作業draftはHTTP transportを説明します。
ASTはdocumentの構造を表す
query { user(id: "7") { name posts { title } } }では、field、argument、入れ子のselectionが構造化されたnodeになります。parse後のvalidationでuserがschemaに存在するか、argument typeが適切か、object fieldに必要なsubfieldが選ばれているかを確認できます。parseできたことは実行可能である証明ではありません。ASTが自動的にdatabase queryや最適化済みexecution planになるわけでもなく、resolverの呼び出し方はserver実装によります。
validation後にresolverが動く
serverはoperationを選び、variable値を処理し、各fieldのresolverを呼んでresponseを組み立てます。GraphQL specはqueryの最上位selectionを並行化できます。一方mutationの最上位fieldは副作用の順序を保つため直列実行すべきとされています。これは同じmutation文書内の順序であり、別clientからのrequest全体を直列化する規則ではありません。
userとpostsを取り、その各postのauthorも読むと、同じ種類のbackend lookupが繰り返されることがあります。DataLoaderのbatch functionなら一回の実行区間で要求された複数keyをまとめて取得できます。返すarrayの位置が元のkey順に対応することも必要です。これはdata access層の最適化で、GraphQL必須機能ではありません。
POST専用ではなくGETもあり得る
GraphQL言語仕様はHTTPをtransportとして必須にしません。現在のGraphQL over HTTP working draftではserverはPOSTをサポートし、GETなどもサポートできます。GETではparameterをURL queryにencodeしますが、mutationの実行には使えません。URL長の制限やvariableがURL・logに残る可能性も考慮します。利用するAPIのtransport仕様を確認してください。
typeやintrospectionは認可ではない
schema typeはdataの形や入力制約を表しますが、利用者が特定recordやfieldを見てよいかは自動判定しません。認証済みprincipalと対象resourceの関係をresolverまたはservice層で認可します。Apollo GraphOS Routerのauthorization directiveはその製品の機能例であり、GraphQL言語共通のdirectiveではありません。
introspectionはschema構造を調べる標準機能です。productionで無効にする構成もありますが、すべてのserverで必ず無効化するというspec規則はありません。GraphQLの公式guideは、introspection制限をauthentication・authorization、operation safelist、depth・breadth制限、cost controlなど広い対策の一部として扱います。公開・非公開だけでAPI安全性を判断しないでください。
実行コストとcache範囲を管理する
深いselectionやalias、繰り返す関連fieldはresolver負荷を増やします。実際のschemaでdepth、alias数、complexity、timeoutを計測して制限を決めます。userごとのdataをmemoizeするDataLoaderはrequestごとに作ってcontextへ渡します。project READMEは、見えるdataが異なるuser間でloader instanceを共有しないよう案内しています。これはDataLoaderの使い方であり、GraphQL自体が保証する安全機能ではありません。