Linux の curl コマンドから Canbus. API を呼び出す方法



Web データベースサービスの Canbus. に関する前回の記事で、Google Apps Script から Canbus. の REST API を呼び出す際の注意点について書きました。 

Canbus. の API は、Google Apps Script や Google スプレッドシート、その他の Web システム等のフロントエンドから Canbus. 内のデータを利用するために呼び出すことも可能ですが、社内の他の業務システムと連動させるために、バッチ処理やシェルスクリプト等から呼び出したいと思うこともあります。

今回は、Linux 上で一般的に利用可能なコマンドを使って Canbus. API を利用する例として、curl コマンドから Canbus. API を呼び出す方法について紹介します。


事例

Linux コマンドライン上から Web リクエストを送信する際に利用できるコマンドの 1 つに、curl があります。もちろん wget でも別によいのですが、今回は curl コマンドを使って Canbus. API を呼び出してみることにします。

サンプルとして、ここではレコード一覧 API を使います。

実務で発生した業務リクエストとして、Canbus. 上のとある業務アプリを運用する中で、「昨日作成されたレコードの数」を継続してモニタリングしたいことがありました。このような時、Canbus. API でレコードをすべて取得し、「作成日時」項目の値を調べて昨日作成された分をカウントしてももちろんよいのですが、レコード一覧画面のフィルター機能とレコード一覧 API を組み合わせれば、もっと簡単に実現できます。

  1. レコード一覧画面で、「作成日時 = 昨日」の条件でフィルターを作成する
  2. 作成したフィルターの ID を調べる
  3. フィルター ID を指定してレコード一覧 API を呼び出す
  4. API レスポンスに含まれるレコード件数を調べる

このような流れになります。


フィルターの作成

最初に、今回の API 呼び出しで使用するフィルターを作成します。Canbus. のレコード一覧画面でフィルターを作成しておくと、そのフィルターを指定してレコード一覧 API を呼び出すことで、条件に一致するレコードだけを取得することができます。

レコード一覧画面のプルダウンから、[フィルターの新規作成] を選択します。


レコード一覧画面の右側にフィルター編集パネルが開くので、適当なフィルター名を入力し、フィルター条件として [作成日時], [= (等しい)], [昨日] を選び、[保存] ボタンをクリックします。


ここでは「昨日作成されたレコード」という名前でフィルターを作成しました。


フィルター ID の取得

レコード一覧 API でフィルターを指定するには、フィルターの ID を知る必要があります。ところが、この取得方法が少々トリッキーです。Canbus. ヘルプセンターのドキュメントにも説明があるのですが、Canbus. の画面上からはフィルター ID を知る術がありません。どうすればよいかというと、レコード一覧画面の HTML ソースを見たり、Chrome 開発者ツールを使って調べる必要があります。

HTML ソースから調べる場合、レコード一覧画面で「昨日作成されたレコード」フィルターを選んだ後、ブラウザの機能でページソースを表示します。表示されたソースの中を検索して、window.GLOBAL.FILTER_ID という変数が書かれている行を探します。


見つけるのは、window.GLOBAL.FILTER_ID の右辺に書かれている英数 24 文字のテキストです。上記スクリーンショットのケースでは、77a3db8d371a47efa1d9e2a1 がフィルター ID になります。

なお、すぐ上の行に window.GLOBAL.APP という行があり、ここにも 24 文字の ID がありますが、探す値はこれとは違うので注意してください。また、フィルター ID が 000000000000000000000000 になっている場合は、レコード一覧画面で「すべてのレコード」フィルターが選ばれています。必ず、ID を確認したいフィルターを選択してから HTML ソースを表示する必要があります。

Chrome 開発者ツールを使ってフィルター ID を調べる場合は、開発者ツールの Console タブに直接、window.GLOBAL.FILTER_ID と入力して [Enter] キーを押します。

> window.GLOBAL.FILTER_ID
'77a3db8d371a47efa1d9e2a1'

注意点としては、この方法でフィルター ID を調べる場合、レコード一覧画面で対象のフィルターを選択した後に一度、[F5] キー等で画面を再読み込みしてから実行する必要があります。この JavaScript 変数は、「ページがロードされたときに最初に選択されていたフィルター ID」を保持しているようです。


レコード一覧 API を curl コマンドから呼び出す

レコード一覧画面でフィルターを作り、作成したフィルターの ID も取得できたので、実際にレコード一覧 API を呼び出してみます。

今回のケースでは、Canbus. API のリクエスト時に渡したいペイロード(リクエストボディ)は次のようになります。アプリ ID や API キーなどは架空の値にしてあります。

{
    "tenant_id": "<tenant-id>",
    "app_id": "f898b8bca13041b2b860f471",
    "api_key": "e1Pwg9EgbobAhoze",
    "api_secret": "5N4cOMC5z08T49Y36yTLRpU4xhyyta3H",
    "record_list": {
        "filter": "77a3db8d371a47efa1d9e2a1",
        "number": 0
    }
}

record_list オブジェクトの filter の値として先ほど取得したフィルター ID を指定することで、このフィルターに含まれるレコードの一覧を取得できます。number については後で触れます。

curl コマンドでこのペイロードを送信するには、Linux コマンドラインから以下のように実行します。

$ curl https://<tenant-id>.canbus.com/api/records -H 'Content-Type: application/json' -X GET -d '{
>     "tenant_id": "<tenant-id>",
>     "app_id": "f898b8bca13041b2b860f471",
>     "api_key": "e1Pwg9EgbobAhoze",
>     "api_secret": "5N4cOMC5z08T49Y36yTLRpU4xhyyta3H",
>     "record_list": {
>       "filter": "77a3db8d371a47efa1d9e2a1",
>       "number": 0
>     }
> }'

