HTTP ステータスコードを正しく使おう
» Permanent link | |
先月、ぐるなび API がリリースされていました。 ぐるなびさんの持っている膨大なデータベースに Web API を通して気軽にア クセスできるようになったのは、非常に喜ばしいし、その英断に感謝したいと 思います。
しかし、Web API 仕様書、特にエラー仕様を見てちょっとがっかりしました。 もう少し上手にデザインすれば、もっとよかったのに…、という思いです。
一度出してしまった API はそう簡単に変えられないと思いますが、 参考までに僕だったらどうするか、を書いてみます。
この仕様の一番の問題はエラーコードです。 以下は 2-2 のエラー仕様に記述されているサンプルです。
<?xml version="1.0" encoding="UTF-8"?> <gnavi> <error> <code>602</code> </error> </gnavi>
タグが三つ(gnavi, error, code)出てきます。 重要なのは code だけで、ここにエラーコードが入ります。 602 というコードは Invalid Shop Number を示します。 エラーコード一覧を見ると、現在五つのコードが定義されていることがわかり ます。
よくない点を一言で言うと、エラーコードを再発明してしまっているということです。 たとえば 604 は "Internal Server Error" なんですが、 このフレーズに覚えがありませんか? そう HTTP の 500 Internal Server Error と同じです。HTTP で 500 を返せばいいところを、 独自 XML 形式でしかも 604 という独自のエラーコードを再発明しています。
HTTP/1.1 200 OK Content-Type: application/xml <?xml version="1.0" encoding="UTF-8"?> <gnavi> <error> <code>604</code> </error> </gnavi>
本来はこうあるべきです。
HTTP/1.1 500 Internal Server Error Content-Type: text/plain; charset=utf-8 処理中にエラーが発生しました。
なぜエラーコードの再発明は駄目なのでしょうか。それは専用のクライアントが必要になる からです。単なる HTTP クライアントではなく、ぐるなびのエラーコードを実 装した専用クライアントが必要になってしまうからです。専用クライアントが 必要なので、その分余計なコードが必要となって、障害が発生する確立も上り ます。
参考までに、ぐるなび API のエラーコードを HTTP のステータスコードにマッピングしてみました。
gnavi エラーコード | HTTP ステータスコード |
---|---|
600 NoShop | 404 Not Found |
601 Invalid Access | 403 Forbiddden |
602 Invalid Shop Number | 400 Bad Request |
603 Invalid Type | 400 Bad Request |
604 Internal Server Error | 500 Internal Server Error |
601 は通常は 401 Unauthorized にしたいところですが、 ぐるなび API は api key 方式を採用しているので 403 にしてみました。 また、この対応により 602 と 603 が 400 にまとめられてしまっていますが、 両者の違いは HTTP のレスポンスボディで記述すればいいでしょう。 もし、この二つを区別する理由が、エラーメッセージを出すためだけであれば、 メッセージそのものをプレーンテキストで返せばいいのです。
HTTP/1.1 400 Bad Request Content-Type: text/plain; charset=utf-8 指定された店舗の情報が存在しません。
HTTP/1.1 400 Bad Request Content-Type: text/plain; charset=utf-8 不正なぐるなび店舗IDパラメータが指定されました。
WEB+DB Press の今月号には、まさにこの話を書きました。 本文とコラムが同じくらいのページ数という、一時期の JavaWorld の檜山さ んみたいな構成ですが、 普段なにげなく使っている HTTP のステータスコードは Web API を作る上でどうあるべきか、という話です。
- WEB+DB PRESS Vol.39
- WEB+DB PRESS編集部
- 技術評論社 2007-06-22
8 Comments:
WebAPIに関わらず、通常のシステム開発でもよくあることですね。
IllegalArgumentExceptionがあるのにParameterExceptionを作っているフレームワークとか。
勘弁してよって。
ぐるなびのAPIは自分もそう思いました。設計慣れしていない雰囲気を感じます。
IllegalArgumentExceptionは実行時例外なので、キャッチ例外が欲しいという可能性があるかも。
主題には同意しますが、エラーメッセージはこれがいいのでしょうか?
・本文にエラーコードを入れる。
・本文のエラーの説明には、英文は必ず入れる。
・もし日本語だけにするならば、せめて言語タグを入れる。
方が良いと思いますが。
Akihiro さん
HTTP レスポンスボディを plain text にしたのは簡単のためです。利用しているメッセージフォーマットに合わせて text, xhtml, atom entry, 独自 XML などを適宜適用するのが望ましいと思います。
ただ、その中にエラーコードが必ず必要とは思いません。どんなユースケースを想定されていますか?
簡単のため、というのは説明を簡単にするため、という意味ですか?
以前から海外のサービスで、エラーメッセージが現地語(ドイツ語とか)しかないものがあり、せめて英語のメッセージも併記してもらいたいとおもっていましたので、英語のエラーメッセージは併記して欲しいですね。
また、エラーコードの件はシェルスクリプトからwgetを使ってアクセスして、エラーの場合コードを検出して分岐する、なんて事例を想定しています。
「簡単のため」はそのとおりです。
エラーメッセージの多言語化ですが、クライアントが Accept-Language ヘッダで自分が所望する言語を指定することも可能です。この場合はクライアントの要求に合わせた言語のメッセージを plain text で返してもいいですね。もちろんサーバ側で実装する必要があるわけですが。
wget の例、ありがとうございます。ただ、まだちょっとわかりません。その分岐には本当にステータスコード以外のエラーコードが必要ですか?ぐるなびの例でいえば、invalid shot number と invalid type のコードがレスポンスに入っていたとして、wget は何をどう分岐するんでしょう?
エラーメッセージの言語の例は、Accept-Languageが指定されていない場合は英文のエラーメッセージで、指定されていたらその言語で、という仕様ならば問題ありません。
あと、エラーコードの件は、HTTPのステータスコード以外のエラーコードを付けるべきだ、とは主張していません。
エラーメッセージの部分(できれば先頭)にHTTPのステータスコードが書いてあれば、より便利と主張しているだけです。
エラーメッセージ(HTTP レスポンスボディ)に HTTP ステータスーコードを書いて、そのコードで処理を分岐するのには反対です。ステータスコードは HTTP の仕様どおり、レスポンスのステータスラインに書かれているものを前提に処理を行うべきです。メッセージにエラーコードが書かれていなかったらどうするんでしょうか。結局ステータスラインを見ますよね。
コメントを投稿
<< Home