CatalystアプリをWebサーバにのっけてみる(5) Catalyst on IIS編

Catalystで作ったアプリをIISCGI動作で動かしてみたら、動作が変。htmlの出力が途中で途切れる。

HTTPヘッダを見てみる(ieHTTPheadersで確認)とどうもContent-Lengthが少ない。というか、途切れている部分までのバイト数と一致している。で、いろいろ調べまわった結果、たぶん、結論はこれ、たぶん。

IISがあほうな改行コード変換をしているせいで、CatalystがContent-Lengthを計算した後に、実態のデータ量が増えている。

ばかー、ふぁっきん、さのばびーっち!

で、しょうがないのでCatalyst側に対策しました。
site/lib/Catalyst.pmのContent-Length計算部分に、$c->response->bodyの改行文字数を足すように変更。↓これ。

   # Content-Length
   if ( $c->response->body && !$c->response->content_length ) {

       # get the length from a filehandle
       if ( blessed( $c->response->body ) && $c->response->body->can('read') )
       {
           if ( my $stat = stat $c->response->body ) {
               $c->response->content_length( $stat->size );
           }
           else {
               $c->log->warn('Serving filehandle without a content-length');
           }
       }
       else {
                       # Hack to fix fxxk'n IIS return code issue.
                       my $n;
                       my $fh = $c->response->body;
                       $n = $fh =~ s/\n/\n/g;
                       $c->response->content_length( bytes::length( $c->response->body ) + $n );
       }
   }

参考になりました:
2.9 小さな親切大きなお世話?! - CGIの要点整理

CGIがデータを送信するときは,すでに,改行コードが [CRLF] になっているデータを送信すると,"CRCRLF"に変換して送信してしまいます.これにより, CGIが Content-Length で指定したサイズよりデータサイズが大きくなってしまいます.

CGIでHTTPヘッダー「Content-Length」を出力するには?

Windows 環境で、出力する HTML が50行程度ならば、改行コードでしょう。
試してないけど length($data) + $data=~s/\n/\n/g とするか、binmode(STDOUT) かな。