最終更新日:2000年 6月 4日(日)

HTTP( Hyper Text Transfer Protocol )


ここでは、 CGI の基礎知識の1つであるサーバ変数に関する、 あれやこれやを採り挙げます


まずはおさらい
以下の項目はリクエストではなく全てのリクエストのために設定される変数
SERVER_SOFTWARE サーバのソフトウェア名とバージョン
SERVER_NAME サーバ名又は IPアドレス
GATEWAY_INTERFACEサーバが使用する CGI のリビジョン
SERVER_PROTOCOLプロトコル名とリビジョン
SERVER_PORT ポート番号
以下の項目は Webゲートウェイ が設定するリクエストのための変数
REQUEST_METHOD メソッド
PATH_INFO 要求されたパス情報
PATH_TRANSLATEDPATH_INFOの変換結果
SCRIPT_NAME 実行しているスクリプト名
DOCUMENT_ROOT ドキュメントのルートディレクトリ
QUERY_STRING CGI に対するクエリー
REMOTE_HOST 要求元のホスト名
REMOTE_ADDR 要求元の IPアドレス
AUTH_TYPE ユーザ認証時の認証メソッド
REMOTE_USER ユーザ認証時の認証名
REMOTE_IDENT 要求元のユーザ識別
CONTENT_TYPE データの MIME タイプ
CONTENT_LENGTH データ長
以下の項目はクライアントからの送信ヘッダに基づく変数
HTTP_ACCEPT クライアントが解釈できる MIMEタイプのリスト
HTTP_USER_AGENTクライアント側のブラウザ
HTTP_REFERER この CGI の参照元ドキュメント


SERVER_PROTOCOL
この変数は通常使用しませんが、 Windowsで Personal/Peer Web Server や Internet Information Server で、 Perlis.dll を使用してサーバスレッドで Perl を CGI として実行する場合に利用します。

if($ENV{'PERLXS'} eq 'PerlIS'){ print $ENV{'SERVER_PROTOCOL'}?$ENV{'SERVER_PROTOCOL'}:'HTTP/1.0',*1 " 200 OK\n"; }
PWS や IIS でサーバスレッドで Perl を実行すると、 本来サーバが応答すべき HTTP ヘッダを送出しないため、 ブラウザ側が異常動作します。 これを防ぐために、このような条件の( つまり、 $ENV{'PERLXS'} が 'PerlIS' である ) 場合にはスクリプト側で応答ヘッダを送出します。

*1
環境変数ではなく「HTTP/1.0」の固定文字列を利用しても 特に実害はでないと思います。

SERVER_NAME
SERVER_PORT
これらの変数はサーバやポートに依存しないようにスクリプトを記述する場合に 使用されます。

print <<END_OF_LINK; : <a href="http://${ENV{'SERVER_NAME'}}:${ENV{'SERVER_PORT'}}/..."> : END_OF_LINK
*1
でも、こんな表記する必要は実際にはないと思います。

SCRIPT_NAME
この変数はパスやスクリプト名に依存しないようにスクリプトを記述する場合に使用されます。

print <<END_OF_FORM; <form class="an" name="f" method="GET" action="${ENV{'SCRIPT_NAME'}}> : </form> END_OF_FORM
*1
CGI が複数のスクリプトから構成され HTML を介して互いに呼び出し合う場合は、 いくら自分のスクリプト名がわかったとしても意味がありませんが... f(^^;
*2
SCRIPT_NAMEは絶対パスの URL 表記なので、 スクリプトのネストが深い場所にあり、出力する HTML にたくさん記述されると、 出力するデータ長も大きくなるので、結局スクリプト内で変数にでもしておいた方が いいかも... f(^^;

逆に、自分自身が nph スクリプトかどうかを識別するのにも利用できます。

my ($script_name)=$ENV{'SCRIPT_NAME'}=~/([^\/]+)$/; if($script_name=~/^nph-/i){ # NPH スクリプト } else { # 通常のスクリプト }

REQUEST_METHOD
QUERY_STRING
CONTENT_TYPE
CONTENT_LENGTH
これらの変数の用途は有名なので説明は省略。 利用する場合は簡単な場合を除き、 cgi-lib.pl や CGI_Lite.pm を利用するのが常道でしょう。
REQUESTY_METHODの HEAD は CGI に渡ってくるのでしょうか?
ただ、 CGI に対してデータを設定する場合には、 コマンドラインでデバッグするための仕組みを入れておくと良いでしょう。

my ($mailaddr, $name); if(defined $ENV{'REQUEST_METHOD'}){ require 'cgi-lib.pl'; # cgi-lib.pl の場合 my %params; &ReadParse(\%params); $mailaddr=$params{'mailaddr'}; $name =$params{'name'}; : } else { # 形式: perl script.cgi -m mail_addr -n name my $i; for($i=0; $i<@ARGV; $i++){ $mailaddr=$ARGV[++$i] if($ARG[$i] eq '-m'); $name =$ARGV[++$i] if($ARG[$i] eq '-n'); : } }

REMOTE_HOST
REMOTE_ADDR
これらの変数はアクセスログの収集データとして利用されることが多いです。 ただ、REMOTE_HOSTは必ずしもサーバ名ではなく IP アドレスの場合もあります。 IP アドレスの場合は以下のようにして名称解決できる場合があります。

my $host=$ENV{'REMOTE_HOST'}; my $addr=$ENV{'REMOTE_ADDR'}; if(defined $host && $host eq $addr){ $host=gethostbyaddr(pack('C4',split(/\./,$addr)),2) || $addr; }

HTTP_USER_AGENT
この変数はアクセスしてきたブラウザの種別を識別するために使用することが多いです。

my $agent=$ENV{'HTTP_USER_AGENT'}; if (!defined $agent || $agent eq ''){*1 # 設定なし } elsif($agent=~/^Mozilla.*MSIE/i || $agent=~/エクスプロ/*2){ # Microsoft Internet Explorer if ($agent=~/Windows 3.1([;\)].*){0,1}$/i) { # windows 3.1 } elsif($agent=~/ Win32([;\)].*){0,1}$/i) { # Windows3.1 32bit } elsif($agent=~/ Windows 95([;\)].*){0,1}$/i) { # Windows95 } elsif($agent=~/ Windows 98([;\)].*){0,1}$/i) { # Windows98 } elsif($agent=~/ Windows NT( 4.0){0,1}([;\)].*){0,1}$/i){ # WindowsNT 4.0 } elsif($agent=~/ Windows NT(( 5.0)|(5.0b))([;\)].*){0,1}$/i){ # Windows 2000 } elsif($agent=~/ Win2000pro([;\)].*){0,1}$/i) { # Windows 2000 } elsif($agent=~/ Mac_PowerPC([;\)].*){0,1}$/i){ # Mac PowerPC } elsif($agent=~/ Mac_PPC([;\)].*){0,1}$/i) { # Mac PowerPC } else { # その他 } } elsif( $agent=~/^Mozilla/i && !($agent=~/\(compatible;/i ) && !($agent=~/\(NetFront/i) && !($agent=~/AVE-Front/i) && !($agent=~/DreamPassport/i) && !($agent=~/Getweb/i) && !($agent=~/IBM Link Browser/i) && !($agent=~/IBM HomePage Builder/i) && !($agent=~/Opera/i) && !($agent=~/PlayStation/i) && !($agent=~/PNWalker/i ) && !($agent=~/WebWhacker/i )){*3 # Netscape Navigator if ($agent=~/\(Win16;/i) { # Windows 3.1 } elsif($agent=~/\(Win95;/i) { # Windows95 } elsif($agent=~/\(Windows; .*; Win95;/io) { # Windows95 } elsif($agent=~/\(Windows[_]*95;/io) { # Windows95 } elsif($agent=~/[\( ]Win98;/i) { # Windows98 } elsif($agent=~/\(Windows_98;/i) { # Windows98 } elsif($agent=~/\(WinNT;/i) { # WindowsNT } elsif($agent=~/\(Windows; .*; WinNT[0-9\.]+;/io){ # WindowsNT } elsif($agent=~/ NT[0-9\.]+;/i) { # WindowsNT } elsif($agent=~/\(Windows_NT;/i) { # WindowsNT } elsif($agent=~/[\( ]Windows NT [0-9\.]+;/i) { # WindowsNT } elsif($agent=~/\(Win2001;/i) { # Windows 2000 } elsif($agent=~/\(Macintosh;.*68K/i) { # Mac 68K } elsif($agent=~/\(Macintosh;.* PPC/i) { # Mac PowerPC } elsif($agent=~/\(Macintosh;.* PowerPC/i) { # Mac PowerPC } elsif($agent=~/ SunOS /i) { # Sun Solaris } elsif($agent=~/ Linux /i) { # Linux } elsif($agent=~/ FreeBSD /i) { # FreeBSD } elsif($agent=~/ AIX /i) { # AIX } elsif($agent=~/ IRIX/i) { # IRIX } elsif($agent=~/ HP-UX /i) { # HP } elsif($agent=~/ OSF1 /i) { # OSF1 } elsif($agent=~/\(OS\/2;/i) { # OS/2 } else { # その他*4 } } else { # MSIE,Netscape Navigator 以外*5 }
*1
HTTP_USER_AGENTはクライアント側(つまり、多くはブラウザ) が設定する情報なので、必ずしも設定されていないことに注意します。
*2
ブラウザの中には漢字が設定されている行儀の悪いブラウザもいます。 この場合、実際にはHTTP_USER_AGENTの値を実行環境の文字コードに 変換する必要があります。
*3
Netscape Navigator の判別は、他のクライアントが詐称していることが多いので、 その判定(完全ではありません)をするため若干複雑になっています。
*4
Netscape Navigator の「その他」はひょっとすると ダウンローダや他のブラウザの可能性があります。
*5
その他のクライアントやクライアントのバージョンチェックなどに関しては、 BrowserWatch! を参考にしてみて下さい。f(^^;

HTTP_REFERER
この変数はアクセスログを取る場合アクセスデータとして収集されることが多いです。

my $referer=$ENV{'HTTP_REFERER'};*1 if(defined $referer && $referer ne ''){ $referer=~s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;*2 $referer=~s/[\n\r]/ /g;*3 }
*1
HTTP_REFERERを JavaScript 等を使用して CGI に渡す場合、 ブラウザによってはウソをつきます。 ( 例えば、IE3 は自分自身の URL ですし、 IE4 は時々参照元でない URL が設定されます ) HTTP_REFERER自体は未調査です。
HTTP_REFERERに設定される値はブラウザ依存なので様々な形式があると思われます。 詳細には調査していないので不明ですが、JavaScript で同様の情報を収集した結果、 以下の形式があります。
No形式備考
1http:/...インターネット上のファイルから参照
URL の形式は間違っていてもブラウザが補完する場合があります。
2file:...ローカルファイルから参照
3bookmarksMac版ネスケ 4.06以降でブックマークから参照
4mailbox:/...ネスケでメールから参照
5IMAP:...ネスケでメールから参照
6about:<URL>ネスケでキャッシュ情報から参照
7wysiwyg://link.msg.<nn>/<URL>ネスケでキャッシュから参照?
8[unknown origin]ネスケ 4.7 でブックマークから参照
*2
URL encode されたデータがあればデコードします。
*3
通常は必要ないのですが、参照元がローカルファイルである場合、 日本語や改行コードが含まれる可能性があります。 ( 日本語に関しては必要とする文字コードに変換する必要があります )


戻る Copyright(c) 1999-2000 ShinSoft. All rights reserved. メール