Perl CGI プログラミング



CGIとは

CGIは現在NCSAによって管理されています。NCSAはCGIを次のように定義しています:

CGI (Common Gateway Interface)、共通ゲートウェイインターフェース、HTTPサーバーなどのサーバー上で実行されるプログラムです。同じクライアント HTML ページ インターフェイス。


Web ブラウズ

CGI の仕組みをよりよく理解するには、Web ページ上のリンクまたは URL をクリックするプロセスから始めます。

  • 1. ブラウザを使用して URL にアクセスし、HTTP Web に接続します。サーバ。

  • 2. リクエスト情報を受信した後、Web サーバーは URL を解析し、アクセスされたファイルがサーバー上に存在するかどうかを確認します。ファイルが存在する場合は、ファイルの内容を返します。存在しない場合は、エラー メッセージが返されます。 。

  • 3. ブラウザはサーバーから情報を受信し、受信したファイルやエラーメッセージを表示します。

CGI プログラムは、Python スクリプト、PERL スクリプト、SHELL スクリプト、C または C++ プログラムなどです。


CGI アーキテクチャ図

cgiarch


Web サーバーのサポートと構成

CGI プログラミングを実行する前に、Web サーバーが CGI をサポートし、CGI ハンドラーが構成されていることを確認してください。

Apache は CGI 構成をサポートします:

CGI ディレクトリをセットアップします:

ScriptAlias /cgi-bin/ /var/www/cgi-bin/

すべての HTTP サーバー実行 CGI プログラムは、事前に構成されたディレクトリに保存されます。このディレクトリは CGI ディレクトリと呼ばれ、慣例により /var/www/cgi-bin という名前が付けられます。

CGI ファイルの拡張子は .cgi ですが、Perl では拡張子 .pl も使用できます。

デフォルトでは、Linux サーバーが実行するように設定されている cgi-bin ディレクトリは /var/www です。

CGI スクリプトを実行する他のディレクトリを指定したい場合は、httpd.conf 設定ファイルを次のように変更できます:

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options +ExecCGI
   Order allow,deny
   Allow from all
</Directory>

AddHandler に .pl サフィックスを追加して、.pl で終わる Perl スクリプト ファイルにアクセスできるようにします。

AddHandler cgi-script .cgi .pl .py

最初の CGI プログラム

ここで、test.cgi ファイルを作成します。コードは次のとおりです。

#!/usr/bin/perl

print "Content-type:text/html\r\n\r\n";
print '<html>';
print '<head>';
print '<meta charset="utf-8">';
print '<title>php中文网(php.cn)</title>';
print '</head>';
print '<body>';
print '<h2>Hello Word! </h2>';
print '<p>来自php中文网第一个 CGI 程序。</p>';
print '</body>';
print '</html>';

1;

次に、ブラウザーで http://localhost/cgi-bin/test.cgi を開きます。出力結果は次のようになります。次のように:

スクリプト「Content-type: text/htmlrnrn」の最初の行の出力コンテンツがブラウザに送信され、表示されるコンテンツ タイプが「text/html」であることがブラウザに伝えられます。


HTTP ヘッダー

test.cgi ファイルのコンテンツ内の「Content-type: text/html」は HTTP ヘッダーの一部であり、ファイルのコンテンツ タイプをブラウザーに伝えるためにブラウザーに送信されます。

HTTP ヘッダーの形式は次のとおりです:

HTTP 字段名: 字段内容

例:

Content-type:text/html\r\n\r\n

次の表は、CGI プログラムの HTTP ヘッダーで一般的に使用される情報を示しています。

HeaderDescription
Content-type:エンティティに対応する要求された MIME 情報。例: Content-type: text/html
Expires: Date応答の有効期限が切れる日時
Location: URL受信者をリクエストされていない URL の場所にリダイレクトするために使用されます。リクエストを完了するか、新しいリソースを特定します
Last-modified: Dateリクエストされたリソースの最終変更時刻
Content-length: Nリクエストされたコンテンツの長さ
Set-Cookie: String HTTP Cookie を設定する

CGI 環境変数

すべての CGI プログラムは、CGI プログラムで重要な役割を果たす次の環境変数を受け取ります:

SERVER_SOFTWARE

以下は、CGI 環境変数を出力する単純な CGI スクリプトです:

#!/usr/bin/perl

print "Content-type: text/html\n\n";
print '<meta charset="utf-8">';
print "<font size=+1>环境变量:</font>\n";
foreach (sort keys %ENV)
{
  print "<b>$_</b>: $ENV{$_}<br>\n";
}

1;

ファイルのダウンロード

Perl CGI を介してファイルのダウンロードを実装したい場合は、以下に示すように、異なるヘッダー情報を設定する必要があります:

#!/usr/bin/perl

# HTTP Header
print "Content-Type:application/octet-stream; name=\"FileName\"\r\n";
print "Content-Disposition: attachment; filename=\"FileName\"\r\n\n";

# Actual File Content will go hear.
open( FILE, "<FileName" );
while(read(FILE, $buffer, 100) )
{
   print("$buffer");
}

Use GET メソッドはデータを送信します

GET メソッドは、以下に示すように、エンコードされたユーザー情報をリクエスト ページの URL に「?」で区切って含めて送信します。

http://www.test.com/cgi-bin/test.cgi?key1=value1&key2=value2
GET リクエストに関するその他の注意事項:
  • GET リクエストはキャッシュ可能

  • GET リクエストはブラウザ履歴に残る

  • GET リクエストはブックマーク可能

  • GET リクエストは機密データを扱う場合には使用しないでください

  • GET リクエストはあります長さ制限があります

  • GET リクエストはデータを取得するためにのみ使用してください

簡単な URL の例: GET メソッド

以下は、GET メソッドを使用して 2 つのパラメーターを test.cgi プログラムに送信する簡単な URL です。

/cgi-bin/test.cgi?name=php中文网&url=http://www.php.cn

以下はtest.cgiファイルのコードです:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取文本信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "GET")
{
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex())/eg;
   $FORM{$name} = $value;
}
$name = $FORM{name};
$url  = $FORM{url};

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2>$name网址:$url</h2>";
print "</body>";
print "</html>";

1;

ブラウザで見ると出力結果は以下の通りです:

簡単なフォームの例: GETメソッド

以下はHTMLを介したフォームです。 GET メソッドを使用して 2 つのメッセージをサーバー データに送信します。送信されたサーバー スクリプトも test.cgi ファイルであり、test.html コードは次のとおりです:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="get">
站点名称: <input type="text" name="name">  <br />

站点 URL: <input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>

ブラウザでの実行効果は次のとおりです:


POST メソッドを使用してデータを転送します

POST メソッドを使用して、サーバーがデータを送信する方が安全で信頼性が高くなります。ユーザー パスワードなどの一部の機密情報は、データの送信に POST を使用する必要があります。

以下も test.cgi で、ブラウザから送信された POST フォーム データも処理できます:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取文本信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else {
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex())/eg;
   $FORM{$name} = $value;
}
$name = $FORM{name};
$url  = $FORM{url};

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2>$name网址:$url</h2>";
print "</body>";
print "</html>";

1;

以下は、HTML を使用して GET メソッドを使用して 2 つのデータをサーバーに送信するフォームです。送信されたサーバー スクリプトも同様です。 test.cgi ファイル、test.html コードは次のとおりです:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="post">
站点名称: <input type="text" name="name">  <br />

站点 URL: <input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>

ブラウザでの実行効果は次のとおりです:

CGI プログラムを通じてチェックボックス データを転送します

チェックボックスは 1 つ以上のオプション データを送信するために使用されますtest.html コードは次のとおりです:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="POST" target="_blank">
<input type="checkbox" name="php" value="on" /> php中文网
<input type="checkbox" name="google" value="on" /> Google
<input type="submit" value="选择站点" />
</form>
</body>
</html>

以下は test.cgi ファイルのコードです:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else {
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex())/eg;
   $FORM{$name} = $value;
}
if( $FORM{php} ){
   $php_flag ="ON";
}else{
   $php_flag ="OFF";
}
if( $FORM{google} ){
   $google_flag ="ON";
}else{
   $google_flag ="OFF";
}

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2> php中文网选中状态 : $php_flag</h2>";
print "<h2> Google 选择状态 : $google_flag</h2>";
print "</body>";
print "</html>";