または、JSON の改行をすべて除去して、次のように実行することもできます。

$ curl https://<tenant-id>.canbus.com/api/records -H 'Content-Type: application/json' -X GET -d '{"tenant_id": "<tenant-id>", "app_id": "f898b8bca13041b2b860f471","api_key": "e1Pwg9EgbobAhoze","api_secret": "5N4cOMC5z08T49Y36yTLRpU4xhyyta3H","record_list": {"number": 0,"filter": "77a3db8d371a47efa1d9e2a1"}}'

どちらの書き方でも、curl コマンドの実行時にポイントになるのは以下の 3 つです。

  • -H オプションで Content-Type: application/json ヘッダーを送る
  • -d または --data オプションでペイロードを送る
  • -X オプションで各 Canbus. API の使用するリクエストメソッドを指定する

Content-Type ヘッダーの送信は Canbus. API の仕様で必須です。送信しない場合、curl は指定されたペイロードを Content-Type: application/x-www-form-urlencoded として送るので、Canbus. 側でペイロードの認証情報が正しく解釈されず、401 Unauthorized エラーレスポンスが返されます。

ペイロードの指定は -d オプションで行えますが、JSON 文字列が空白文字を含むため、全体をクォーテーションで括る必要があります。JSON 文字列自体がダブルクォーテーションを多用するため、ここではシングルクォーテーションで括りました。JSON 内にシングルクォーテーションが登場したり、curl のオプション引数を指定する際にダブルクォーテーションしか使えない環境(他の開発環境に curl 機能が組み込まれているようなケースで遭遇します)では、JSON 内のクォーテーションを \" や \' のようにすべてエスケープする必要があります。

リクエストメソッドについては、curl で -d オプションを使用するとデフォルトで POST メソッドが使用されるため、あらためて各 API ごとの適切なリクエストメソッドを指定する必要があります。今回のレコード一覧 API は GET を使用するため、-X GET と指定します。


レスポンス JSON の解析

レコード一覧 API を実行すると、次のようにレスポンスが返ってきます。

{"authen":"OK","results":[{"result":"0","count":52,"length":1,"records":[{ ... }]}]}

上記の "..." で省略した部分には、フィルター条件に該当するレコードの実際のデータが格納されています。

今回は「昨日作成されたレコード」の件数を調べることが目的なので、実際のレコードデータを取得する必要はありません。このような場合、レコード一覧 API のリクエストで record_list オブジェクトの number を指定すると、取得する最大レコード数を限定できます。実際には 0 を指定しても最低 1 件のレコードは取得される動きになるようですが、API 呼び出しパフォーマンスの観点からも、レコードの中身が必要ない場合には number: 0 か number: 1 を指定しておく方がよいといえます。

そして、レスポンスに含まれる count: 52 の部分が、このフィルターに該当したレコードが全部で 52 件あったことを表しています。

前述のように、レコード一覧 API では取得するレコード数を number で限定できます。それ以上にレコードが存在する場合は、複数回のレコード一覧 API 呼び出しを分割して行うページング処理が必要になるのですが、その場合でもレスポンスの count には常にトータルのレコード件数(総数)が格納されています。

このため、「昨日作成されたレコード」フィルターに該当するレコード総数を知りたい場合は、シンプルにレコード一覧 API のレスポンスに含まれる count の値を調べればよいということになります。今回は、52 レコードだったようです。

Linux コマンドラインで JSON 文字列の解析をするには、jq コマンドを利用できます。

$ sudo yum install jq
...

$ which jq
/usr/bin/jq

レコード一覧 API のレスポンスからレコード件数の count 部分を取り出すには、次のように実行します。

$ count=`curl -s https://<tenant-id>.canbus.com/api/records -H 'Content-Type: application/json' -X GET -d '{
>     "tenant_id": "<tenant-id>",
>     "app_id": "f898b8bca13041b2b860f471",
>     "api_key": "e1Pwg9EgbobAhoze",
>     "api_secret": "5N4cOMC5z08T49Y36yTLRpU4xhyyta3H",
>     "record_list": {
>       "number": 0,
>       "filter": "77a3db8d371a47efa1d9e2a1"
>     }
> }' | jq .results[0].count`

ネットワーク通信の進捗状況が出力されるのを抑制するため、curl に -s オプションを追加しています。

JSON を解析するため、curl によって出力される API 呼び出しのレスポンスをパイプを使って jq コマンドに渡します。jq は、引数で指定した .results[0].count によってトップレベルのオブジェクトの中にある results 配列の先頭要素の count プロパティの値を取り出します。全体をバッククォートで囲むことで、取り出した値をシェル変数 count に格納しています。

これで、あとはシェルスクリプトの中で「昨日作成されたレコードの数」を自由に使うことができます。

$ echo $count
52


まとめ

Web API を使って Canbus. 内のデータにアクセスすることで、レコード作成状況の推移など、利用状況の把握を利用者側でも独自に行うことができます。既存の業務ロジックが Linux 上にあるようなケースでは、curl を使って Canbus. API を呼び出すことで、比較的容易に Canbus. のデータを既存の仕組みに統合することができるといえます。

curl を使う際は、API 呼び出し時に以下の 3 点に注意します。

  • -H オプションで Content-Type: application/json ヘッダーを送ります。
  • -d または --data オプションでペイロードを送ります。
  • -X オプションで各 Canbus. API の使用するリクエストメソッドを指定します。

この記事では触れませんでしたが、curl からの API 呼び出しでエラーが発生し、うまくいかない時には、curl -v オプションで詳細なログ出力をすることで、原因を確認できます。もう少し知見が溜まれば、トラブルシューティングなどの情報もまとめてみたいと思います。