Entry

ウェブアプリが返すレスポンスヘッダのステータスコード問題についてつらつら

2008年08月22日

随分昔の話なんですけれど,こちらの話から。EC サイトで「商品がないよ」というとき,HTTP のレスポンスヘッダに何を設定すべきか,といった話です。

オリジナルのWebアプリでも出来合いのWebアプリでも企業が構築した高度なWebサイトであっても、データ層(DBとか)からの取得結果がゼロ件なら「その商品/記事はありません」を表示する、といった仕様は当たり前のように実装されている。しかし、HTTPステータスコードまできちんと考慮されているケースは実は驚くほど少ない。

ステータス200なのに「その商品はありません」

これって実は結構根が深くって,単純に「商品が見つかりませんでした」のときに 404 を返せばいいってな話でもないんですよね。以下のコメントで,「商品がない」を 404 にすべきだと言っているわけではない,とあるんですけど,それはその通りなんだと思います。

筆者のかたは、
「商品がない」は「404」にすべき。
と言っているわけではないですよね。

人間には「えらー」とか「ページがありません」しか見せていないのに、
機械には「200」と返している矛盾が問題だと行っているのだと思います。

ステータス200なのに「その商品はありません」[しげさんのコメント]

けれど,この見方も少し考えると微妙です。HTTP のレスポンスヘッダは,ボディの「内容」とはあまり関係がない。つまり,「人間には『えらー』とか『ページがありません』しか見せていないのに、機械には『200』と返している」ことを「矛盾」ととらえるかは,そのウェブアプリの例外ポリシーに依存する話なんだと思います。

どういうことか。まず,何はともあれ,404 のステータスコードがどのように説明されているか,見てみましょう。RFC 2616 から抜粋。

The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.

HTTP/1.1: Status Code Definitions

超訳。

サーバがリクエスト URI にマッチするリソースを見つけられなかったことを表します。見つからなかった事情が一時的なものか恒久的なものかについて,指し示すものはありません。もしサーバで設定可能な機能を通じて,恒久的に参照不能なりソースであり,フォワードアドレスもないことが分かるようなら,サーバは 410 (Gone) を返すべきです。このステータスコードは,サーバがリクエストを拒否する理由を正確には明らかにしたくないときや,他のレスポンスが当てはまらないときにも,同じように使われます。

つことで,404 ってのは,「URI にいわゆるリソース(Resource)がなかったよ」という場合の他に,「なんか嫌なリクエストだから拒否するですよ」というときにも使われるようです。HTTP は,ネット上のリソースに対する要求(リクエスト)と応答(レスポンス)のプロトコルですから,プロトコルレベルで考える限り,404 を返すか否かの主眼は,拒否すべき URI リクエストかってなところにあるわけで,商品が実際にあるかとか,裏っかわの DB がどうとかってのは,あまり関係がなかったりします。

この点,URI という視点で考えると,ウェブアプリで使われる URI は,REST な環境でもない限り,URI そのものの意味をあまり意識していなかったりします。「処理の入り口」くらいの意味合いしかないこともしばしばじゃないでしょうか。こういう状況では,404 で不正なものとして拒否すべき「リクエスト」ってもんを,アプリケーションの仕様抜きでそもそも観念しづらかったりします。つまり,大半のウェブアプリにおいて,URI にどういう意味を与えるか(リソース的な意味合いなのか,とか,単なる処理の入り口なのか)は,「アプリケーション仕様」の水準で考えられるものであって,アプリケーション側で考える,リソース概念とか例外機構に強く依存すると思うんですね。

もう少し具体的に言うと,例えば,商品検索機能について,その URI が「商品」というリソースを表現するものであると(仕様として)規定した場合は,404(商品というリソースがないよ)を返した方が説得的です。しかし反面,URI を検索機能の単なる入り口として規定した場合は,「商品がないよ」と表示する画面ないし機能そのものが資源(Resource)として取り扱われることになります。この場合は,プロトコルレベルではなく,アプリケーションレベルで「商品がない」と言っているだけの話になるので,200 (OK) を返してもなんら問題はないんじゃないでしょうか。「商品がない」と表示する画面は「ある」わけですから。この点については,引用コメント中ふじさわさんも指摘しています。

問題は,相手方(クライアント)側でする 404 または 200 の受け取り方(解釈)です。

上述した通り 404 は,サーバとして拒否すべきリクエストなのかが問題になっているわけで,このレスポンスはいわゆる「異常系」に分類されるものです。つまり,こういうリクエストはサーバアプリとして受け付けない不正なものなんですよ,ということを表している。商品の例で言うと,URI 中,ISBN のような商品コードを表す箇所の桁数やチェックサムが不正だった場合(URI としてありえない場合)なんかは,404 を返す(異常系に分類する)のもアリなんだと思います。しかし,形式的にありうる商品コードで,単に取り扱いがない場合についても,不正なリクエストとして異常系に分類すべきかは,一般的には判断できないかなり微妙は問題なんじゃないでしょうか。それこそ,そのアプリの例外機構をどうデザインするかによると思うわけです。

消費者からみれば、検索結果に引っかかったページへのリンクをクリックしたら「売り切れました」と表示されるより、最初っから検索に引っかからないほうがいいわけですよね?

ステータス200なのに「その商品はありません」[とおりすがりの倉庫キャラさんのコメント]

一方,引用中では「検索にひっかかるか否か」が主要なお題になっているわけですけれど,この話は,当該検索エンジンの検索ポリシーの問題なわけで,ウェブサーバ側で気にするようなことではないと考えています。404 または 200 を受け取った後でクライアントがどのような処理を実行するかは,クライアントの自由なわけで,その後の振る舞いにまで首を突っ込むべきじゃないからです。検索エンジンのためにウェブアプリがあるわけじゃありませんしね。主従が逆です(少なくともタテマエ的には)。

個人的には,レスポンスヘッダで細かく状態を示すのは,労力の割に効果が少ないんじゃないかと思っていたりするわけで,アプリケーションレイヤで例外機構を完結させても問題はないと思っています。つまり,プロトコル的には全て 200 を返すということ。あえて検索エンジンのことを考えても,無効だった URI を有効なものに変更した時に,一度 404 を返されたクライアントが,同じ URI で再びクロールしてくれるのか,ってな心配もありますしね。

まぁ……まぁ,微妙な問題だとは思うわけです。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN