Apache Tutorial: CGI による動的コンテンツ

# CGI による動的コンテンツ

- CGI による動的コンテンツ
- CGI を許可するように Apache を 設定する
  - ScriptAlias
  - ScriptAlias ディレクトリ外の CGI
    - CGI の実行を可能に するために Options を明示的に使用する
    - .htaccess ファイル
- CGI プログラムを書く
  - あなたの最初の CGI プログラム
- しかし、まだ動かない !
  - ファイルのパーミッション
  - パス情報
  - 構文エラー
  - エラーログ
- 裏で何が起こっているのか?
  - 環境変数
  - 標準入出力
- CGI モジュール/ライブラリ
- 更なる情報

## CGI による動的コンテンツ

関連モジュール mod_alias mod_cgi | 関連ディレクティブ AddHandler Options ScriptAlias

CGI (Common Gateway Interface) は、ウェブサーバがコンテンツ生成をする 外部プログラムと協調して動作するための方法を定義しています。そのプログラムはしばしば CGI プログラムや CGI スクリプトと呼ばれます。CGI は、ウェブサイトに 動的なコンテンツを置くための最も簡単で一般的な方法です。このドキュメントは、 Apache ウェブサーバで CGI を設定し、CGI プログラムを書き始めるための 入門書となるでしょう。

## CGI を許可するように Apache を 設定する

CGI プログラムを正しく動作させるには、CGI を許可するように Apache の設定を行う必要があります。これを行なうための方法がいくつか あります。

### ScriptAlias

`ScriptAlias` ディレクティブを使用して、CGI プログラム用の 特別な別ディレクトリを Apache に設定します。 Apache は、このディレクトリ中の全てのファイルを CGI プログラムであると 仮定します。そして、この特別なリソースがクライアントから要求されると、 そのプログラムの実行を試みます。

`ScriptAlias` ディレクティブは以下のように使用します:

            ScriptAlias /cgi-bin/ /usr/local/apache/cgi-bin/

デフォルト位置に Apache をインストールしたならば、 この例はデフォルト状態の `httpd.conf` 設定ファイル に含まれています。 `ScriptAlias` ディレクティブは、URL の前に付加するディレクトリを定義する `Alias` ディレクティブとかなり似ています。 `Alias` と `ScriptAlias` は通常、 `DocumentRoot` ディレクトリ外のディレクトリのために使用されます。 `Alias` と `ScriptAlias` との差は、 `ScriptAlias` が接頭辞で始まるすべての URL は CGI プログラムと みなされるという追加の意味を含んでいることです。従って、 上記の例では、`/cgi-bin/` で始まるリソースへのあらゆるリクエストに対して、ディレクトリ `/usr/local/apache/cgi-bin/` から提供し、それらを CGI プログラムとして扱うよう Apache に示します。

例えば、URL `http://dev.rcbowen.com/cgi-bin/test.pl` が要求された場合、Apache は ファイル `/usr/local/apache/cgi-bin/test.pl` を実行し、その出力を返すことを 試みます。 もちろん、ファイルが存在し、実行可能であり、決められた方法で出力を返します。 そうでなければ、Apache はエラーメッセージを返します。

### ScriptAlias ディレクトリ外の CGI

CGI プログラムは、セキュリティ上の理由から `ScriptAlias` されたディレクトリに制限されることがしばしばあります。 この方法により、CGI プログラムを使用できるユーザを管理者が厳しく制御する ことができます。 しかしながら、適切なセキュリティ事前対策がとられるならば、CGI プログラム を任意のディレクトリで実行できないようにする理由はありません。 例えば、ユーザに `UserDir` ディレクティブで 彼らのホームディレクトリ配下にウェブコンテンツを持たせたいとします。 もし、彼らが CGI プログラムを持つことを望んでいても、メインの `cgi-bin` ディレクトリへのアクセスができない場合、CGI プログラムを 実行することができる他の場所が必要になります。

### CGI の実行を可能にするために Options を明示的に使用する

サーバのメインの設定ファイル中で `Options` ディレクティブを 明示的に使用することで、特定のディレクトリ配下で CGI の実行を許可するように 指定することができます:

            <Directory /usr/local/apache/htdocs/somedir>
                    Options +ExecCGI
            </Directory>

