サーバサイドプログラム

WWW のさらなる仕組み

動的WEBページ

WWWとは で説明したように、 WWW サーバは基本的にはあらかじめ用意されたペー ジを返すのですが、もっと自分のページを動的にしたい、例えば、「来訪 者カウンタ(自分のページに何人来たか)を表示させたい」とか「メッセー ジを何か書きこんでもらう」などという要求があるのは当然のことです。

これを実現しようと思えばやはり「プログラム」が必要です。ただ一言 で「プログラム作ってWEBページで動かす」といっても、大きく次の2つ にわかれます。

です。これらのうち前者のクライアント側(ブラウザ)で動くものとして は、 JavaScript, Java applet や VBScriptなどがあります。これらのものは基本的に 状態が保存でき ない ため、ユーザの使い勝手をよくするとか、見た目を修飾すると かにもっぱら用いられます(とりあえずここでは説明を省略します)。

後者は、最近では「Webアプリケーション」と呼ばれることが多 いものですが、「サーバ側で動かす」ことにより、サーバー上のデー タ(情報)を変化・保存することが可能となりますので、多彩な応 用ができます。ネット通販に代表されるように、現在のインターネットビ ジネスは、この技術無しでは考えられません。サーバー側でプログラムを 動かす方法としては、Java Servletや ASP.NET 、SSI (Server Side Include) 等がありますが、まずは最も基本的で一般的な CGI (Common Gateway Interface) をとりあげます。

CGIとは?

CGI とは、サーバーホスト上で、WWW サーバプログラムが自分以外のプログラ ムを呼び出し、目的とする処理を依頼し、(HTML形式で記述されている)処理 結果をWWW ブラウザに送りかえす仕組みです。ここで、呼び出した外部プログ ラムのことをゲートウェイと呼ぶことがあり、CGI という言葉ができました。 以下の図のように、サーバーが外部プログラムの助けを借りて処理をおこなっ ています。(上の普通の WWW の場合と見比べながら仕組みを理解するのが良 いかもしれません。)

CGI

この外部プログラムはそのサーバー上で動くプログラムであればどのよう な言語・開発環境でも良いです。とはいえ、多くの場合 perl が最も一般 的でした。それは、perl の特徴が CGI の要求によくマッチしていたから なのです(が、それは後述しています)。

最近のトレンドとしては、perl でごりごり書くのははやらなくて、 PHP/Python/Ruby で書き、さらに言うと、スクラッチから書くのではなく アプリケーションフレームワーク使って開発、というものが大規模サイト でも主流となっているようです(別途解説)。


(以下、興味のある人は独習してみてください)

CGIを含めた Web ページの設置方法

ここでは、一般的な(?UNIX系のサーバで、設定次第でなんとでもなるけど、 大抵のデフォルト設定では、の意)CGIを含めた Web ページの設置の方法を説 明します。 付録:学内でのWWWページの設置 も参考にしてください。
  1. その前に、当然CGIが許可されているサーバにページを設置する権限(ア カウント)がある、という前提があります。一般には各自のホームディレクト リの直下の public_html/ というディレクトリの下が、個人のページを設置す るディレクトリです。もし無い場合はサーバに login して
    mkdir ~/public_html
    chmod 755 ~/public_html
    
    として、ディレクトリを作って、 パーミッション(読み/書き/ 実行の許可) を与えておきましょう。"~" は、ホームディレクトリを表す特殊記号です。 755 の意味ですが、これは実は8進数で、左から「自分」「同じグループ」 「それ以外のユーザ」についての属性を表しています。そして、 それぞれの8進数=3ビットについて という意味です。すると、755 とは、自分自身は読むのも書き込むのも実行も 可能、それ以外は読むのと実行は可能で、書き込みは不可、という意味になり ます。慣れるまではピンとこないかもしれませんが、おいおい分かってくると 思います。chmod では、上のような8進数で直接パーミッションを指定するほ か、
    chmod +x ~/public_html
    
    とすることで実行可能 (eXecutable) にする、という操作も可能です。詳細は 略します。

  2. そして、以前に作ったページがある人はそのファイルを、無ければ以下のよう な内容のファイルを、その public_html の下に index.html というファイル 名で置きます。
    <html>
    <body>
    This is a test page.
    </body>
    </html>
    

    Windows PC (以下、PC)がメインな人の場合、サーバである別マシンにファイルを「置く」 方法ですが、いくつかあります:

  3. public_html 内におくだけでは駄目な場合があり、上述のようにパーミッショ ンのチェックが必要になります。index.html の場合だと liweb にログインして
     ls -l index.html 
    として
    -rwxr-xr-x    1 maechan  maechan      1508 Nov  9 07:21 index.html
    
    のように、誰でも読めるようになっていればOKです。 なっていなければ
    chmod +r index.html
    
    として読み出し許可してやります。

    CGI も同様に、事前に作っておいてもいいですし、その場で (un*x 上で)編 集してもいいですし、とにかく foobar.cgi というファイルを作ります。そし て、実行可能にしておけば動くはず、です(コードの問題は後 述)

