QUERY_STRING でパラメータを受け取る

先ほどのエントリで %ENV を表示する CGI プログラムを作りましたが、この CGI プログラムの URL の末尾に「?abc」と付けて、開いてみてください。
http://palmo.is.land.to/cgi/v/envtable.cgi?abc
$ENV{'QUERY_STRING'} の値として「abc」が入っているのが確認できると思います。


この「URL の最後に ? を付けて文字列を渡す」というのは、CGI などのウェブアプリケーションに簡単なパラメータを渡す時に利用されます。
HTML で送信フォームを作る為には <form> 要素を利用しますが、この際 method という属性を指定する必要があります。method は、HTTP リクエストに用いるメソッドを指定する属性で "GET" か "POST" を指定するのですが、これに "GET" を指定すると、URL の最後に「?」を付けて、「名前=値」の形の各パラメータが「&」でつなげられて渡されます。
例えば、以下のように HTML でフォームを作ってみます。

<form action="query.cgi" method="GET">
  <input type="text" name="value" />
  <input type="submit" value="送信" />
</form>

この場合、以下のように表示されます。

入力欄に何か入力して送信ボタンを押すと、ウェブブラウザソフトは自動的に「query.cgi?value=入力した内容」という URL へと移動します。


つまり CGI プログラム側で $ENV{'QUERY_STRING'} を参照すれば、どのような値が入力されたのか取得できる、という事になります。QUERY_STRING には「abc=012&def=345&ghi=678」のような文字列が入るので、以下のようにすれば各パラメータの名前をキーにしたハッシュを生成する事ができるはずです。

my %param = map { /([^=]+)=(.+)/ } split /&/, $ENV{'QUERY_STRING'};

まず $ENV{'QUERY_STRING'} を & で split すると、「名前=値」のリストを得る事ができます。そのリストに対して名前と値をキャプチャする正規表現map すれば (名前, 値, 名前, 値, 名前, 値...) というリストが得られるので、それをそのままハッシュ変数へ代入しています。
これにより、$param{'value'} を見れば「value=ABC」の "ABC" の部分を得る事ができますね。(^_^)


確認の為に、こんな CGI を作ってみました。

#!/usr/local/bin/perl
use strict;

my %param = map { /([^=]+)=(.+)/ } split /&/, $ENV{'QUERY_STRING'};

my $value;
if (exists $param{'value'}) {
    $value = "あなたが入力したのは「$param{'value'}」です。";
} else {
    $value = "入力してください。";
}

print <<HTML;
Content-Type: text/html

<html>
<head><title>QUERY_STRING Test</title></head>
<body>
<h1>QUERY_STRING Test</h1>

<form action="$ENV{'SCRIPT_NAME'}" method="GET">
  <input type="text" name="value" />
  <input type="submit" value="送信" />
</form>
<p>$value</p>

</body>
</html>
HTML

__END__

さきほど例として書いたフォームを使って、自分自身($ENV{'SCRIPT_NAME'})へ入力した内容(value)を送信するようにしています。
パラメータとして value が渡されていれば、その値を表示します。
実行結果は、以下で見る事ができます。
query.cgi 実行結果
これで、利用者からの入力を受け取って処理した内容を表示するような、動的なページも作る事ができそうですね。できる事が拡がっていくのは、とても楽しいです。(^_^)

%ENV で HTTP リクエストの情報を調べる

特殊変数 %ENV には、スクリプトが動作しているコンピュータの「環境変数」が入っています。環境変数とは、OS の内部の設定などを設定/記録する為の変数で「名前=値」の組が集まっているものです。環境変数を調べる事でシステムの設定や情報を調べる事ができます。
%ENV の内容を調べるために、以下のスクリプトを実行してみました。

use strict;

while (my ($key, $value) = each %ENV) {
    print "$key=$value\n";
}

palmo の環境での実行結果は以下のようになりました。一部省略しています。

HOMEDRIVE=C:
CLIENTNAME=Console
COMMONPROGRAMFILES=C:\Program Files\Common Files
PROGRAMFILES=C:\Program Files
OS=Windows_NT
(中略)
TEMP=C:\DOCUME~1\palmo\LOCALS~1\Temp
PROCESSOR_REVISION=2701
SYSTEMDRIVE=C:
SYSTEMROOT=C:\WINDOWS
COMSPEC=C:\WINDOWS\system32\cmd.exe

環境変数を調べれば、システムで使われるファイルやフォルダ(ディレクトリ)のパスを調べたり、OS のバージョンを調べる事ができますね。(^_^)


CGI プログラムとして動かした場合、%ENV には環境変数に加えて「HTTP リクエスト」に関する情報も入っています。サイトの利用者が、ページを取得するためにサーバーに送ってくる要求を「リクエスト」と呼びますが、リクエストには「ヘッダー」と呼ばれる「名前: 値」形式のパラメータが付属しています。
例えば Mozilla Firefox 1.5 でこの「ぱるも日記」のトップページ http://d.hatena.ne.jp/palmo/ を要求する際の HTTP リクエストは、以下のようになります。(LiveHTTPHeaders エクステンションを利用しました)

GET /palmo/ HTTP/1.1
Host: d.hatena.ne.jp
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.0.4) Gecko/20060508 Firefox/1.5.0.4
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

%ENV には、この「ヘッダー」が入っています。各パラメータの名前には、頭に「HTTP_」が付き、全て大文字になって、「-」(ハイフン)が「_」(アンダーバー)に置き換えられた名前が使われます。例えば、上の「User-Agent」の値は $ENV{'HTTP_USER_AGENT'} に入っています。
また、リクエストの一番最初の行の情報は、頭に「REQUEST_」がついた名前で表されています。サーバーに要求する操作(メソッド)を表す「GET」は $ENV{'REQUEST_METHOD'} に、要求されているページのアドレス「/palmo/」は $ENV{'REQUEST_URI'} に入っています。
他にも、%ENV には CGI スクリプト自身のパスを表す SCRIPT_NAME や、サーバーに関する情報など、CGI の処理に便利な情報が入っています。


確認の為に %ENV の内容を表示する CGI を作りました。

#!/usr/local/bin/perl
use strict;

my $rows = "";
for my $key (sort keys %ENV) {
    $rows .= "<tr><th>$key</th><td>$ENV{$key}</td></tr>\n";
}

print <<HTML;
Content-Type: text/html

<html>
<head><title>ENV Values</title></head>
<style type="text/css">
th, td { font-size: 90%; padding: 0.2em 0.5em; border-bottom: 1px #C00 solid; }
th { text-align: left; background-color: #FCC; border-right: 1px #C00 solid; }
</style>
<body>
<table>$rows</table>
</body>
</html>
HTML

__END__

実行結果は下のページで見ることができます。
envtitle.cgi 実行結果
リクエストヘッダーやサーバーの情報などが確認できるはずです。普段は目に見えませんが、色々な情報が送られているんですね。(^_^)