上記ディレクティブは、CGI ファイルの実行を可能にするよう Apache に伝えます。また、どのファイルが CGI ファイルかを サーバに伝える必要があります。次の `AddHandler` ディレクティブの例では、`cgi` または `pl` を拡張子に 持つすべてのファイルを CGI プログラムとしてみなすことをサーバに伝えます:

         AddHandler cgi-script cgi pl

### .htaccess ファイル

`.htaccess` ファイルは、ディレクトリ毎に ディレクティブを指定する方法です。 Apache は、リソースを提供するときに、提供するファイルが置かれている ディレクトリ中の `.htaccess` というファイルを参照します。 そのファイルを発見したら、その中で発見されたディレクティブが適用されます。 `.htaccess` ファイルは、`AllowOverride` ディレクティブの指定により使えるようになります。 `AllowOverride` ディレクティブは、`.htaccess` ファイルで 設定できるディレクティブのタイプを指定します。 `AllowOverride` ディレクティブの指定がない場合、まったく使えません。 CGI の実行を許可するために必要となるディレクティブを指定可能にするには、 以下の設定がサーバのメインの設定で必要になります:

            AllowOverride Options

`.htaccess` ファイルでは、次のディレクティブが必要と なります:

            Options +ExecCGI

この設定では、このディレクトリにおける CGI プログラムの実行を許可するよう Apache に伝えます。

## CGI プログラムを書く

通常のプログラミングと CGI プログラミングの間には主に二つの違いが あります。

一つは、CGI プログラムのすべての出力には MIME-type ヘッダを付けなければなりません。これはどのような種類のコンテンツを受け取って いるかをクライアントに示す HTTP ヘッダです。ほとんどの場合では、 次のように出力します:

            Content-type: text/html

もう一つは、出力を HTML か、ブラウザが表示することが できる何か他の形式にする必要があります。 大抵の場合は HTML でしょうが、GIF イメージや他の非 HTML コンテンツを出力する CGI プログラムを書くこともあるでしょう。

これら二点以外では、CGI プログラムを書くことは、あなたが書いている 他のプログラムと大いに似ているでしょう。

### あなたの最初の CGI プログラム

次に示すのは、ブラウザに 1 行印字する CGI プログラムの例です。 以下を入力し、`first.pl` というファイルに保存し、それを `cgi-bin` ディレクトリに置いてください。

            #!/usr/bin/perl
            print "Content-type: text/html\r\n\r\n";
            print "Hello, World.";

Perl に精通していなくても、何が起こるかを 理解することはできるはずです。 1 行目は、`/usr/bin/perl` で見つけ られるインタプリタにこのファイルを供給することでこのプログラムが実行されることを Apache に (シェル上で実行しようとしているならば、そのシェルに ) 示します。 2 行目は、前述したとおり content-type の定義を印字します。 これには復帰改行の二つの組を後に付加します。これにより、 ヘッダの終りに空行が置かれ、HTTP ヘッダの終りとボディの始まりを示します。 3 行目は、``Hello, World.'' という文字列を印字し、これで終りとなります。

好みのブラウザを開き、アドレス

            http://www.example.com/cgi-bin/first.pl

あるいはファイルを置いたロケーションを指定すると、 `Hello, World.` という 1 行がブラウザウィンドに現れるでしょう。 それはあまりエキサイティングなことではありません。 しかし、これがうまく動けば、 他のどのようなものでも動かすことができるようになります。

## しかし、まだ動かない !

ウェブから CGI プログラムへのアクセスを行なったとき、 ブラウザで見る可能性がある四つの基本的なことがあります:

CGI プログラムの出力
  素晴らしい ! それはすべてがうまく動いたことを意味します。
CGI プログラムのソースコード、または "POST Method Not Allowed" というメッセージ
  これは、CGI プログラムを処理できるよう Apache を適切に設定して いなかったことを意味します。 「CGI を許可するように Apache を設定する」の章を読み直し、あなたが何を間違えたかを 探してみてください。
メッセージが "Forbidden" で始まっている
  これはパーミッションの問題ということを意味します。 Apache のエラーログと、後述の 「ファイルのパーミッション」の章を チェックしてください。