perl 超入門

特徴

perl とは、WWW サーバ上で動く CGI プログラムとして使用できるプログ ラミング言語のうち、最もよく利用されるものの1つです。その特徴は 以下の通りです。

CGI のさわり

本来はここでさらに perl の仕様を詳細に説明すべきですが、興味ある人は 最低限の説明 を参照してみ てください。
ここでは、とりあえずまずは最初ということで、perl で CGI を構成すること にします。最終的には HTML を出力するわけですので、その場合、もっとも普 通にかつ頻繁に使うのは「print」すなわち引数で与えられた文字列 をそのまま標準出力に書き出す命令になります。 print 命令の書き方は以下の通りです。
print  "ブラウザに送りたい文字列\n"; 

ダブルコーテーション「″」で囲まれた文字列がブラウザに返されます。最後 にある「\n」は改行コードなのですが、これはあくまでこの perl プログラム が生み出すHTML 文書の改行であってブラウザ上での改行ではありません。ブ ラウザ上で改行させたければ <BR>タグを使って

 print "あいうえお<BR>\n";
と記述します。

まずは、一番簡単な例を書いてみましょう。以下のような perl プログラムファ イルを「test.cgi」などと名前で作成しサーバ上のデイレクトリに置きます。 #!/usr/bin/perl # print "Content-Type: text/html; charset=Shift_JIS\n\n"; print "<HTML>\n"; print "<HEAD><TITLE>perl test </TITLE></HEAD>\n"; print "<BODY>\n"; print "ここ本文1行目<BR>\n"; print "ここ本文2行目<BR>\n"; print "</BODY>\n"; print "</HTML>\n"; このファイルを実行するのには、ブラウザのURL(アドレス)に http://puffin.hannan-u.ac.jp/lect/libs/nets/test.cgi と入力します。

まず、このファイルの先頭行の

#!/usr/bin/perl
ですが、これはこのファイルが perl で書かれており、そのインタープリタ (処理するプログラム)が /usr/bin に存在する、ということを指示していま す。これは、unix系OS でスクリプトを動かす時のお約束なので、そういうも のだと思って、当面はおまじないと思っていて従ってください。
とはいえ、たまに、「ちゃんとファイルを置いたのに動いてくれない!」と、は まる人がいるのですが… テキストファイルは基本的に文字(コード)の羅列なわけです。でも、我々は 適当な長さの行で折り返して編集したり表示したりしています。じゃぁ行の終 わりはどうなっているのかというと、ファイル内に 改行を表す特殊文字 (制御コード)がはいっていて、それを印として行をかえている、という わけです。

そして、やっかいなことに、OSによって、改行を表すコードが違うのです。伝 統的に、unix 系 (Linux 含む)では ^J (0x0A) 1 文字、 DOS/Windows では ^M^J (0x0D0A) の2 文字、さらに MacOS (ver.9 以前)では ^M (0x0D) 1 文字(MacOS X は unix 系なので改行 は ^J のみ)で表しています。なので、何も考えないで Windows で 作ったテキストファイルを Linux に持っていくと、行の終わりに ^M が残った ままになっていて、「/usr/bin/perl^M というプログラムなんて無い!」となっ てしまうわけです。

