RESTful APIを設計した際のステータスコードの指針です。
メソッド別
GET
成功した場合
-
200 OK:最も一般的 -
304 Not Modified:条件付きGETでキャッシュを使わせたい場合
POST
成功した場合
-
201 Created- 作成したリソースのURIを示す
Locationヘッダを付けておく
- 作成したリソースのURIを示す
議論
-
200 OKだとまずいのか?-
200 OKを応答する実装も多くあり、まずいというわけでもない -
200 OKはPOST結果がキャッシュ可能、201 CreatedはPOST結果がキャッシュ不可能として分けてもいいが、そこまでする必要があるか?(POSTのキャッシュは一般的ではない)
-
-
204 No Contentだとまずいのか?- クライアントがPOST結果を事前に全て知っているわけではないので
No Contentは不親切では?
- クライアントがPOST結果を事前に全て知っているわけではないので
失敗した場合
-
409 Conflict:作成しようとしたリソースが既にある場合
成功でも失敗でもない場合
-
303 See Other:作成しようとしたリソースが既にあるが失敗とみなさないようにする場合- 既存の同一とみなすリソースのURIを示す
Locationヘッダを付けておく - ただし、失敗とみなすのが普通かもしれない
- 既存の同一とみなすリソースのURIを示す
PUT
成功した場合
-
204 No Content:更新の場合 -
201 Created:新規作成の場合- 作成したリソースのURIを示す
Locationヘッダを付けておく
- 作成したリソースのURIを示す
議論
- PUTで新規作成できるAPIを提供する必要があるかどうかはまた別の話
- 更新の場合
200 OKだとまずいのか?- まずくはないが、PUTが成功したということはクライアントにとって自分の思い通りの結果になったということなので中身はそんなに重要ではない。
204 No Contentで十分。
- まずくはないが、PUTが成功したということはクライアントにとって自分の思い通りの結果になったということなので中身はそんなに重要ではない。
失敗した場合
-
409 Conflict:作成しようとしたリソースが既にある、または、更新しようとしたリソースがロック中(楽観・悲観どちらでも)の場合
PATCH
成功した場合
-
200 OK:パッチしたリソースを返却する場合 -
204 No Content:パッチしたリソースを返却しない場合
失敗した場合
-
409 Conflict:パッチしようとしたリソースがロック中(楽観・悲観どちらでも)の場合
DELETE
成功した場合
204 No Content
失敗した場合
-
409 Conflict:削除しようとしたリソースがロック中(悲観)の場合
議論
- 削除しようとしたリソースがRDBでいうところの参照整合性制約違反のため削除できない場合
- そのリソースを削除しようとすること自体が間違いなのでサーバエラーではなくクライアントエラーであるはず
-
422 Unprocessable Entityもしくは409 Conflict
- 削除済みの場合、
410 Goneを使うべきか?- 不要。
404 Not Foundで十分。 - ただし、最初から存在しないリソースを削除しようとした時と区別がつかない
- 不要。
どんなメソッドでも
成功した場合
-
205 Reset Content:不要。リセットするかどうかはクライアントが考えればよいのでは?
失敗した場合
-
4xxは通知することでクライアントまたはユーザが反応できる可能性があるときに応答する-
400 Bad Request:データ形式が間違っている場合(JSONのパースエラーなど) -
401 Unauthorized:何らかの認証が必要な場合。言い換えるとAuthorizationヘッダが必要な場合。 -
402 Payment Required:支払いが必要な場合。(RFCでは将来のための予約らしいがWebPayがこれで応答する時がある) -
403 Forbidden:不要。クライアントが403を受け取っても特別な意味のある処理はできないのなら404 Not Foundで十分。 -
404 Not Found:存在しない場合。または、存在することを隠したい場合。 -
405 Method Not Allowed:そのリソースに指定されたメソッドが用意されていない場合。 -
406 Not Acceptable:Acceptヘッダとマッチしない場合。 -
408 Request Timeout:不要。そもそも、これがクライアントエラーであることをサーバ側ではどうやって判定するのだろう。 -
415 Unsupported Media Type:データ形式は正しいがサーバが相手にしたくない場合。
-
-
5xxは通知しても反応に困るときに応答する-
500 Internal Server Error:その他のサーバに起因するエラーにより処理続行できない場合。 -
503 Service Unavailable:一時的にサービス提供ができない場合。(メンテナンス等)
-
議論
- 入力チェックエラーについて
- データ形式が間違っている場合は
400 Bad Request - データ形式は間違っていなくてもサーバ側で処理できない場合は
415 Unsupported Media Type - データ形式は間違っていなくて処理もできるがビジネスロジック上受け入れてはいけない場合は
422 Unprocessable Entity -
422 Unprocessable EntityはWebDAV拡張だけど使っていいのか?(Railsがデフォルトで使っている)
- データ形式が間違っている場合は
- 存在しないものについて
- URIで表されたリソースが存在しない場合
404 Not Foundとする - URIで表されていないが処理継続に必要になるリソースが存在しない場合はどうするか
- 場合によっては
500 Internal Server Errorかもしれない
- 場合によっては
- POSTの場合は処理対象とするリソースそのものはなくても構わない
- 例えば、
/posts/1/commentsのcommentsはなくてもいいが/posts/1がないと404 Not Found
- 例えば、
- URIで表されたリソースが存在しない場合
- 外部システムのエラーについて
- サーバが別のシステムに依存していて、そのシステムがエラーを返した場合
- 別システムが起因(
5xx)の場合、その別システムが正常に動くようになるまで503 Service Unavailable - 自サーバが起因(
4xx)の場合- クライアントから与えられたデータを丸投げしているだけの場合、
422 Unprocessable Entity - サーバ内で何らかの処理をしている場合、
500 Internal Server Error
- クライアントから与えられたデータを丸投げしているだけの場合、
- 別システムが起因(
- サーバが別のシステムに依存していて、そのシステムがエラーを返した場合
- エラー詳細について
- エラーの場合は、結局レスポンスボディになんらかのエラー詳細情報を含めないとクライアント側では反応に困ることになる
- ということは、実際問題としてステータスコードでは
400と500だけ分けておいて、細かいことはエラー詳細情報で判断するようにしてもいいのでは?