1;

ブラウザでの実行効果は次のとおりです:


を介して無線データを送信するCGI プログラム

ラジオは 1 つのデータのみをサーバーに配信します。test.html コードは次のとおりです:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="post" target="_blank">
<input type="radio" name="site" value="php" /> php中文网
<input type="radio" name="site" value="google" /> Google
<input type="submit" value="提交" />
</form>
</body>
</html>

test.cgi スクリプト コードは次のとおりです:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else {
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex())/eg;
   $FORM{$name} = $value;
}
$site = $FORM{site};

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2> 选择的网站 $site</h2>";
print "</body>";
print "</html>";

1;

ブラウザでの実行効果は次のとおりです:


CGIプログラムを通じてTextareaデータを送信します

Textareaは複数行のデータをサーバーに転送します。test.htmlコードは次のとおりです:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="post" target="_blank">
<textarea name="textcontent" cols="40" rows="4">
在这里输入内容...
</textarea>
<input type="submit" value="提交" />
</form>
</body>
</html>

test.cgiスクリプトコードは次のとおりです:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else {
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex())/eg;
   $FORM{$name} = $value;
}
$text_content = $FORM{textcontent};

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2>输入的文本内容为:$text_content</h2>";
print "</body>";
print "</html>";

1;

ブラウザ内、実行効果は次のとおりです:


CGI プログラムを通じてドロップダウン データを転送します

HTML ドロップダウン ボックスのコードは次のとおりです:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>php中文网(php.cn)</title>
</head>
<body>
<form action="/cgi-bin/test.cgi" method="post" target="_blank">
<select name="dropdown">
<option value="php" selected>php中文网</option>
<option value="google">Google</option>
</select>
<input type="submit" value="提交"/>
</form>
</body>
</html>

test.cgi スクリプト コードは次のとおりです:

#!/usr/bin/perl

local ($buffer, @pairs, $pair, $name, $value, %FORM);
# 读取信息
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}else {
   $buffer = $ENV{'QUERY_STRING'};
}
# 读取 name/value 对信息
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
   ($name, $value) = split(/=/, $pair);
   $value =~ tr/+/ /;
   $value =~ s/%(..)/pack("C", hex())/eg;
   $FORM{$name} = $value;
}
$site = $FORM{dropdown};

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print '<meta charset="utf-8">';
print '<title>php中文网(php.cn)</title>';
print "</head>";
print "<body>";
print "<h2>选择的网站是:$site</h2>";
print "</body>";
print "</html>";

1;

ブラウザでの実行効果は次のとおりです:


CGI での Cookie の使用

http プロトコルの大きな欠点は、ユーザーの身元を判断しないことです。これはプログラマーにとって非常に不便です。 この欠点を補うのがCookie機能の登場です。

Cookieとは、お客様がスクリプトにアクセスした際に、お客様のブラウザを通じてお客様のハードディスクに記録データを書き込むものです。 、次回お客様がスクリプトにアクセスしたときにデータ情報が取得され、本人確認機能を実現するために Cookie がよく使用されます。

Cookie 構文

http Cookie は、ファイル転送よりも先に http ヘッダーを通じて送信されます。ヘッダー内の set-cookie の構文は次のとおりです:

Set-cookie:name=name;expires=date;path=path;domain=domain;secure
  • name=name: Cookie は次のとおりです。値を設定します (名前には「;」と「,」は使用できません)。複数の名前の値がある場合は、「;」を使用して区切ります。例: name1=name1;name2=name2;name3 =名前3

  • expires=date: Cookieの有効期間、形式:expires="Wdy,DD-Mon-YYYY HH:MM:SS"


  • path=path: Cookieの設定 サポートされていますpath がパスの場合、Cookie はこのディレクトリ内のすべてのファイルとサブディレクトリに対して有効になります。たとえば、path="/cgi-bin/" です。 path がファイルの場合、Cookie はこのファイルに対して有効になります。例: path="/cgi-bin/cookie.cgi"。

  • domain=domain: Cookie に有効なドメイン名。たとえば、domain="www.php.cn"

  • secure: このフラグが指定されている場合、それは、 Cookie は SSL プロトコル サーバーの https を通過してのみ配信できます。

  • Cookie の受信は環境変数 HTTP_COOKIE を設定することで実現され、CGI プログラムはこの変数を取得することで Cookie 情報を取得できます。


