見出し画像

hund.ioのAPIを触ってみる (Roy FieldingのREST実装例)

先日Roy FieldingのRESTは我々のよく知るRESTとは違うんだよという記事を書きました。

もっと具体的に実装例を触って、大きく違うところを実際に見てみましょう。

トライアル環境をもらえるようなのでまずはもらいましょう。上記ページからトライアル環境をもらえます。

APIドキュメントはこちら。今回は具体的にRoy FieldingのRESTらしさを観察するためだけにここに書きますので、hund.ioのAPIの仕様の確認は直接ドキュメントを参照してください。

APIキーをもらおう

APIのドキュメントによるとAPIキー認証のようです。
APIキーはトライアル環境の画面上から、左のナビゲーションのUsers > 初期登録したユーザーを選択 > 画面右上 Manage API Keys ボタン > New API Keyボタンで生成できます。

初期URLにリクエストを投げてみよう

Roy FieldingのRESTは「初期URLにリクエストを投げることで使い方がわかる」というのがメリットです。
普通のWebページでいうところの index.html にあたる初期URLが決まっており、そこを叩けば何ができるかがわかるという仕組みになっているはず。

Hund.ioのAPIドキュメントではBase URLのところに

https://{domain}/api/v1

が初期URLとして定義されており、

Accessing the API through any of these domains will only show objects accessible from that domain

(APIを使ってこれらのドメインにアクセスすることで、そのドメインではどのようなオブジェクトにアクセスできるかだけがわかるようになっています。)
https://hund.io/help/api#section/Base-URL

と書いてありますので早速リクエストを送ってみましょう。

  • HTTPメソッド: GET

  • URL: https://<自分の環境のドメイン>/api/v1/

  • Authorizationヘッダー: Basic認証、中身はAPIキーのみ

Authorizationヘッダーの値の生成方法はこちらに書いてあります。

面倒なので私はAPIのテストツールをよく使っています。ヘッダーの入力テンプレートに従って必要情報を入れれば良いのでラク。

結果。

{
   "_links":{
      "self":{"href":"https://<自分の環境のドメイン>/api/v1"},
      "components":{"href":"https://<自分の環境のドメイン>/api/v1/components"},
      "groups":{"href":"https://<自分の環境のドメイン>/api/v1/groups"},
      "metric_providers":{"href":"https://<自分の環境のドメイン>/api/v1/metric_providers"},
      "issues":{"href":"https://<自分の環境のドメイン>/api/v1/issues"}
   }
}

みていただけるとわかる通り、HALのフォーマットに従ってオブジェクトの一覧と、該当オブジェクトが欲しい場合のURLが送られてきました。

ヘッダーにはHALであることが記述されています。

content-type: application/hal+json; variant=links-only; charset=utf-8

VariantでLinks-onlyという値が指定されています。ほかにStandardとかCompactとかがあるようですが、初期URLではリンク以外がないようで必ずlinks-onlyが返信されました。

Componentオブジェクトにリクエストを投げてみよう

今度は /components にリクエストを送ってみます。適当に登録してみました。

