#97 GraphQL
先日OSCPを取得して、完全に満足しちゃっていましたが、OSCP受講のおまけでついてきた無線通信のコース(OSWP)も、せっかくなのでやってみました。
昨日受験して、先ほど、合格通知がきました!内容はそれほど難しくなく、教材の内容を理解していれば簡単に解ける問題でしたが、OSCP同様、監視されながらの試験だったので緊張しました。
さて、流行りかわかりませんが、GraphQLに触れる機会が増えてきました。FacebookのAPIで使われているので存在は知っていましたが、開発側の立場で扱うチャンスはそれほどありません。
というわけで、Hello Worldまでやってみます。Expressでリクエストを受け取って、GraphQLにクエリを流し、結果をレスポンスとして返すような形にしたいと思います。
作業
ソースはGitHubで公開していますので、ご活用ください。
環境構築
GitHubからソースコードをクローンしたら、Dockerコンテナを立ち上げます。
docker compose up -d --build
http://localhost:3000にアクセスして、”Hello World!”と表示されればOKです。
GraphQL
GraphQL.jsを使用します。
app.jsの実装は以下の通りです。
var { graphql, buildSchema } = require("graphql")
const express = require('express')
const app = express()
const port = 3000
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
var schema = buildSchema(`
type Query {
hello: String
}
`)
var rootValue = { hello: () => "Hello GraphQL!" }
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.post('/graphql', async (req, res) => {
var source = req.body.query;
var result = await graphql({ schema, source, rootValue });
res.send(result);
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
/graphqlにPOSTでクエリを送ると、GraphQLから結果が返されます。curlで送信してみます。
$ curl -X POST http://localhost:3000/graphql -H "Content-type: application/json" -d '{"query": "{ hello }"}'
{"data":{"hello":"Hello GraphQL!"}}
期待通りです!
ちなみに、GraphQLには、Introspectionという機能があって、以下のようなクエリでスキーマの情報を取得することができます。
{__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}
そのままでは読みにくいですが、スキーマの定義が返ってきます。
{"data":{"__schema":{"types":[{"name":"Query","fields":[{"name":"hello","args":[]}]},{"name":"String","fields":null},{"name":"Boolean","fields":null},{"name":"__Schema","fields":[{"name":"description","args":[]},{"name":"types","args":[]},{"name":"queryType","args":[]},{"name":"mutationType","args":[]},{"name":"subscriptionType","args":[]},{"name":"directives","args":[]}]},{"name":"__Type","fields":[{"name":"kind","args":[]},{"name":"name","args":[]},{"name":"description","args":[]},{"name":"specifiedByURL","args":[]},{"name":"fields","args":[{"name":"includeDeprecated","description":null,"type":{"name":"Boolean","kind":"SCALAR","ofType":null}}]},{"name":"interfaces","args":[]},{"name":"possibleTypes","args":[]},{"name":"enumValues","args":[{"name":"includeDeprecated","description":null,"type":{"name":"Boolean","kind":"SCALAR","ofType":null}}]},{"name":"inputFields","args":[{"name":"includeDeprecated","description":null,"type":{"name":"Boolean","kind":"SCALAR","ofType":null}}]},{"name":"ofType","args":[]}]},{"name":"__TypeKind","fields":null},{"name":"__Field","fields":[{"name":"name","args":[]},{"name":"description","args":[]},{"name":"args","args":[{"name":"includeDeprecated","description":null,"type":{"name":"Boolean","kind":"SCALAR","ofType":null}}]},{"name":"type","args":[]},{"name":"isDeprecated","args":[]},{"name":"deprecationReason","args":[]}]},{"name":"__InputValue","fields":[{"name":"name","args":[]},{"name":"description","args":[]},{"name":"type","args":[]},{"name":"defaultValue","args":[]},{"name":"isDeprecated","args":[]},{"name":"deprecationReason","args":[]}]},{"name":"__EnumValue","fields":[{"name":"name","args":[]},{"name":"description","args":[]},{"name":"isDeprecated","args":[]},{"name":"deprecationReason","args":[]}]},{"name":"__Directive","fields":[{"name":"name","args":[]},{"name":"description","args":[]},{"name":"isRepeatable","args":[]},{"name":"locations","args":[]},{"name":"args","args":[{"name":"includeDeprecated","description":null,"type":{"name":"Boolean","kind":"SCALAR","ofType":null}}]}]},{"name":"__DirectiveLocation","fields":null}]}}}
開発者にはありがたい一方、余計な情報まで公開してしまいそうで怖いです。今回使用しているGraphQL.jsには標準ではIntrospectionを無効にする機能はないようで、別途パッケージをインストールする必要があるみたいです。
まとめ
GraphQLクエリを実行するところまでは結構あっさりできました。ただ、実運用するには、スキーマの定義やデータベースとのつなぎ合わせなどが必要です。データベースにはNeo4jのようなグラフDBを使うのが筋なのでしょうか?Postgresで構築する記事なども発見しました。
まだまだ奥が深そうです…
EOF
この記事が気に入ったらサポートをしてみませんか?