2024年2月25日日曜日

graphqlの動作確認をcurlで実施


背景

graphqlとはサーバーのAPIの記述方式の1つです。
動作確認時のコマンドを組み立てるのがなかなか手間だったので、備忘録として内容を記事に残します。

紹介するコマンドは下記のログ取りサーバーの動作確認のために作りました。
clj-server-practice

作ったコマンド全体

コマンドの全体はこちらです。
ubuntu22.04のbashで動作を確認しました。
AUTH_BEARER="XXYYZZ"
HOST=http://localhost:3000

function escape_str () {
echo "$1" | sed 's/\\/\\\\/g' | sed 's/\"/\\"/g'
}

WHERE="[{\"key\": [\"data\", \"camera_id\"], \"action\": \"not_null\"}]"
ESCAPED_WHERE=$(escape_str "$WHERE")
ORDER="[{\"key\": \"created_at\", \"dir\": \"desc\"}]"
ESCAPED_ORDER=$(escape_str "$ORDER")
QUERY="{ raw_device_logs(where: \"$ESCAPED_WHERE\", order: \"$ESCAPED_ORDER\") { total } } }"
ESCAPED_QUERY=$(escape_str "$QUERY")
JSON="{\"query\": \"$ESCAPED_QUERY\"}"

RECEIVED_JSON=$(curl -X POST ${HOST}/graphql \
-H "Authorization: Bearer $AUTH_BEARER" \
-H "Content-Type: application/json" \
-d "$JSON")
echo $RECEIVED_JSON

要所を解説します。

graphQLのリクエストはjsonのqueryキーに必要な情報を記述してpostする

jsonのqueryキーにgraphqlのquery(取得したい情報)の文字列を渡します。
HOST=http://localhost:3000
curl -X POST ${HOST}/graphql \
-H "Content-Type: application/json" \
-d "{\"query\": \"{ raw_device_logs { total } }\"}"

文字列なので、query内部で文字列を扱う場合はダブルクオートやバックスペースなどのエスケープ(文字列の中で表示する文字列の形式に変換)が必要です。
HOST=http://localhost:3000
curl -X POST ${HOST}/graphql \
-H "Content-Type: application/json" \
-d "{\"query\": \"{ raw_device_logs(where: \\\"[{\\\\\\\"key\\\\\\\": [\\\\\\\"data\\\\\\\", \\\\\\\"camera_id\\\\\\\"], \\\\\\\"action\\\\\\\": \\\\\\\"not_null\\\\\\\"}]\\\", order: \\\"[{\\\\\\\"key\\\\\\\": \\\\\\\"created_at\\\\\\\", \\\\\\\"dir\\\\\\\": \\\\\\\"desc\\\\\\\"}]\\\") { total } } }\"}"

上記のような3階層以上の文字列エスケープは手動入力が困難なほど「\」が多いです。

bashでの文字列エスケープは関数を作って使うのが便利

echoとsedコマンドを組み合わせて文字列エスケープを行う関数を作り、必要な箇所で呼びました。
(bashのShell Parameter Expansion( ${STR//a/b} で aをbに変えられる表現)も試しましたが、2回連続で処理する記述方法は無さそうだったので、今回はecho1回とsed2回で関数を組みました。)

function escape_str () {
echo "$1" | sed 's/\\/\\\\/g' | sed 's/\"/\\"/g'
}

これを使うことで、「\」の数の把握が困難な階層のエスケープも手動入力に比べて楽に作れます。
WHERE="[{\"key\": [\"data\", \"camera_id\"], \"action\": \"not_null\"}]"
ESCAPED_WHERE=$(escape_str "$WHERE")
ORDER="[{\"key\": \"created_at\", \"dir\": \"desc\"}]"
ESCAPED_ORDER=$(escape_str "$ORDER")
QUERY="{ raw_device_logs(where: \"$ESCAPED_WHERE\", order: \"$ESCAPED_ORDER\") { total } } }"
ESCAPED_QUERY=$(escape_str "$QUERY")
JSON="{\"query\": \"$ESCAPED_QUERY\"}"
echo $JSON
{"query": "{ raw_device_logs(where: \"[{\\\"key\\\": [\\\"data\\\", \\\"camera_id\\\"], \\\"action\\\": \\\"not_null\\\"}]\", order: \"[{\\\"key\\\": \\\"created_at\\\", \\\"dir\\\": \\\"desc\\\"}]\") { total } } }"}

更に良い書き方や便利コマンドがあれば、コメントなどで教えていただけると嬉しいです。

必要に応じてヘッダに認証情報を追加

curlコマンドなので、一般的なAPIのpostと同様に必要があれば認証情報を付与できます。
AUTH_BEARER="XXYYZZ"
curl -X POST ${HOST}/graphql \
-H "Authorization: Bearer $AUTH_BEARER" \
-H "Content-Type: application/json" \
-d "$JSON"

おわり

graphql動作確認用のcurlコマンドを作って動かせました。
エスケープの「\」が多かったの人力でのコマンドを組み立ては早々諦めてbash芸に集中しました。
この記事の情報がコマンドでgraphqlの動作確認をcurlで行いたい人(将来の自分も含む)の助けになれば嬉しいです。

参考

公式のREADMEです。
GraphQLでの呼び出しの作成

今回は使わなくなりましたが、bashの変数の文字列を置き換える表現の関連情報です。
echo | sedなんていらなかったんだ!
Replace one substring for another string in shell script
Shell Parameter Expansion

bashの関数で変数を扱うには$1や$2を使えば良いと把握したフォーラムです。
Passing parameters to a Bash function

0 件のコメント :