HTTP レスポンスを解析する
←[www.kasai.fm]



1. 概要
 このページでは、perl を使って HTTP レスポンスを解析する方法を説明します。
 perl プログラムの文法や、書き方、実行の方法は、既に知っている事を前提にしています。
 ここで説明するのは、HTTP レスポンスを解釈するプログラムだけです。HTTP レスポンスをサーバから取り寄せる方法は、perl から他の Web ページを読み込むを参考にして下さい。

 HTTP レスポンスとは、Web サーバから送られてくるデータの事です。
 ちょっと考えると、これはただの HTML や画像データのような気がしますが、実際はもう少し複雑で、色々な付加情報が含まれています。
 ブラウザ(HTTP クライアント)は、この付加情報を見ることによって、転送をスムーズに行ったり、情報の種類を判別したりしています。

 よって、例えば自分で telnet を使ってサーバにアクセスした場合などは、目的のデータ(HTML や画像)を得る為に、もうちょっと努力して、この付加情報を解釈せねばならないのです。

 ブラウザも、Web サーバから送られてくる HTTP レスポンスを解析し、ホームページとして表示しています。
2. HTTP レスポンスの構造
 HTTP レスポンスは、ある文法に従って構成されるテキストメッセージです。
 文法は、IETF の RFC2616(別ウィンドウ)で規定されています。

3. レスポンスからデータ部を取り出す手順
下記のプログラムを使用すると簡単です。
4. プログラムソース

(1) analysisHTTP
2003年 1月18日
  • 改行を分割する正規表現を、\r\n から \r?\n に変更。(UNIXサーバ上では \r が必要ないため)
    横浜のH.N.様よりご指摘頂きました。ありがとうございます。
2002年 1月16日未明
  • ヘッダ部とデータ部を分割する正規表現を変更。(環境により正しく動かなかったのが修正されました)
2002年 1月12日未明
  • 初稿。transfer-extension および chunk 以外の transfer-coding は理解せず、それらは素通りする。
####### HTTP レスポンスを解析する

# 動作に必要な環境:
# ・perl 5 以降

# 使用方法:
# require('analysisHTTP');
# require('decodeChunk');
# %data = &analysisHTTP($http_response);
#  # $data{BODY} に、データ部(HTML や JPEG 画像)が入る。
#  # $data{STATUS} に、ステータスコード行が入る。
#  # $data{ヘッダ名} に、ヘッダに書かれていた値が入る。


sub analysisHTTP{
  my $data = $_[0];
  my %head;

  my ( $head, $body ) = split(/\r?\n\r?\n/, $data, 2);
  my ( $status, @headline ) = split(/\r?\n/, $head);

  foreach $line(@headline){
    my ($item, $val) = split(/:\s*/, $line, 2);
    $head{$item} = $val;
  }
  
  if ($head{'Transfer-Encoding'}){
    foreach $te( split(/\s*:\s*/, $head{'Transfer-Encoding'}) ){
      my ( $coding, @parameter ) = split(/\s*;\s/, $te);
      my %parameter;
      foreach $parameter(@parameter){
        my ( $item, $val ) = split(/\s*=\s/, $parameter, 2);
        $parameter{$item} = $val;
      }
      
      $body = &decodeChunk($body) if ($coding eq 'chunked');
    }
  }
  
  return (%head, 'STATUS', $status, 'BODY', $body);
}
1;



(2) decodeChunk
2002年 1月12日未明
  • 初稿。chunk-extension、空でない trailer は理解しない(ただしエラーにはならない)。
####### chunk transfer-coding をデコードする

# HTTP レスポンスの chunked transfer coding されたデータを
# 解釈(平文に戻す)します。

# 動作に必要な環境:
# ・perl 5 以降

# 使用方法:
#  require('decodeChunk');
#  $flat_data = &decodeChunk($chunked_data);

sub decodeChunk{
  my ($chunk_body, $data) = ($_[0]);
  
  do {
    my %chunk_ext;
    my ($topchunk_sizeline, $chunk_body) = split(/\r?\n/, $chunk_body, 2);
    my ($topchunk_size, @topchunk_ext) = split(/\s*;\s*/, $topchunk_sizeline);
    $topchunk_size = hex($topchunk_size);
    
    foreach $ext(@topchunk_ext){
      my ( $item, $val ) = split(/=/, $ext, 2);
      $chunk_ext{$item} = $val;
    }
  
    my $chunk_part;
   ($chunk_part, $chunk_body)
   = ( substr($chunk_body, 0, $topchunk_size), substr($chunk_body, $topchunk_size + 1) );
    
    $data .= $chunk_part;
  } while ($topchunk_size);

  $chunk_body =~ s/\r?\n\r?\n$//;
  
  return $data;
}
1;

5. 使用方法
 使用する手順は次の通りです。
  1. 上記 (1)(2) のソースコードをコピー&ペーストし、(1) を analysisHTTP、(2) を decodeChunkというファイル名でそれぞれ保存します。
  2. この機能を使いたいプログラムを analysisHTTP, decodeChunk と同じフォルダに置き、
    require('analysisHTTP');
    require('decodeChunk');
    と、プログラムの中に書きます。プログラムのどこに書いても OK です。
  3. HTTP レスポンスを解析する時は、
    %http = &analysisHTTP($http_response);
    のようにします。($http_response) の部分に、解析したい HTTP レスポンスの入った変数名(スカラー値)を書く訳です。
  4. %http には、次のように結果が格納されます。
    $http{STATUS} ステータスコード行
    $http{BODY} 実データ
    $http{ヘッダ名} ヘッダ値


6. 免責
 本プログラムは、自由に配布、使用、改変して頂いて結構です。転載の許可も必要ありません。
 但し本プログラムを使用した結果、何らかの損害を被ったとしても、当方では責任を負いかねます。ご了承ください。

 と言いつつ虫の好い話ですが、バグや無駄な部分等を発見されましたら、下記アドレスまでご一報頂ければ幸いです。

←[www.kasai.fm]