入力フォーム編(GETとPOSTデータを受け取るには)

  1. はじめに
  2. GET と POST
  3. GET METHOD でのデータの受け方
  4. POST METHOD でのデータの受け方
  5. GET と POSTの区別の方法
  6. Perlスクリプト上での実装

 CGIを作成する上で、テキストボックスやラジオボタンなどのフォームに入力、選択された状態を取り込むことは避けてとおれません。ここでは、入力フォームのデータをどのようにCGIで取り込むのかを紹介します。その前に、GETとPOSTについて説明します。

 入力データをCGIに引き渡す方法(METHOD)として、「GET」と「POST」があります。このMETHODの指定は、入力フォーム(HTML)上で、<INPUT>タグ内で指定します。

GET METHODは、HTTP/0.9から規定されており、データをサーバに送る手段として、当時においては唯一の手段でした。ただ、255文字分しか有効にならないという制限がありました。しかも、URLエンコード(後述)した状態で255文字までですので、複雑なフォームを送信しようとするには限界がありました。

これを改善するかのように、最大有効文字数という制限がない POST という手段が規定されました。ただ、リクエスト時のHTTPヘッダーに、Content-Lengthヘッダーを含める必要があります。通常、ブラウザーでの実装となりますので、データを受け取る側のCGIでは考慮する必要はありません。ただ、CGIからHTTPリクエストを送出する場合には、考慮しなければいけません。

GET METHODでは、データを、リクエストURLの後ろに付け加える形で送信されます。この場合、環境変数 QUERY_STRING に収められます。CGIでは、$ENV{'QUERY_STRING'} からデータを取得します。以下の例を使って開設します。

<form action="http://www.futomi.com/lecture/form/exec/gettest.cgi" method="get">
<p>お名前:<input type="text" name="namae" value="太郎" size="20" /></p>
<p>OS:
<input type="radio" name="OS" value="win" checked="checked" /> Windows
<input type="radio" name="OS" value="mac" /> Machintosh
<input type="radio" name="OS" value="unix" /> Unix
</p>
<p><input type="submit" name="submit" value="送信" /></p>
</form>

お名前:

OS: Windows Machintosh Unix

上の例で、送信ボタンを押すと、$ENV{'QUERY_STRING'} の値をそのまま表示します。ここで注意してみてほしいのが、ブラウザーのアドレス欄に表示されているURLです。以下のとおりになっているはずです。

http://www.futomi.com/lecture/form/exec/test.cgi?namae=%91%BE%98Y&OS=win&submit=%91%97%90M

送信データが、URLの一部として送信されたわけです。送信データとURLは、「?」で区切られます。

CGIのURL http://www.futomi.com/lecture/form/exec/test.cgi
送信データ namae=%91%BE%98Y&OS=win&submit=%91%97%90M

送信データの部分が、$ENV{'QUERY_STRING'} に格納されます。

送信データは、各入力項目ごとに「&」で区切られます。例では、「お名前」と「OS」の質問にあたります。加えて、送信ボタンのデータも送られます。

お名前 namae=%91%BE%98Y
OS OS=win
送信ボタン submit=%91%97%90M

それぞれの質問項目は、<input>タグで指定したnameと入力値(value)とを「=」で区切ります。そこで「お名前」の値は「太郎」のはずなにの「%91%BE%98Y」となっています。これはブラウザーがデータを送信する際に、URLエンコーディングをしているからです。同様に「送信ボタン」の値「送信」もURLエンコーディングされています。

GET METHODで送信されたデータをCGIで受け取るには、$ENV{'QUERY_STRING'} の値を、上で説明したように分解する必要があります。加えて、URLエンコーディングされた値をデコードする必要があります。

POST METHODで送られるデータは、GETのようにURLとして送信されるわけではありません。したがって、$ENV{'QUERY_STRING'} から受け取ることができません。POSTで送信した場合、$ENV{'QUERY_STRING'} には何も入ってきません。

その代わり、CGIは、サーバから stdin (標準入力)経由で送信データを受け取ります。Perlスクリプト上では、以下の記述で取得します。

read (STDIN, $PostData, $ENV{'CONTENT_LENGTH'});

上の例では、スカラー変数 $PostData に、送信データが格納されます。$ENV{'CONTENT_LENGTH'} は、ブラウザーからのリクエストヘッダーにあるContent長(バイト)です。

以下の例を使って説明します。

<form action="http://www.futomi.com/lecture/form/exec/posttest.cgi" method="post">
<p>お名前:<input type="text" name="namae" value="太郎" size="20" />
</p>
<p>OS:
<input type="radio" name="OS" value="win" checked="checked" /> Windows
<input type="radio" name="OS" value="mac" /> Machintosh
<input type="radio" name="OS" value="unix" /> Unix
</p>
<p><input type="submit" name="submit" value="送信" /></p>
</form>

お名前:

OS: Windows Machintosh Unix

スカラー変数 $PostData には、

namae=%91%BE%98Y&OS=win&submit=%91%97%90M

が格納されます。これは、GETメソッドの時の $ENV{'QUERY_STRING'} に格納されるデータと同じです。以降の文字列の分解については、GETメソッドの場合と同様です。

GET と POST でのデータの受け取り方の違いがあることはご説明した通りですが、もし、

な場合には、どうすればいいのでしょうか。

CGI側で、リクエストがGET なのか POST なのかを区別しなければいけません。これは非常に簡単に区別できます。

環境変数 REQUEST_METHOD から区別することができます。Perlスクリプト上では、$ENV{'REQUEST_METHOD'} の値を見ることで実現できます。この値は、以下の通りです。

メソッド $ENV{'REQUEST_METHOD'} の値
GET GET
POST POST

この値を見て、Perlスクリプト上で場合わけをすればいいのです。

これまで GET と POST でのデータの受け取り方を説明しましたが、Perlスクリプト上でどのようなコードを書けばいいのでしょう。これまで説明した送信データの分解をするように作ればいいのですが、すでに優秀な Perlモジュール や ライブラリー があります。これらを使ってデータを取得することをお勧めします。

Perlモジュールとしては、「cgi.pm」が有名です。Perl5では標準に組み込まれているモジュールですので、ほとんどのプロバイダーで利用することができます。futomi's CGI Cafe で公開しているフリーCGIも「cgi.pm」を使っております。

futomi's CGI Cafe でもこれらの使い方を掲載しておりますので、ご覧下さい。