TeraPad で作成する場合、「コードを指定して保存」で、 改行が LF だけになっているのを確認してください。

1行目をこうしておいて、あとはそのファイルの実行属性をON にしておくと、 あとは普通のプログラムのように(いちいちインタープリタを指定しなくても) 動いてくれます。属性を変更するには、そのファイルが test.cgi だとすると、 シェルから
chmod +x test.cgi
とコマンドを打ち込んでやればOKです。

プログラムの中身はというと単純で、基本的にはHTMLをそのまま出力している わけですが、最初のprint 文だけは特別です。実は、HTTP のブラウザへの出 力は、メールと同様ヘッダ (header)本文 (body) が必 ずあって、ヘッダの部分でいまからブラウザへ送信するデータの種類などを示 すきまりです。ヘッダと本文の間は空行であるのもメールの場合と同様です。 ここでは

Content-Type: text/html; charset=Shift_JIS
と出力してるので、「今から送信するデータは HTML のテキストであって、文 字セット(ここではコードとほぼ同義)が Shift_JIS ですよ」とサーバがブ ラウザに教えている、というわけです。Windows で作ったテキストファイルは デフォルトで SJIS なので SJISで送信するなら Shift_JIS (ハイフンではな くアンダーバーであることに注意)とします。もし unix 上で euc で作成し たのなら、Shift_JIS ではなくEUC-JP等と適切なコード名を書いておかないと 文字化けしてしまいます。
この場合はどうするかというと、FTPの時にバイナリモードではなくテキスト モードで転送する(と、ソフトで自動変換してくれる)とか、あるいはシェル で(元のが win-edit.html とすると)
nkf --unix win-edit.html > unixfile.html
とすることで、改行コードが変換されたものが unixfile.html として保存さ れます。ついでに文字コードを例えば SJIS から JIS (ISO-2022-JP) に変換 するなら
nkf --unix --jis win-edit.html > unixfile.html
で一度にできます。あとは
rm win-edit.html 
mv unixfile.html win-edit.html 
と元のを消して名前をつけかえればOKです。 いずれにせよ、今自分が編集しているファイルのコード(文字セットと 改行コード)が何であるかを意識しないと、HTML/CGIはうまく動いてくれない ことがあるということは是非覚えておいてください。

フォームで値を渡す

前のように print で出力するだけなら、最初からHTML 書いてるのとかわらな いのであまりCGI を使う意義はなくって、クライアント(ブラウザ)からの入 力を活用できないとプログラムを動かしている意味がないです。そこで、ブラ ウザからCGIへの値の渡し方について簡単に例を示します。

多く使われるのは、form というタグをつかって入力データを渡すことで す。方法には GET, POST がありますがここでは詳細ははぶき当面 GET method のみを使うものとします。その場合、以下のようなHTML をまず書 くことになります。

<form action="http://puffin.hannan-u.ac.jp/lect/libs/nets/test2.cgi" method="GET"> <input type=text name="IN"> </form> こうすると、cgi のパラメータとして入力したデータが例えば「まえだ」 だとしますと、
test2.cgi?IN=%1B%24B%24%5E%24%28%24%40%1B%28B

