職場実習4日目
今日からperlのCGI掲示板を作成し始めた。
まずはApatchでperlを動かす所から始める。
perlの無料CGIを入手し、動かしてみる。
このサイトから、BBS Type2のソースを入手し、サーバに入れて動かしてみた。
無料のCGI/Perlスクリプト - CANDY CGI
…しかし、画面が真っ白のまま動かない。
マニュアルを読んで、ファイルのアクセス権限を正しくセットしたにも関わらず、全く動かず、どこに不具合があるのか見当すら付かなかった。
perlのバージョンは5.8以上なので、とりあえず、ソースの文字コードを全てUTF-8に変え、HTML記述部分のメタデータの文字コードもUTF-8に設定したが、全く変わらず。
Apatchの設定を再確認する。
送信されたフォーム入力内容を受け取って、ハッシュに格納し、テーブル出力するCGIを試験的に作ってみた。
Web上では、POSTメソッドの送信内容が標準入力から取得でき、標準出力からブラウザ画面に出力できるらしいので、コマンドライン上とはあまり変わらない感覚でプログラムを作ることができた。
CGIの仕組み
しかし、いざ実行すると、画面が表示されなかったり、文字化けしたりと不具合だらけなので、Apatchの設定ファイルを見直してみる。
CGIの設定 - Apacheの設定 - 自宅サーバーの構築 - 自宅サーバーでやってみよう!!
Apache Tutorial: CGI による動的コンテンツ - Apache HTTP サーバ
粗方見直しが終わり、ファイルのアクセス権限の確認もしてみたのだが、文字化けだけは直らず。
ふと気が付き、ソースファイルの文字コードを見たところ、Shift_JISになっていた。
ソースファイルもUTF-8にしたところ、文字化けが無くなり、フォーム入力内容がきちんとテーブルで表示された。
ここで、POSTからの送信内容をもっと厳密に取得するのと、GETメソッドに対応するため、標準入力ではなく環境変数(ハッシュ)から取得する形に変えてみた。
CGIの仕組み
入力フォーム編(GETとPOSTデータを受け取るには) - futomi's CGI Cafe
環境変数
read [Perl講座 -Smart]
さらに、送信データを取得する箇所をサブルーチン化して、別ファイルに切り離してみたところ、また不具合が出た。
文字コードを確認し、ファイルのアクセス権限も設定し、別ファイル内の最後にtrueを意味する1を返すように設定しても、結果は変わらなかった。
ブラウザ出力からはエラー箇所を特定できないため、コマンドラインから実行できるようにし、その場合は標準入力からパラメータを手入力するようにしたところ、問題なく動いた。
どうやら環境変数を取得する箇所がうまく動いていないらしい。
#!/usr/bin/perl # フォーム入力内容をリクエスト属性として受け取るサブルーチン(lib/HttpRequest.pl) package lib; use utf8; sub get_request { my $formdata; if (exists $ENV{'REQUEST_METHOD'}) { my $request_method = $ENV{'REQUEST_METHOD'}; print "<!-- $request_method -->\n"; if ($request_method eq 'GET') { $formdata = $ENV{'QUERY_STRING'}; } elsif ($request_method eq 'POST') { read(STDIN, $formdata, $ENV{'CONTENT_LENGTH'}); } else { $formdata = join('', <STDIN>); } } else { $formdata = join('', <STDIN>); } my @formdata_list = split('&', $formdata); my %formdata_hash = (); foreach my $hashdatas (@formdata_list) { (my $hashdata_key, my $hashdata_value) = split('=', $hashdatas); $hashdata_key = &url_decode($hashdata_key); $hashdata_value = &url_decode($hashdata_value); $formdata_hash{$hashdata_key} = $hashdata_value; } return %formdata_hash; } sub url_decode { (my $urlcode) = @_; $urlcode =~ tr/+/ /; $urlcode =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $urlcode =~ s/</</g; $urlcode =~ s/>/>/g; $urlcode =~ s/\r//g; $urlcode =~ s/\n/<br>/g; $urlcode =~ s/\,/,/g; return $urlcode; } 1;
試しに環境変数をテーブル表示するスクリプトを書いて動かしてみたところ、コマンドラインでもWebブラウザでも問題なく動いた。
こうなると、原因が全く分からない。とりあえず思いつくまま、送信データを取得するサブルーチンをプログラムの最初のほうから、後半部分に移動してみたところ、何故かうまく動いた。サブルーチンを実行する場所によって、環境変数を取得できない事があるのだろうか。
#!/usr/bin/perl # フォーム入力内容を受け取り表示するスクリプト(a.pl) use utf8; require 'lib/HttpRequest.pl'; print "Content-type: text/html; charset=utf-8\n\n"; print "<html>\n"; print "<head>\n"; print "<title>テスト</title>\n"; print "</head>\n"; print "<body bgcolor=\"#ffcccc\">\n"; print "<p>これはCGIのテストです。</p>\n"; print "<table border>\n"; %formdatalist = lib::get_request(); foreach $request_key (sort keys(%formdatalist)) { print "<tr><th>" . $request_key . '</th><td>' . $formdatalist{$request_key} . "</td></tr>\n"; } print "</table>\n"; print "</body>\n"; print "</html>\n";
perlの無料CGIを入手し、動かしてみる。(その2)
GET/POSTメソッドからの送信内容を取得したり、URLエンコードされた文字列をデコードしたり、環境変数を使うことはできるようになったので、再び掲示板CGIのサンプルを動かしてみる。
最初に入手したCGIは処理が複雑なため、もっとシンプルなCGIを探してみる。
CGI(Perl) 掲示板
1ファイルのみで全部の処理を行える見通しのよいプログラムのため、導入は簡単だった。
これを雛形に、自分で色々な機能を付け加えていくのも楽しいかも知れない。
しかし、いくつか問題点が見つかった。
- POSTメソッドを使って送信した内容を同じページで取得するため、書き込みを行った後に更新ボタンを押すと再送信され、同じ書き込みが繰り返される。
- 書き込みログファイルは前もって用意しておき、アクセス権限を誰でも書き込み可能にする必要がある。さもないと、ログが記録されず、書き込み内容は最後に行った1件しか表示されない。
更新による多重投稿の問題はよく原因が分からない。書き込みを行った後、名前欄の内容が残るのは仕様だが、内容欄は空になっているので、更新時に再送信されるのはフォーム内容ではなく環境変数に保持されたリクエスト属性なのだろうか。
このCGIを使うなら、解決する必要のある問題だろう。