Cookieの設定

Cookieの設定は非常に簡単で、Cookieはhttpヘッダーで個別に送信されます。次の例では、Cookie にユーザー ID、パスワード、有効期限を設定します。

#!/usr/bin/perl

print "Set-Cookie:UserID=XYZ;\n";
print "Set-Cookie:Password=XYZ123;\n";
print "Set-Cookie:Expires=Tuesday, 31-Dec-2017 23:12:40 GMT";\n";
print "Set-Cookie:Domain=www.php.cn;\n";
print "Set-Cookie:Path=/perl;\n";
print "Content-type:text/html\r\n\r\n";
...........其他 HTML 内容

Cookie の検索

Cookie 情報の取得ページは非常に簡単で、CGI 環境変数 HTTP_COOKIE に格納されます。 出力は次のとおりです。上記の例の結果は次のようになります: :

#!/usr/bin/perl
$rcvd_cookies = $ENV{'HTTP_COOKIE'};
@cookies = split /;/, $rcvd_cookies;
foreach $cookie ( @cookies ){
   ($key, $val) = split(/=/, $cookie); # splits on the first =.
   $key =~ s/^\s+//;
   $val =~ s/^\s+//;
   $key =~ s/\s+$//;
   $val =~ s/\s+$//;
   if( $key eq "UserID" ){
      $user_id = $val;
   }elsif($key eq "Password"){
      $password = $val;
   }
}
print "User ID  = $user_id\n";
print "Password = $password\n";

CGI module

Perl には多くの組み込み CGI モジュールが用意されており、次の 2 つが一般的に使用されます:

変数名説明
コンテンツタイプ この環境変数の値は、渡される情報の MIME タイプを示します。現在、環境変数 CONTENT_TYPE は通常、application/x-www-form-urlencoded であり、データが HTML フォームから取得されることを示します。
CONTENT_LENGTHサーバーとCGIプログラム間の情報伝達方式がPOSTの場合、この環境変数は標準入力STDINから読み取れる有効なデータのバイト数になります。この環境変数は、入力されたデータを読み取るときに使用する必要があります。クライアント内の
HTTP_COOKIECOOKIEコンテンツ。
HTTP_USER_AGENTバージョン番号やその他の独自データを含む顧客のブラウザ情報を提供します。
PATH_INFO この環境変数の値は、CGI プログラム名の直後の他のパス情報を表します。多くの場合、CGI プログラムのパラメータとして表示されます。
QUERY_STRINGサーバーとCGIプログラム間の情報転送方式がGETの場合、この環境変数の値が転送される情報となります。この情報は、CGI プログラム名の後に疑問符「?」で区切って続きます。
REMOTE_ADDR この環境変数の値は、リクエストを送信するクライアントの IP アドレス (上記の 192.168.1.67 など) です。この値は常に存在します。これは、Web クライアントが Web サーバーに提供する必要がある一意の識別子であり、CGI プログラムでさまざまな Web クライアントを区別するために使用できます。
REMOTE_HOST この環境変数の値には、CGI リクエストを送信したクライアントのホスト名が含まれます。クエリしたいクエリがサポートされていない場合、この環境変数を定義する必要はありません。
REQUEST_METHOD スクリプトを呼び出すメソッドを提供します。 HTTP/1.0 プロトコルを使用するスクリプトの場合、GET と POST のみが意味を持ちます。
script_fileNameCCGIスクリプトのフルパスcgiスクリプトの名前の名前は、Webサーバーのホスト名、エイリアス、またはIPアドレスです。
この環境変数の値には、CGI プログラムを呼び出す HTTP サーバーの名前とバージョン番号が含まれます。たとえば、上記の値は Apache/2.2.14(Unix) です