はとのーと

エジソンノート(アイデア、思い付き、メモ)として使っています。誰かの役に立つかもしれないので公開しています。

Web APIをRESTfulにするためのメモ

WebAPIについての自分用のメモです。 「これが良さそう」というような自分の方針などをまとめています。

目次:

このノート全体の参考になるページ

  1. 翻訳: WebAPI 設計のベストプラクティス - Qiita
  2. 身の丈にあったWebAPI設計ガイドラインを作った話 - Qiita
  3. RESTful APIのURI設計(エンドポイント設計) - Qiita

URLはRESTful、エンドポイントは複数形にする

(参考ページ1より)

例:

  • GET /tickets - チケットのリストを取得する
  • GET /tickets/12 - チケット #12 の情報を取得する
  • POST /tickets - 新しいチケットを作成する
  • PUT /tickets/12 - チケット #12 を更新する
  • PATCH /tickets/12 - チケット #12 を部分的に更新する
  • DELETE /tickets/12 - チケット #12 を削除する

関連データーが特定のリソースに付随してのみ存在するのであればリソースURLの下に入れてもよい。

関連データーの例:

  • GET /tickets/12/messages - チケット #12 に紐づくメッセージのリストを取得する
  • GET /tickets/12/messages/5 - チケット #12 に紐づくメッセージ #5 を取得する
  • POST /tickets/12/messages - チケット #12 に新しいメッセージを作成する
  • PUT /tickets/12/messages/5 - チケット #12 のメッセージ #5 を更新する
  • PATCH /tickets/12/messages/5 - チケット #12 のメッセージ #5 を部分的に更新する
  • DELETE /tickets/12/messages/5 - チケット #12 のメッセージ #5 を削除する

サブリソースはリンクのみ提示する

rest - How to handle many-to-many relationships in a RESTful API? - Stack Overflow

サブリソースはJSONに内容を埋め込まず、リンクを返す。

例: スポーツのチームと所属プレイヤーを表す情報

/api/team/0:

{
    name: 'Boston Celtics',
    logo: '/img/Celtics.png',
    players: [
        '/api/player/20',
        '/api/player/5',
        '/api/player/34'
    ]
}

/api/player/20:

{
    pk: 20,
    name: 'Ray Allen',
    birth: '1975-07-20T02:00:00Z',
    team: '/api/team/0'
}

クエリストリングに配列を渡す場合は v[]=a&v[]=b&... にする

(参考ページ2より)

サブリソースをリンクにした場合、いわゆる「N+1問題」が発生する。 これは最初の1回+リンクN回のアクセスが必要になるという問題。

そこでAPIへのアクセス効率を上げるため、一度で複数のリソースIDを取得できるように考える。 たとえばクエリストリングに配列で渡す。

クエリストリングで配列を表現をするケースをざっと調べる - コード日進月歩

RailsでGETメソッドのクエリストリングで配列を渡したい時にどうするか - Qiita

以下のような配列vを考える。

["v" => ["zero", "one", "two"]]

RailsではArray.to_queryで以下のような文字列が得られ、一般的にこれが使われる。

v[]=zero&v[]=one&v[]=two

PHPではhttp_build_queryに配列を渡すと以下のようになる。

v[0]=zero&v[1]=one&v[2]=two

PHPではparse_strでこのクエリストリングを配列に戻すことができる。 もし配列に添字が無い場合には、自動的に0からの連番とみなされる。 つまり、Rails形式も受け入れることができる。

ページネーションは page=2&per_page=100

GitHub API v3 | GitHub Developer Guideでは以下のようになっている。

page=2&per_page=100

URLにAPIバージョンを入れる /v1

APIバージョンをURLに入れてしまう。 apiという言葉自体もホスト名に入れて不要とし、いきなりv1などとするのが簡潔に思える。

WebAPIから返ってくるJSONの実例

Introduction to Tweet JSON — Twitter Developers

郵便番号検索API - zipcloud

RESTfulでないものの扱い

(参考ページ1より)

検索用には/searchというエンドポイントを作成する。

上記zipcloudのURLは次のようになっている。

http://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060
集計、レポーティング

特定の集計やレポート、たとえば企業の年間売上などはサーバーで集計すると効率がよい。

集計結果自体を(更新不可能な)リソースとして提供する。

例: 売上集計のURL

/report/sales/2019
/report/sales/2019/09
/report/sales/2019/09/05

/archives/:year/:month/:day routes with REST? - Rails - Ruby-ForumによるとこのURLはRESTfulではない。 日付をよりRESTfulにするには以下のようにすべきらしい。

/report/sales/year/2019/month/9
/report/sales/year/2019/month/9/day/5