Pinto公開に向けて #19 ― HTTPレスポンスヘッダのテストを考える
あらすじ
Pintoというソーシャルブックマークサービス、およびPintoBeansというWebアプリケーションフレームワークをRubyで開発中です。その際に気づいたことや工夫した点などを、備忘録を兼ねて書いています。その19回目です。
Rackの挙動を確認
PintoではRackというライブラリを使います。SPECには下記のようにあります。
A Rack application is an Ruby object (not a class) that responds to call. It takes exactly one argument, the environment and returns an Array of exactly three values: The status, the headers, and the body.
よって、Rackベースのアプリケーションを単純化すると、こうなります。
class PintoApplication def call(environment) [ 200, # status {'Content-Type' => 'text/plain'}, # headers 'under construction' # body ] end end
Pintoのトップページ仕様
昨日の日記に書いたとおり、PintoはTDD(BDD)で開発しようと思っています。何はともあれ、トップページのテスト(仕様)を書かなければすっきりしません。
ざっくり、トップページの仕様は下記のような感じです。
テストをどう書くか
さて、下記のようなリクエストに対するテストを考えてみます。
GET / HTTP/1.1 Host: pinto.jp
Rackにはモックリクエストクラスがあるので、リクエストのエミュレートにはそれが使えます。そのリクエストに対するレスポンスが正しいかどうかのテストを書けばよいわけです。
とりあえず、ステータスコード(配列の1番目)が300であるかどうかは単純に書けますね。
レスポンスボディ(配列の3番目)も、XHTML1.1として妥当かとか、UTF-8で書かれているかとか、特定の要素が正しく出力されているかとか、そのようなテストを書けばよいでしょう。
悩むのはレスポンスヘッダ(配列の2番目)です。
妥当なレスポンスヘッダは何か
RFC 2616で規定されているレスポンスヘッダを列挙しながら考えます。
- general-header
-
Cache-Control 6時間(21600秒)キャッシュさせたいので「max-age=21600」 Connection Webサーバが設定してくれるので出力しない Date 同上 Pragma キャッシュありなので出力しない Trailer Webサーバが必要に応じて設定すべきと判断して出力しない Transfer-Encoding 同上 Upgrade 不要 Via 不要 Warning 不要 - response-header
-
Accept-Ranges Webサーバが必要に応じて設定すべきと判断して出力しない Age 不要 ETag Last-Modified値などを元に出力する(生成ロジックは後日考える) Location 不要 Proxy-Authenticate 不要 Retry-After 不要 Server 不要(WEBrickは勝手に追加する) Vary Accept系のリクエストヘッダは無視することに決めたので出力しない WWW-Authenticate 不要 - entity-header
-
Allow 「GET, HEAD, OPTIONS」 Content-Encoding Webサーバが必要に応じて設定すべきと判断して出力しない Content-Language 「en」 Content-Length Webサーバが設定してくれるので出力しない Content-Location 不要 Content-MD5 攻撃には無力らしいので出力しない Content-Range Webサーバが必要に応じて設定すべきと判断して出力しない Content-Type 「application/xhtml+xml; charset=UTF-8」 Expires 6時間後の時刻(HTTP1.1では不要だが、そこまで考えたくない><) Last-Modified スクリプトファイルの更新日時 extension-header 特に不要
というわけで、強調した7件について正しく出力されること、それ以外について出力されないことをテストすればOK、という結論に至りました。ああ、長かった。
ちなみに
時刻を返す部分は、テスト実行時刻に応じて値が変わるのを防ぐため、Mochaなどでスタブを作ろうと思っています。
追記(2008-08-26)
ETagやLast-Modifiedを吐くと書いておきながら、304や412のケースの想定を忘れていました。
ざっくりまとめると、304の場合はETagとExpires、412の場合はエラー画面のXHTMLとともにAllowとContent-LanguageとContent-Typeを、それぞれ出力すれば良いと思っています。HTTP難しい><