"Internal Server Error" というメッセージ
  Apache のエラーログをチェックすると、 "Premature end of script headers" というログが記録されていると思います。 そして、おそらく CGI プログラムによって生成されたエラーメッセージも記録されているでしょう。 この場合、CGI プログラムが適切な HTTP ヘッダを出力できない原因を 知るために、以下の各章でチェックしてみてください。

### ファイルのパーミッション

サーバはあなたの権限で実行されていないのを忘れないように。 つまり、起動するとき、サーバは特権をもたないユーザ - 通常 ``nobody'' や ``www'' の権限で実行されます。したがって、あなたが所有するファイルを 実行するには別のパーミッションが必要となります。 通常、``nobody'' が実行するのに十分なパーミッションを与える方法は、ファイルに 誰でも実行可能とするパーミッションを与えることです:

            chmod a+x first.pl

また、もしあなたのプログラムが他のファイルを読み書きするならば、 それらのファイルは、これが可能となる正しいパーミッションを持っている必要が あります。

これに対する例外は、サーバが suexec を 使用するよう設定されている場合です。 suexec は、CGI プログラムが置かれているバーチャルホストまたはユーザのホーム ディレクトリによって、異なるユーザ権限で 実行されるようにします。 suexec はとても厳しいパーミッションのチェックがあり、 そのチェックを通過できないと "Internal Server Error" となり、 その CGI プログラムの実行は失敗します。 この場合、どのセキュリティチェックが失敗しているのかを知る ために suexec ログファイルをチェックする必要があります。

### パス情報

コマンドラインからプログラムを実行するとき、意識しなくても シェルに渡される情報があります。 例えば、参照するファイルのためにどこを検索したらよいかをシェルに伝えるパスが あります。

プログラムが CGI プログラムとしてウェブサーバによって実行されるとき、 それはパスを持ちません。 CGI プログラム内で呼び出すあらゆるプログラム (例えば、'sendmail' の ようなもの) は、フルパスで指定する必要があるでしょう。 それにより、CGI プログラムを実行しようとしたとき、シェルはそのようなプログラムを 見つけることができます。

同様なことは、スクリプトのインタプリタ (しばしば `perl` ) へのパスで、CGI プログラムの 1 行目に次のように示されます:

         #!/usr/bin/perl

これがインタープリタへの実際のパスであることを確実にしておきます。

### 構文エラー

CGI プログラムが失敗するのは大抵、プログラム自身に問題がある場合です。 一度 CGI の使い方を理解し、前述の二つの誤りを犯していないならば、 まず間違いなくそうでしょう。ブラウザを通してテストを行う前に必ず、コマンドライン からプログラムの実行を試しなさい。これにより、大抵の問題が起こらなくなります。

### エラーログ

エラーログは友達です。全てのうまくいかないことは、エラーログに メッセージを生成します。必ずそれを最初に見るべきです。 もし、あなたがウェブサイトを主催している場所がエラーログの参照を 許していないならば、きっと他のサイトで主催するべきです。 エラーログの読み方を学ぶことで、ほとんど全ての問題が迅速に 確認され、迅速に解決されるということが分かるでしょう。

## 裏で何が起こっているのか?

CGI プログラミングに熟達すると、裏で起こっている ことについて更に理解することは有益になるでしょう。ブラウザと サーバがどのように相互通信するかについては特にそうです。なぜなら、 ``Hello, World.'' を印字するプログラムを書くことはまことに結構ですが、 それは特に有益ではありません。

### 環境変数

環境変数は、あなたがコンピュータを使うときに辺りに存在している値です。 それらは、パス (コマンドをタイプしたときに実行する実際のファイルを 探し出すところ)、ユーザ名、端末型などのような便利なものです。 通常の、毎日の環境変数の完全なリストを調べるには、コマンドプロンプトで `env` を入力します。

CGI の処理中、サーバとブラウザも環境変数を設定し、それにより 相互に通信することができるようになります。 その環境変数は、ブラウザタイプ (Netscape, IE, Lynx)、 サーバタイプ (Apache, IIS, WebSite)、実行されている CGI プログラムの名前 などのようなものです。

これらの変数は CGI プログラマが使用することができます。そして、 それはクライアントとサーバの通信の話の半分です。必要な変数の完全なリストは http://hoohoo.ncsa.uiuc.edu/cgi/env.html にあります。

