解説 11月(1)

今回の学習項目です。


値を受け取るCGIのプログラム

これまで扱ってきたCGIのプログラムは、占いのページのようにランダムにページの内容を変化させたり、アクセスカウンターのようにサーバー内部のファイルの状態によってページの内容を変化させるものでした。

しかし、バスの時刻を表示するページは、ユーザーが時刻を選択することによって、表示するバスの発車時刻を変えることができました。 CGIのプログラムの大半は、このように外部から(ブラウザから)の値を受け取り、その値に応じてページの内容を変更するように作られます。 実際に、掲示板やブログ、オンラインショッピングサイトやSNS(ソーシャル・ネットワーキング・サービス)など、多くのWebサービスがこの仕組みを利用して作られています。

今回はそのような、外部からの入力を受け取ることのできるCGIプログラムの基本を勉強しましょう。

課題1

今回の課題1の最終目標は、次のような、受け取った名前をページに表示するCGIプログラムを作成することです。

受け取った名前を表示するCGIプログラム

課題1-1-1

まず、CGIプログラムに値を渡す方法を理解しておきましょう。
次のURLのCGIプログラムは、名字と名前の値を受け取り、「こんにちは、○○ ××さん。」とページに表示します。 まず、値を渡さずに、ページをそのまま表示してみましょう。 次のURLをコピーしてブラウザのアドレスバーに入力し、ページを表示してください。

http://nausicaa.cyber.sist.chukyo-u.ac.jp/cgi-bin/helloMr.cgi

名字と名前の値を渡さなかったので、「こんにちは、 さん。」と表示されてしまったはずです。 このプログラムに値を渡すためには、URLのファイル名の後ろに、次のようにパラメータを付け加える必要があります。

http://nausicaa.cyber.sist.chukyo-u.ac.jp/ ...(中略)... /helloMr.cgi?sei=Sirai&mei=Hidetosi

上のURLの ? 以降の部分がパラメータです。 ? の後ろに、パラメータ名と値を = で結んで書きます。 パラメータが複数ある場合は & で区切って書いていきます。

helloMr.cgiは、seiとmeiという2つのパラメータを受け取り、名字と名前の値としてページに表示するように作られています。 つまり、上の例では、helloMr.cgiに "Sirai" という名字の値と、"Hidetosi" という名前の値を渡していることになります。

上のCGIのページに自分の名字と名前を表示させるには、どのようなURLにアクセスすればよいか答えなさい。 実際にそのURLをブラウザのアドレスバーに入力し、自分の氏名がページに表示されるか確認すること。 (アドレスバーには半角英字で氏名を入力してください。日本語を入力すると正しく表示されないことがあります。)

課題1-1-2

今度はCGIプログラムがパラメータを受け取る仕組みについて理解しましょう。 パラメータを受け取る機能は、Rubyに用意されているCGIクラスによって提供されます。 使用する前に、CGIクラスをプログラムに読み込んでおく必要があります。

require "cgi"    #CGIクラスを読み込む。

cgi = CGI.new    #CGIクラスのインスタンスオブジェクトを生成。
                 #(このときパラメータが受け取られる。)
変数1 = cgi["パラメータ名1"]  #生成したCGIオブジェクトからパラメータの値を取得。
変数2 = cgi["パラメータ名2"]  #生成したCGIオブジェクトからパラメータの値を取得。
変数3 = cgi["パラメータ名3"]  #生成したCGIオブジェクトからパラメータの値を取得。
...

パラメータの値は、上のようにCGIクラスのインスタンスオブジェクトから取り出すことができます。 今回は名字の値が sei というパラメータ名で渡されますので、次のように書くことで名字の値を取り出すことができます。

変数 = cgi["sei"]    #"sei"というパラメータ名で送られた値を取得。

同様に、名前の値を取り出すときは次のように書きます。

変数 = cgi["mei"]    #"mei"というパラメータ名で送られた値を取得。

このCGIクラスの働きを確かめるために、次のプログラムにパラメータの値を取得する部分を追加し、オフラインで実行しなさい。 パラメータには自分の名字と名前を入力すること。 実行したら、変数myoujiと変数namaeにどのような値が代入されているか確かめて答えなさい。

#! /usr/local/bin/ruby
$KCODE = "e"
print "Content-type: text/html; charset=euc-jp\n\n"


require "cgi"

cgi = CGI.new
myouji = #この部分を作成する。
namae = #この部分を作成する。

p myouji
p namae

CGIクラスを使用したプログラムをオフラインで実行すると、パラメータの入力を求められます。 次のようにパラメータを入力することで、ブラウザからアクセスするときと同じように、CGIプログラムにパラメータを渡すことができます。

[h209xxx@ls01 h209xxx]% ./helloMr.cgi    #Enterキーを押して実行開始。
Content-type: text/html; charset=euc-jp

(offline mode: enter name=value pairs on standard input)
sei=Sirai&mei=Hidetosi    #Enterキーを押して改行する。
#Ctrl + d を押して実行再開。

オレンジ色の文字の部分はキーボードからの入力です。 パラメータを入力し終わったら改行して、Ctrlキーを押しながらDキーを押してください。プログラムの実行が再開されます。

[その他のパラメータの渡し方]

CGIプログラムをオフラインで実行するときのパラメータの渡し方は他にもあります。 どの方法で入力しても実行結果は同じです。

[h209xxx@ls01 h209xxx]% ./helloMr.cgi    #Enterキーを押して実行開始。
Content-type: text/html; charset=euc-jp

(offline mode: enter name=value pairs on standard input)
sei=Sirai    #Enterキーを押して改行する。
mei=Hidetosi    #Enterキーを押して改行する。
#Ctrl + d を押して実行再開。

次のように、コマンドの一部としてパラメータを記述する方法もあります。

[h209xxx@ls01 h209xxx]% ./helloMr.cgi sei=Sirai mei=Hidetosi    #Enterキーを押して実行開始。

この方法なら、パラメータがコマンドの履歴に残りますので、オフラインでプログラムをたびたび実行して動作を確認したいときにはとても便利です。 この場合、複数のパラメータを渡すときは & ではなく、半角スペースで区切ることに注意してください。

課題1-1-3

上で作成したプログラムにHTML文書を出力する部分を書き足して、受け取った名字と名前をWebページに表示するCGIプログラムを完成させなさい。 プログラムが完成したら、もう一度オフラインで実行し、次のようにHTML文書が出力されることを確認しなさい。 (太字の部分は受け取ったパラメータの値によって変わるようにすること。)

Content-type: text/html; charset=euc-jp

(offline mode: enter name=value pairs on standard input)
sei=Sirai&mei=Hidetosi
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
<title>受け取った名前を表示するCGIプログラム</title>
</head>
<body>
姓:Sirai<br>
名:Hidetosi<br>
<br>
こんにちは、Sirai Hidetosiさん。<br>
</body>
</html>

課題1-1-4

完成したCGIプログラムにブラウザでアクセスして、パラメータに指定した名字と名前が正しく表示されていることを確認しなさい。 自分の氏名を表示するようにパラメータを付加したURLを提出すること。

課題1-2-1

名字と名前の値を受け取るCGIプログラムはこれで完成しました。 しかし、実行するたびにブラウザのアドレスバーにパラメータを入力しなければいけないようでは、あまり現実的とは言えません。 そこで今度は、このCGIプログラムに、名字と名前の値を渡すためのWebページを作成してみましょう。

名前送信用HTMLファイル

上のWebページの「送信」というリンクをクリックするとhelloMr.cgiが実行されますが、その際に "Sirai" という名字の値と "Hidetosi" という名前の値がパラメータとして渡されます。