のような形で渡されます。これは実は文字列のコードの16進数表示になって いることに注意してください。そして、test2.cgi として、 #! /usr/local/bin/perl # require 'jcode.pl'; $value = $ENV{'QUERY_STRING'} ; $value =~ s/^IN=//; $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg; print "Content-Type: text/html; charset=Shift_JIS\n\n"; print "<HTML>\n"; print "<HEAD><TITLE>perl test </TITLE></HEAD>\n"; print "<BODY>\n"; print "入力された文字列は、<BR>\n"; print "「".&jcode'sjis($value)."」です。<BR>\n"; print "<a href=\"index.html\"> 目次にもどる</a>\n"; print "</BODY>\n"; print "</HTML>\n"; のように作っておくと、
入力された文字列は、
「まえだ」です。
目次にもどる
のようにブラウザに帰ってきます。以下のフォームに入力してみてくださ い。
ここで perl のサンプルを(場当たり的で申し訳ないですが)少しずつ解説し ていきます。
  1. #!/usr/bin/perl
    これは 上と同様です。
  2. #
    これはコメント行です。
  3. require 'jcode.pl';
    これはVB.NET でいう import 文に相当するもので、ライブラリを使うときに 指定します。ここで指定しているものは漢字コード変換用ライブラリです。 liweb では既に/usr/lib/perl5/site_perl/jcode.pl としてインストールされ てるのですぐ使えますが、無い場合は自分でインストールする必要があります。 といってもこの jcode.pl というファイルをネットから落として cgi と同じ 場所に置くだけです。
  4. $value = $ENV{'QUERY_STRING'} ;
    これは、先に指定されたパラメータを環境変数という形でとりこみ、それ を変数 $value に格納してます。perl では変数の頭は(配列や連想記憶 の全体の参照を除き)かならず$ではじめます。環境変数についてはちょっ とややこしいので、ここではおまじないとして「こうしたら取り込める」 と覚えておいてください。
  5. $value =~ s/^IN=//;
    ここで、form で指定した input の名前"IN" をとりのぞいています。
  6. $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;
    実はパラメータの %1B%24B%24%5E%24%28%24%40%1B%28B は、「まえだ」を 変換した文字列だったのですが、それをもとの漢字コードにもどすおまじ ないです。
  7. print "Content-Type: text/html; charset=Shift_JIS\n\n";
  8. print "<HTML>\n";
  9. print "<HEAD><TITLE>perl test </TITLE></HEAD>\n";
  10. print "<BODY>\n";
  11. print "入力された文字列は、<BR>\n";
    ここまでは test.cgi とほぼ同じです。
  12. print "「".&jcode'sjis($value)."」です。<BR>\n";
    ここで、上でもとめた $value 、すなわち入力文字列を SJIS コードに変 換して、それをプリントしています。
  13. print "<a href=\"cgi-intro.html\"> 元にもどる </a>\n"; test.cgi ではつけませんでしたが、このように「元にもどる」リンクを つけておくと親切かもしれません。"\”" は、"" の中で文字として ″ を 使いたいときに \ を添えてあるもの(エスケープ)です。
  14. print "</BODY>\n";
  15. print "</HTML>\n";
    これらは前と同じです。

ちなみに次の CGI だと、式をいれるとその結果を返してきます。これだと ちゃんと「プログラムが動いている」ということが実感できるかもしれません。
呼び出しはこんな感じです。 <form action="http://puffin.hannan-u.ac.jp/lect/libs/nets/test3.cgi" method="GET"> <input type=text name="IN"> </form> test3.cgi の中身はこちらです。下のままなら、保存する時の漢字コードをEUC に、改行コードをLFだけにするのを忘れないようにしてください。 #! /usr/bin/perl # require 'jcode.pl'; $value = $ENV{'QUERY_STRING'} ; $value =~ s/^IN=//; $value =~ s/\+//g; $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg; print "Content-Type: text/html; charset=EUC-JP\n\n"; print "<HTML>\n"; print "<HEAD><TITLE>perl test </TITLE></HEAD>\n"; print "<BODY>\n"; print "入力された文字列は「".&jcode'euc($value)."」で<BR>\n"; print "結果は「".eval($value)."」です。<BR>\n"; print "<a href=\"cgi-intro.html\"> 元にもどる</a>\n"; print "</BODY>\n"; print "</HTML>\n";
eval($value) という関数呼び出しで、$value という変数内の 式を、EVALuate (評価)して、すなわち計算して、 その結果を print で表示してるというわけです。
以上のようにして、ブラウザとサーバー上のCGIとのデータ連係ができる ようになります。
前田としゆき maechan@hannan-u.ac.jp

講義用スタイル
印刷用スタイル (開いてから、ページを再度更新してください)