Restful APIにおけるリソース設計とレスポンスのHTTPステータス考察

とあるSAP案件でサーバーサイド側を一任され、リソース設計から担当していました。

TaNA
こーゆーのは最初の設計がイケてないと、使い辛い&保守し辛いシステムになるので責任重大。とは言え1からリソース設計した事が無かったので、とりあえず先人が遺してくれたQiitaの素晴らしい記事を読み漁ることに。

更にこの本を再度読み返し、2週間くらいで設計、1ヶ月くらいでの開発でした。

本当に良いリソース設計だったか不安ですが、その時のメモ書きです。

RESTとは

RESTとはWebのアーキテクチャスタイル。

RESTではクライアント/サーバに他の制約(ステートレス/キャッシュなど)を課す事で構成。

本書ではRESTを、クライアント/サーバから派生したアーキテクチャステイルであり、素のクライアント/サーバアーキテクチャスタイルに幾つかの制約を加えたものがRESTになる紹介されています。

POINTRESTの意味はリソース(Web上の情報)の状態を表現するもの。

では実際にRestfulなAPIを実装するためにリソースの設計はどうすればよいのか!?

リソース設計

リソース設計とはクライアント・サーバ間のインタフェース設計(Web APIの外部設計)。

オブジェクト指向やリレーショナルデータベースに比べ、リソース設計には一般的な設計手法が無いとのことですが、本書ではリソース指向アーキテクチャの設計アプローチが紹介されています。

リソース指向アーキテクチャのアプローチは以下のとおりです。

1.Webサービスで提供するデータを特定

2.データをリソースに分ける

3.リソースにURIで名前をつける

4.提供するリソース表現を設計

5.リンクとフォームでリソース同士を結びつける

6.イベントの標準的なコースを検討

7.エラーについて検討

1と2はデータベース設計等でやるイメージですが、まぁ考えるべきは3、4、7でしょうか。

良いURI設計

ちなみに良いURI設計については、このように紹介されています。

POINT良いURI・綺麗なURI(クールURI)は変わらない!!

3と4について「良いURI」設計のための勘所が記載されています。

・言語依存の拡張子はNG

・実装依存のパスはNG

・言語のメソッド名はNG

・セッションIDを含めない

・リソースを表現する名詞

ここまでは教科書に載っていた内容。

Qiitaでは実戦的に分かりやすく説明されている こちらの記事 を発見したので併せて熟読。

ステータスコード

主に利用するメソッドはGET、POST、PUT、DELETEの4つ。

まずはリソース取得で利用するGET。

・200 – 成功時

リソースの新規登録など多岐に利用されるPOST。

・201 – 成功時

リソースの追加で利用するPUT。

・200 – 成功時

・409 – 対象リソース無し

最後にリソースの削除で利用するDELETE。

・200 – 成功時

・409 – 対象リソース無し

DELETEの成功時は204にする事もある模様。

共通的なものは以下の3つ。

・400 – バリデーションエラー

・401 – 認証エラー

・503 – 予期せぬエラー

リソースをHTTPメソッドで操作

RESTのキーは「論理的に分割されたリソース」をHTTPメソッドで操作する事。

TaNA
実際のフレームワーク開発では、名詞(使う側が客観的に見て分かる名前[複数形])で名付けられたコントローラクラスに対し、HTTPメソッド(GET、POST、PUT、DELETE等)でリソース操作を行うよう設計を考えます。

RESTの原則に従い、HTTPメソッドを使ってCRUD操作は以下のように定義。

・GET:リソースの取得

・POST:リソースの新規作成

・PUT:リソースの更新

・DELETE:リソースの削除

例えばUsersテーブルに対して取得・登録・更新・削除を行う場合は以下のようなイメージ。

・GET /users – ユーザーのリストを取得

・GET /users/1 – 指定ユーザーの情報を取得

・POST /users – 新しいユーザーを作成

・PUT /users/1 – ユーザー #1を更新

・DELETE /users/1 – ユーザー #1 を削除

KISSの原則によれば、リソースは複数形が良いそうです。

関連データを取得する場合は!?

関連データの取得ですが、あるリソースに付随してのみ存在する場合は簡単。

・GET /users/1/skills – ユーザー #1に紐づく資格リスト取得

・GET /users/1/skills/2 – ユーザー #1に紐づく資格 #2の情報取得

・POST /users/1/skills – ユーザー #1に紐づく資格情報の登録

・PUT /users/1/skills/2 – ユーザー #1に紐づく資格 #2の更新

・DELETE /users/1/skills/2 – ユーザー #1に紐づく資格 #2の削除

関連データがリソースから独立して存在する場合は!?

レスポンス値に関連データのキー情報を含めるよう設計する。

複数テーブル結合のケース

この名詞選びが意外に難しいです。

単純に1つのテーブルに対してなら、上の設計で問題無いのですが、実際の業務では、複数テーブルを結合して必要なデータを取得するので、その場合の名詞はどうすべきなのか…

複数テーブルを結合し、元のテーブルが意味するリソースと別の意味を持つリソースを取得する場合、使う側が分かりやすいよう複数テーブルが表現するデータの概念を名詞にしていました。

例えばテーブルに本、利用者、貸出リストの場合は以下の通り。

・GET lendinguser/{userId} – 本を借りているユーザー取得

実際、複数テーブルを結合する場合でも、その複数のテーブルが扱うリソースが単一テーブル名から、それ程逸脱していなければ、テーブル名をそのまま使っている場合も(^▽^;)

CRUDに合致しないケース

一括削除などが例ですが、最初は「DELETE /articles」のように設計を考えました。

しかしDevelopers.IOさんのブログでは「/articlesという記事の集合リソース自体を削除」と解釈される可能性があるので、推奨されず、ブログではPOST+末尾に動詞で紹介されています。

・POST /articles/delete

ちょっとリソース設計に名詞ではなく、動詞が入っているのは気になりますが…