日曜日, 5月 29, 2005

Transfer-Encoding の chunked

HTTPプロトコル(protocol)の話です。
たぶん、かなりマニアック。

HTTPのヘッダーには「Transfer-Encoding」というものがあります。
どうやってコンテンツ部分を転送するかを指定するものです。サーバー側の環境変数でいうと「HTTP_TE」です。
特に値が指定されていなければContent-Lengthの数バイトがコンテンツとして転送されますね。

この値が「chunked」のときにはちょっと変わっています。
1. 最初の行の値が16進数で表した、これに続くコンテンツのバイト数
2. 上のバイト数が0ならここでリクエストの応答は終わりです。
3. 上のバイト数分のコンテンツ
4. 1に戻る
みたいな感じなので、「0」だけの行が出てくるまで読み続けるわけですね。

動的なコンテンツの場合にはパートごとに分けて作れるので便利なわけです。
ソケットを使って自分で読み取るプログラムをPerlで書いてみました。

---------------------------------------------------------------------
sub get_content {

my $sock = shift or die;
my $debug = shift;

my $header = '';
my $content_length;
my $chunked;
while ( <$sock> ) {
warn $_ if $debug;
$header .= $_;
$content_length = $1 if m/Content-Length: (\d+)/;
$chunked = 1 if m/Transfer-Encoding: chunked/;
last if m/^\r\n$/;
}

my $content = '';
if ( $chunked ) {
while ( <$sock> ) {
warn $_ if $debug;
last if m/^\r\n$/;
s/\r\n//;
my $content_length = hex($_) or last;
my $buff;
read $sock, $buff, $content_length;
$content .= $buff;
}
}
elsif ( $content_length ) {
my $buff;
read $sock, $buff, $content_length;
$content .= $buff;
}
else { die $header }

return wantarray? ( $content, $header ): $content;
}
---------------------------------------------------------------------

まあ、たまにはこんなこともしてみます。

0 件のコメント: