2. CGIとは何か?

CGI(Common Gateway Interface)は、Webサーバが外部プログラムを実行し、その標準出力をHTTPレスポンスとして返すための取り決めです。

CGIそのものはプログラミング言語ではありません。C、Perl、Python、シェルスクリプトなど、標準入力・標準出力・環境変数を扱えるプログラムであれば、CGIとして動かせます。


この章で学ぶこと


静的コンテンツと動的コンテンツ

WebサーバがHTMLファイルをそのまま返す場合、その内容は誰がアクセスしても同じです。このようなファイルを静的コンテンツと呼びます。

ブラウザ -> Webサーバ -> index.htmlを返す

一方、フォームに入力された名前を表示する、ログイン中のユーザーだけに内容を見せる、データベースから取得した一覧を表示する、といった処理では、アクセスごとに返す内容が変わります。このような内容を動的コンテンツと呼びます。

ブラウザ -> Webサーバ -> プログラムを実行 -> 実行結果を返す

CGIは、この「Webサーバがプログラムを実行する」部分の共通ルールです。


CGIの基本的な流れ

CGIでは、WebサーバがHTTPリクエストの情報を環境変数や標準入力に変換し、外部プログラムを起動します。CGIプログラムは処理結果を標準出力に書き出し、WebサーバはそれをHTTPレスポンスとしてブラウザへ返します。

[ブラウザ]
    |
    | HTTPリクエスト
    v
[Webサーバ]
    |
    | 環境変数・標準入力
    v
[CGIプログラム]
    |
    | 標準出力
    v
[Webサーバ]
    |
    | HTTPレスポンス
    v
[ブラウザ]

C言語でCGIを書く場合でも、特別なWeb用ライブラリが必須になるわけではありません。最初は getenv()stdinprintf() を使って、リクエストとレスポンスの境界を確認できます。


CGIプログラムが受け取る情報

CGIプログラムは、主に次の方法でリクエスト情報を受け取ります。

種類 受け取り方
リクエストメソッド 環境変数 REQUEST_METHOD GET, POST
クエリ文字列 環境変数 QUERY_STRING name=Alice&age=20
POSTデータの長さ 環境変数 CONTENT_LENGTH 17
Cookie 環境変数 HTTP_COOKIE SID=abc123
POST本文 標準入力 stdin name=Alice

この仕組みを理解すると、Webフレームワークが普段どのような情報を整理してくれているのかが見えてきます。


CGIプログラムが返す情報

CGIプログラムは、標準出力にレスポンスを書き出します。最低限必要なのは、レスポンスヘッダと空行です。

Content-Type: text/html; charset=UTF-8

その後ろにHTML本文やJSON本文を書きます。

<!DOCTYPE html>
<html>
<body>
  <h1>Hello</h1>
</body>
</html>

C言語では、これを printf() で出力します。

printf("Content-Type: text/html; charset=UTF-8\r\n\r\n");
printf("<h1>Hello</h1>\n");

CGIの利点と制約

CGIの利点は、仕組みが単純で、Webサーバとプログラムの境界が見えやすいことです。言語を問わず使えるため、C言語でもCGIプログラムを書けます。

一方で、リクエストごとにプロセスを起動するため、現代的なWebアプリケーション基盤と比べると効率はよくありません。また、入力値の解析、エスケープ、セッション管理、エラー処理などを自分で扱う必要があります。

本書では、この不便さを教材として利用します。CGIを通じて、Webアプリケーションの基本要素をひとつずつ確認していきます。


現代のWeb技術との関係

PHP、Ruby on Rails、Django、Express、Java Servlet、FastCGIなどは、CGIと同じく「リクエストを受け取り、処理し、レスポンスを返す」構造を持っています。

実装方式や実行モデルは大きく異なりますが、次の流れは現代のWebアプリケーションにも残っています。

リクエストを読む
入力を解析する
処理する
レスポンスヘッダを決める
本文を生成する
返す

CGIを学ぶ目的は、CGIを最新技術として扱うことではありません。この基本構造を、できるだけ隠れた層の少ない形で確認することです。


小まとめ

次章では、C言語で最初のCGIプログラムを作成し、ブラウザから実行してみます。