以下の単純な Perl CGI プログラムは、渡される全ての環境変数を 表示します。同様のプログラムは、Apache ディストリビューションの `cgi-bin` ディレクトリに二つ含まれています。 いくつかの変数が必須であり、いくつかは任意であることに注意してください。 そして、公式のリストにはないいくつかの変数が表示されているかもしれません。 さらに、Apache はデフォルトで用意されている基本的なものに あなた自身の環境変数を加える ための、多くの異なる方法を用意してします。

         #!/usr/bin/perl
         print "Content-type: text/html\n\n";
         foreach $key (keys %ENV) {
              print "$key --> $ENV{$key}<br>";
         }

### STDIN と STDOUT

サーバとクライアント間のもう一つの通信は、標準入力 (`STDIN`)と 標準出力 (`STDOUT`) を通じて行なわれます。通常の文脈において、 `STDIN` はキーボードやプログラムが動作するために与えられる ファイルを意味し、`STDOUT` は通常コンソールまたはスクリーンを 意味します。

ウェブフォームから CGI プログラムへ`POST` したとき、 フォームのデータは特別なフォーマットで束ねられ、`STDIN` を 通して、CGI プログラムに引き渡されます。プログラムはデータがキーボード もしくはファイルから来ていたかのように処理することができます。

「特別なフォーマット」はとても単純です。フィールド名と値はイコール (=) で結ばれます。そして値の組はアンパサンド (&) で 結ばれます。スペース、アンパサンド、イコールのような面倒な文字 は、それらが動作を駄目にしないようにその文字に相当する 16 進に変換されます。 全データ文字列は、以下のようになります:

         name=Rich%20Bowen&city=Lexington&state=KY&sidekick=Squirrel%20Monkey

時々、このような文字列が URL に付加されるのを見るでしょう。 その場合、サーバは `QUERY_STRING` という環境変数にその 文字列を入れます。それは `GET` リクエストと呼ばれます。 HTML フォームでは、データを渡すために `GET` と `POST` のどちらを使用するかを、 `FORM`タグの `METHOD` 属性の設定で指定します。

CGI プログラムは、その文字列を役に立つ情報に分割する責任があります。 幸いにも、そのデータ処理を助けるライブラリやモジュールが存在します。これらは、 CGI プログラムの他の面でも同様に役に立ちます。

## CGI モジュール/ライブラリ

CGI プログラムを書くとき、面倒な仕事の大部分をしてくれる コードライブラリまたはモジュールを使うことを検討すべきです。 これはエラーを減らし、早い開発につながります。

Perl で CGI プログラムを書いているなら、モジュールは CPAN で提供されています。この目的のための 最も普及しているモジュールは CGI.pm です。 CGI::Lite も検討しましょう。これは、ほとんどのプログラムにおいて必要とするすべての機能の最小セットの実装です。

C で CGI プログラムを書いているなら、いろいろな オプションがあります。これらの内の一つは http://www.boutell.com/cgic/ で提供されている CGIC ライブラリです。

## 更なる情報

CGI に関する情報はウェブで数多く提供されています。CGI の問題については Usenet の comp.infosystems.www.authoring.cgi で、他のユーザと 論議することができます。HTML Writers Guide の -serversメーリングリスト は、あなたの質問に回答してくれる偉大なリソースです。 http://www.hwg.org/lists/hwg-servers/ で更に多くを探し出すことが できます。

そしてもちろん、おそらく CGI プログラムの動作に関する詳細の 全てが記述されている CGI の仕様を読むべきです。オリジナルバージョンを NCSA で、 アップデートされたドラフトを Common Gateway Interface RFC プロジェクトで参照することができます。

CGI の問題について、加わっているメーリングリストまたはニュース グループに質問を送るとき、起こったもの、起こってほしいこと、 実際に起こったことがどう違うか、使用しているサーバ、 CGI プログラムを記述している言語に関する十分な情報と、 可能であれば問題のコードを提供するようにしてください。 そうすることで、問題がより間単に見つかるようになります。

Apache のソースコードにおいて問題を発見したことを確信していない 限り、CGI の問題に関する質問を Apache バグデータベースに送るべきでない ことに注目してください。