リンクをクリックして「こんにちは、Sirai Hidetosiさん。」と表示されたら、ブラウザのアドレスバーを確認してみましょう。 先程のように、URLの最後に名字と名前のパラメータが付加されているはずです。

http://nausicaa.cyber.sist.chukyo-u.ac.jp/ ...(中略)... /helloMr.cgi?sei=Sirai&mei=Hidetosi

上のWebページのように、リンクをクリックすると、自分の名字と名前を自分で作成したCGIプログラムに渡すHTMLファイルを作成しなさい。 作成したHTMLファイルのURLと、ファイルの内容(HTML文書)を提出すること。

[ヒント]

リンクタグに送信先を指定するときに、ファイル名だけでなくパラメータも記述する必要があります。

<a href="helloMr.cgi?sei=Sirai&mei=Hidetosi">送信</a>

課題1-2-2

CGIプログラムに値を渡すためのHTMLファイルは作成することができました。 しかし、特定の値しか渡すことができないようでは、CGIを呼び出す意味があまりありません。 そこで今度は、パラメータの値を自由に入力できるWebページを作成してみましょう。
次のWebページには、名字と名前を送信するフォームが用意されています。 自分の氏名を入力して、送信ボタンをクリックしてみましょう。 (今度は日本語の文字も正しく表示されるはずです。氏名を漢字で入力してみましょう。)

名前入力用HTMLファイル

氏名を漢字で入力すると、ブラウザのアドレスバーには、次のようにパラメータの値がURLエンコード(符号化)されて表示されます。

http://nausicaa.cyber.sist.chukyo-u.ac.jp/ ...(中略)... /helloMr.cgi?sei=%C7%F2%B0%E6&mei=%B1%D1%BD%D3

[日本語の文字がURLエンコードされる理由]

URLとして使用することのできる文字は、半角英数字と一部の記号だけに限られています。 日本語の文字をそのままURLとして使用することはできませんので、%と16進数を組み合わせた符号に変換する必要があります。 フォームを使用すると、自動的にURLエンコードが行われます。

なお、cgiライブラリを用いて渡されたパラメタの値を受け取った場合には、 URLエンコードされた日本語文字は「デコード」(元の文字に復元すること) されています。それもぜひ確認しておいてください。

上のページのように、フォームを使って任意の名前を送信するWebページを作成してみましょう。 先程のリンクタグの変わりに、次のようなタグを使って入力フォームを表示します。

<form method="GET" action="helloMr.cgi">
  姓:<input type="text" name="sei"><br>
  名:<input type="text" name="mei">
  <input type="submit" value="送信">
</form>

上記のタグを<body>タグの中に記述することで、氏名の入力フィールドと送信ボタンが表示されます。

入力フォームを使って、任意の氏名を自分で作成したCGIプログラムに渡すためのHTMLファイルを作成しなさい。 作成したHTMLファイルのURLと、ファイルの内容(HTML文書)を提出すること。

[入力フォームのタグの解説]

<form>タグは、様々なフォーム部品を使用して、CGIプログラムにパラメータを渡すためのHTMLタグです。

<form method="GET" action="ファイル名">
  フォーム部品
  フォーム部品
</form>

method属性には値の送信方法を指定します。 GETというのは、値をURLのパラメータとして送信し、その結果返ってくるWebページの情報を取得する方法です。 当面はこの方法を使用して値を送信していきます。 action属性には送信先のCGIファイル名を指定します。

フォームタグの間には、フォーム部品を表示するためのタグなどを書くことができます。 フォーム部品にはいくつかの種類がありますが、今回はテキスト入力フィールドと実行ボタンを使用しています。

<input type="text" name="パラメータ名">  #テキスト入力フィールドを表示。
<input type="submit" value="ボタンに表示される文字">  #実行ボタンを表示。

<input>タグはフォーム部品を表示するためのタグです。 type属性に "text" や "submit" と指定することで、部品の種類を指定することができます。

プログラミングIIIのホームに戻る