{
   "type":"paged_array",
   "total_count":1,
   "data":[{
      "id":"62ba780ca877244a595b0cc5",
      "type":"component",
      "created_at":1656387596,
      "updated_at":1656387646,
      "name":"Test Component",
      "description":"This is a Test Component",
      "description_html":"\u003cp\u003eThis is a Test Component\u003c/p\u003e\n",
      "exclude_from_global_history":false,
      "exclude_from_global_uptime":false,
      "last_event_at":1656387646,
      "group":"62ba77d6a877244a57b58948",
      "watchdog":"62ba780ca877244a595b0cc1",
      "percent_uptime":100.0}
      ],
   "has_more":false,
   "_embedded":{
      "data":[{
         "_links":{
            "self":{"href":"https://<自分の環境のドメイン>/api/v1/components/62ba780ca877244a595b0cc5"},
            "self-view":{"href":"https://<自分の環境のドメイン>/components/62ba780ca877244a595b0cc5"},
            "update-form":{"href":"https://<自分の環境のドメイン>/dashboard/components/62ba780ca877244a595b0cc5/edit"},
            "watchdog":{"href":"https://<自分の環境のドメイン>/api/v1/watchdogs/62ba780ca877244a595b0cc1"}
          }
       }]
   },
   "_links":{
      "self":{"href":"https://<自分の環境のドメイン>/api/v1/components?limit=10"},
      "create-form":{"href":"https://<自分の環境のドメイン>/dashboard/components/new"},
      "prev":{"href":"https://<自分の環境のドメイン>/api/v1/components?ending_before=62ba780ca877244a595b0cc5\u0026limit=10"},
      "beginning":{"href":"https://<自分の環境のドメイン>/api/v1/components?limit=10"}
   }
}

_links が2箇所あります。
_embedded 以下のリンクのところに、表示されたレコードに関連するURLが書いてあります。例えばupdate-formはこのレコードを編集する場合のURLですが、ブラウザで開く場合のURLのようです。

_embedded と同じ階層に位置する _links には、このリストに関連するURLが含まれています。例えばこのリストのURL、新しいレコードを登録する場合のURLや1ページ前を参照したい場合のURLなど。
リスト表示にした時の目的のページをみつけやすくするようなメタデータはGitHubではヘッダーに格納されていました。

単一レコードを参照する /components/{id} でも同じ内容が返ってきました。
せっかくですからリンク先のオブジェクトであるgroupとかが_embeddedに入っていると面白いんだけど。

メタデータのメリットと設計の基本的な考え方

みていただけるとわかる通り、メタデータを含めるとデータ量が多くなります。
なぜわざわざメタデータを含めるんでしょうか。特にリンクは画面上に描画する要素としては不要ですよね。

これはそもそもRoy FieldingがブラウザとHTMLでできたWebページのように、メディアタイプ (content-type) がわかれば、このメディアタイプを解釈するだけでアプリケーションができるように作りたかったからだと言われています。

よく考えればRoy FieldingはそもそもHTTPの設計に携わった方です。そこを考えるとむしろその意見はとても自然に見えます。

Roy Fieldingのブログの我々のよく知るRESTへの反論の記事に記載されている通り

A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state

(REST APIではリソースやアプリケーションステートを変遷させるためのメディアタイプを定義することにほとんどの時間を費やすべきだ)
https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

つまりメディアタイプがしっかりしていればしているほど、APIの設計は大きくしなくてもすみます。
HTML言語を解釈してレンダリングするブラウザのようにAPIのメディアタイプを作り込み、サーバー側クライアント側双方がそれに準拠したデータをやり取りすれば、メディアタイプの設計に反した内容を記述しない限りアプリケーションは壊れませんし、どんなAPIの変更も許容できます。

とはいえそれは人の目でクライアントの画面を見て何かをするケースであって、APIの本領であるマシン-マシン間のインタラクションでは難しいような気はします。

こういったRoy FieldingのRESTのAPIを設計する場合は、オブジェクトにどんな名前をつけてURLとするかではなく、WebページのサイトマップやWebページのページ間のつながりを設計するような感覚でAPIを作るものだということを迷路の設計に例えて解説されているのが以下の本です。

以下の図が時々引用されたりします。Entranceが初期URLに当たります。リンクをたどって目的を達成 (Exit) させるにはどう迷路をたどらせたらいいかを考えるんですね。

『RESTful Web APIs』より、Figure 5-3. The example maze as a network of cells 

余談ですがたどることを前提とした作りになっていないRoy Fieldingを意識したREST APIを見ると、Roy FieldingのREST派の方が「リンクを入れればいいってもんじゃないんだ」とおっしゃいますのでいろいろ思うところがあるようです。


この記事が気に入ったらサポートをしてみませんか?