Apacheは知らないhttpステータスは返さない。

正しくは、500を返す。

render :nothing => true, :status => 450

なんてことをしていて、Mongrelの開発環境だとちゃんと450が返ってくるのにApache+Passengerの検証環境だと500が返ってきていた。
そこで原因を調べたところ、返す可能性のあるステータスコードはすべて定義されていて、それ以外は500で返している。(※ソースは後述)

で、なんでこんなことをしようとしているのか。Flashのアップローダを作ってFileReference#upload()でアップロードしているのだけれど、こいつが結果をHTTPステータスでしか受け取れない。だから、結果のメッセージをサーバから返してそれを表示する、てこともできない。
アップロード自体が成功したか否かを知るには200かそれ以外か、くらいで十分なんだけれど、アプリ要件(たとえば、アップロードが終わってからファイルを受け付けられない状況になってただとか、ファイルの中身を見て判断しなきゃいけないだとか)での結果を返すには、これでは足りない。
結局、Apacheのソースコメントでunusedとなっていた418~421に意味を持たせ、そこを使って対応しました。層を混同していて気持ちがいいものではないのだけれど、影響範囲は広くなく、なんらかのフラグを立てて別リクエスト、のコスト増を考えるといいだろうとの判断。もしなにかいい方法があったら教えてください。

以下、Apacheソースの該当部分。

httpd-2.2.14/modules/http/http_protocol.c

 731 AP_DECLARE(int) ap_index_of_response(int status)
 732 {
 733     static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400,
 734     LEVEL_500, RESPONSE_CODES};
 735     int i, pos;
 736
 737     if (status < 100) {               /* Below 100 is illegal for HTTP status */
 738         return LEVEL_500;
 739     }
 740
 741     for (i = 0; i < 5; i++) {
 742         status -= 100;
 743         if (status < 100) {
 744             pos = (status + shortcut[i]);
 745             if (pos < shortcut[i + 1]) {
 746                 return pos;
 747             }
 748             else {
 749                 return LEVEL_500;            /* status unknown (falls in gap) */
 750             }
 751         }
 752     }
 753     return LEVEL_500;                         /* 600 or above is also illegal */
 754 }

httpd-2.2.14/modules/http/http_protocol.c

  99 #define LEVEL_400 19
 100     "400 Bad Request",
 101     "401 Authorization Required",
 102     "402 Payment Required",
 103     "403 Forbidden",
 104     "404 Not Found",
 105     "405 Method Not Allowed",
 106     "406 Not Acceptable",
 107     "407 Proxy Authentication Required",
 108     "408 Request Time-out",
 109     "409 Conflict",
 110     "410 Gone",
 111     "411 Length Required",
 112     "412 Precondition Failed",
 113     "413 Request Entity Too Large",
 114     "414 Request-URI Too Large",
 115     "415 Unsupported Media Type",
 116     "416 Requested Range Not Satisfiable",
 117     "417 Expectation Failed",
 118     "418 unused",
 119     "419 unused",
 120     "420 unused",
 121     "421 unused",
 122     "422 Unprocessable Entity",
 123     "423 Locked",
 124     "424 Failed Dependency",
 125     /* This is a hack, but it is required for ap_index_of_response
 126      * to work with 426.
 127      */
 128     "425 No code",
 129     "426 Upgrade Required",
タイトルとURLをコピーしました