CGI
- なぜ生まれた?
- プログラムの呼び方がサーバーごとに違い、ゲートウェイはサーバーごと配らないと共有できなかった。
- 何を解決した?
- 環境変数と標準入出力で受け渡す共通の取り決めにし、同じプログラムを別のサーバーでも動かせた。
- 何を残した?
- 要求のたびにプロセスを起動する重さと、HTML を1行ずつ出力する手間が残った。
- 登場
- 作者
- Rob McCool、Tony Sanders、Ari Luotonen、George Phillips
- 状態
- レガシー
CGI という考え方が無かったころ
Section titled “CGI という考え方が無かったころ”1993年4月に公開された NCSA httpd 0.3 の告知に並ぶ機能は、ディレクトリの割り当て、ディレクトリの一覧の自動生成、gopher の一覧の表示の3つです。 ソースは gopher 対応を除いて約500行で、置いてあるファイルを返すための小さなプログラムでした。
一方で、Web から使いたいものは WAIS の検索やデータベースのように、ファイルの外にもありました。
1993年7月、ヴィクトリア大学の Nathan Torkington は、CERN の httpd 2.06 に “an executable shell script ability”(シェルスクリプトを実行する機能)を足した差分を www-talk に投稿しました。
検索語が付いてきたら ページ名.search というスクリプトを探し、検索語を引数にして実行し、出力をそのまま返す改造です。
差分に残る元の CERN のコードには、検索を断るエラーの箇所に “It ought to, using an executable script”(実行できるスクリプトを使って、そうすべきだ)というコメントが付いていました。
同じ月には、Plexus というサーバー向けに Oracle を引くゲートウェイも公開されました。組み込むには Plexus の設定ファイルにコードの読み込みを書き足します。
9月の NCSA httpd 1.0a2 の告知には /htbin の不具合修正が載り、CERN にも版 2.13 で入った、URL が /htbin/ で始まるとスクリプトを呼ぶ旧式の仕組みがありました(どちらが先かは確かめられていません)。
1993年の夏には、サーバーにプログラムを実行させる方法がいくつもあり、どれもサーバーごとに別の方法でした。
なぜ Web サーバーに機能を足すのでなく、別のプログラムを起動する形だったのか
Section titled “なぜ Web サーバーに機能を足すのでなく、別のプログラムを起動する形だったのか”困っていたのは、ゲートウェイを書いて人に配りたい人たちでした。 1993年11月、George Phillips は NCSA httpd の alpha 版のスクリプトの仕組みの問題点を NCSA の Rob McCool に送り、最後にこう書いています。
“I’m quite eager to have the ability to publish some of my gateway code without having to publish my server along with it.” (自分のサーバーを一緒に公開しなくても、ゲートウェイのコードを公開できるようにしたくてたまらない)
サーバーを改造すれば、ゲートウェイはそのサーバーの一部になり、別のサーバーの利用者には渡せません。 別のプログラムにして受け渡し方だけを決めておけば、プログラムだけを配れます。 McCool も引数のデコードの議論で “I don’t want to have people upgrading their server every time a new convention is invented.”(新しい決まりができるたびに、サーバーを入れ替えさせたくない)と書いています。
CGI という考え方
Section titled “CGI という考え方”名前が付くまでの3週間
Section titled “名前が付くまでの3週間”1993年11月11日、Plexus を作っていた BSDI の Tony Sanders が、ゲートウェイにデータを渡す形式を Plexus・NCSA・CERN で統一しようと www-talk で呼びかけました。 11月14日、McCool は、多くのゲートウェイの作者が “for fear that the script interface will change again”(スクリプトの仕組みがまた変わるのを恐れて)公開を待っていると書き、正式な 1.0 に入れた仕組みは変えないと約束して、中身の議論をスクリプトの作者たちに開きました。
11月17日の Common Gateway Protocol(CGP/1.0)の仕様案で、McCool は情報のほとんどを環境変数で渡すことにしました。コマンドラインの長さの制限と、短いスクリプトが標準入力を解析する面倒を避けるためです。 CERN の Ari Luotonen は翌日、フォームの値の渡し方などについて意見を返しています。
11月19日の改訂版で、名前が変わります。
“I have changed the name to CGI because it’s really an interface and not a protocol. I know, picky picky.” (名前を CGI に変えた。これは本当はプロトコルではなくインターフェースだから。細かいのはわかってる)
同じ日、Phillips は環境変数の名前を GATEWAY_INTERFACE・REQUEST_METHOD にしてはどうかと返しました。1997年の NCSA の仕様には、どちらもこの名前で載っています。
12月4日に McCool は仕様を HTML の文書にまとめて最後の意見を募り、12月13日、最初の非 alpha 版の NCSA httpd 1.0 が CGI/1.0 を実装して公開されました。
この記事では、CGI という名前が付いた11月19日の改訂版を登場としています(CGP の案は11月17日、実装の公開は12月13日)。 名前が付いたのは1993年11月ですが、サーバーにプログラムを実行させること自体は、それ以前から各サーバーで行われていました。
サーバーとプログラムは何をやり取りするのか
Section titled “サーバーとプログラムは何をやり取りするのか”使うのは、プログラムがもともと持つ入り口と出口です。
| 経路 | 何を渡すか |
|---|---|
| 環境変数 | REQUEST_METHOD・QUERY_STRING・PATH_INFO・REMOTE_ADDR など、要求についての情報 |
| 標準入力 | POST で送られた本文。サーバーは CONTENT_LENGTH バイトを渡す |
| 標準出力 | Content-type: などのヘッダ、空行、本文。Location: なら別の文書を返させる |
| コマンドライン | ISINDEX の検索語だけ(デコード済み) |
McCool は NCSA httpd 1.0 の公開の日、期末試験のさなかだと断りながら、以前の /htbin との違いを “cosmetic”(見た目の違い)と説明しました。引数がコマンドラインではなく環境変数で来る、という点です。
コードで見る違い
Section titled “コードで見る違い”フォームから送られた名前を受け取って、あいさつのページを返す処理で比べます。どちらもこの記事のための作例です。 旧式の側は、Luotonen が書いた CERN の旧式スクリプトの説明に沿っています。
#!/bin/sh# /htbin/greet?name=Ari+L は、次の引数で呼ばれる# $1 = ''(URL の残り) $2 = 'name=' $3 = 'Ari L'# デコードとシェル向けのエスケープはサーバーが済ませているecho "Content-Type: text/html"echo ""echo "<TITLE>Hello</TITLE>"echo "<H1>Hello, $3</H1>"CGI の側は、1993年当時の Perl 4 でも動く書き方にしています。
#!/usr/local/bin/perl# GET なら QUERY_STRING、POST なら標準入力から CONTENT_LENGTH バイトif ($ENV{'REQUEST_METHOD'} eq 'POST') { read(STDIN, $query, $ENV{'CONTENT_LENGTH'});} else { $query = $ENV{'QUERY_STRING'};}foreach $pair (split(/&/, $query)) { ($key, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack("C", hex($1))/eg; $in{$key} = $value;}print "Content-type: text/html\n\n";print "<TITLE>Hello</TITLE>\n";print "<H1>Hello, $in{'name'}</H1>\n";どちらも、受け取った値を HTML としてエスケープする処理は省いています。 旧式が短いのはサーバーがデコードしてくれるからで、W3C も旧式を “nice for quick hacks that don’t need to be portable”(移植しなくてよい手早い仕事には便利)と書いています。 CGI はデコードを自分で書く代わりに、同じファイルが NCSA でも CERN でも動き、長い値や POST の本文もコマンドラインの長さに縛られずに受け取れます。
CGI は言語なのか
Section titled “CGI は言語なのか”違います。CGI はサーバーと外部プログラムのあいだの取り決めで、実行できるものなら何で書いてもかまいません。 1997年の NCSA の入門は、C/C++、Fortran、Perl、Tcl、Unix のシェル、Visual Basic、AppleScript を挙げています。 Perl で書かれた CGI は多くありましたが、仕組みとしては言語を選びません。
CGI を実装した技術
Section titled “CGI を実装した技術”NCSA httpd 1.0 は、旧来の htbin のスクリプトを配るのをやめ、その CGI/1.0 版を同梱しました。古いスクリプトも OldScriptAlias という設定で動かせました。
同じ日、McCool は NCSA の FTP サーバーに CGI スクリプトの置き場を作り、投稿を呼びかけています。
CERN httpd は 2.15 で “CGI/1.0 interface fully implemented”(CGI/1.0 を完全に実装)とし、旧式のスクリプトも名前の末尾に .pp を付ければ動くようにしました。
W3C の説明は CGI を “enables scripts to be shared between different server implementations (NCSA server, Plexus, etc)“(NCSA や Plexus など、別々のサーバーのあいだでスクリプトを共有できる)ものとし、旧式より CGI を使うよう強く勧めています。
本当に NCSA が最初だったのか
Section titled “本当に NCSA が最初だったのか”CGI の仕様を書き、12月の NCSA httpd 1.0 に実装したのは NCSA の McCool ですが、サーバーにプログラムを実行させる仕組みは、それ以前に CERN・NCSA・Plexus のそれぞれにありました。 CGI はそれらを1つにまとめたもので、McCool 本人も “it is not an NCSA-only feature as it was developed by several server authors and script writers”(何人ものサーバーの作者とスクリプトの作者で作ったので、NCSA だけの機能ではない)と書いています。
残した課題と、次に来たもの
Section titled “残した課題と、次に来たもの”要求のたびにプログラムを起動する
Section titled “要求のたびにプログラムを起動する”CGI では、アクセスが1回あるたびにプログラムが1回起動し、終わると消えます。
1996年4月29日の FastCGI の仕様は、プロセスを作って1件の要求に答えさせて終わらせる CGI に対し、プロセスを常駐させて続けて要求を受けさせる形をとりました。 同じ年には Apache に Perl を組み込む mod_perl が始まり、5月1日に 0.50a1 が公開されています。
安全と、HTML を組み立てる手間
Section titled “安全と、HTML を組み立てる手間”1997年の NCSA の入門は、CGI を置けることは “basically the equivalent of letting the world run a program on your system”(世界中の人に自分のシステムでプログラムを実行させるのとほぼ同じ)だと書きます。
そのため CGI は管理者が握る決まったディレクトリ(cgi-bin)に置き、一般の利用者はふつう CGI を作れない、と説明しています。
もう1つは書き方です。上の作例のように、ページ全体をプログラムが print で出力するので、見た目を変えるにもプログラムを直します。
PHP は、Perl の CGI を毎回起動する重さを避けて C で書き直した道具から始まり、HTML の中に処理を書く形をとって、1996年には Apache のモジュールとして CGI を通らずに動くようになりました。
2026年10月時点の立ち位置
Section titled “2026年10月時点の立ち位置”CGI/1.1 は、2004年10月に Apache の D. Robinson と K. Coar が RFC 3875 として記録しました。“The interface has been in use by the World-Wide Web (WWW) since 1993.”(1993年から Web で使われてきた)とあり、分類はインターネット標準ではない Informational です。
2026年10月28日に確かめた、主なソフトウェアの公式の記述は次のとおりです。
| ソフトウェア | 公式の記述 |
|---|---|
| Apache HTTP Server 2.4 | mod_cgi は標準で組み込まれる Base のモジュール。Unix でマルチスレッドの MPM を使うなら mod_cgid を使う |
| Go の net/http/cgi | 要求ごとにプロセスを起動するので、常駐するサーバーより一般に効率が悪く、主に既存のシステムとの互換のためにある |
| Python | PEP 594 で cgi・cgitb を削除する対象とし、3.11 で非推奨、2024年10月7日公開の 3.13 で削除 |
| Perl | 5.22.0 で CGI モジュールがコアの配布物から外された |
PEP 594 も理由を “every incoming request is handled in a new process”(要求ごとに新しいプロセスで処理する)ことに置いています。 Python と Perl は標準の配布物から外し、Go は既存のシステムとの互換のために残す一方、Apache には標準で入り続けています。 どれだけ使われているかを示す数字は、見つけられませんでした。
- 1993年、プログラムを実行させる方法はサーバーごとに違い、ゲートウェイの作者はサーバーと一緒でないとコードを配れませんでした。
- 1993年11月、NCSA の McCool が Plexus・CERN の作者やスクリプトの作者と議論し、環境変数と標準入出力で受け渡す取り決めを CGI と名付けました。
- CGI は言語ではなく取り決めなので、どの言語でも書け、同じプログラムを別のサーバーでも動かせるようになりました。
- 要求ごとにプロセスを起動する重さと、HTML を print で組み立てる手間が残り、FastCGI・mod_perl・PHP のモジュールが続きました。
- 2026年10月時点で、Apache は mod_cgi を標準で持ち、Go は互換のために残す一方、Python と Perl は標準の配布物から CGI のモジュールを外しています。
年表
NCSA httpd 0.3 が公開される。機能はファイルとディレクトリの一覧・gopher の構造を返すこと ksi.cpsc.ucalgary.ca
Nathan Torkington が CERN httpd 2.06 を改造し、検索語をシェルスクリプトに渡せるようにした差分を投稿する ksi.cpsc.ucalgary.ca
Tony Sanders が、Plexus・NCSA・CERN で共有できるゲートウェイへの受け渡しの形式を提案する ksi.cpsc.ucalgary.ca
Rob McCool が Common Gateway Protocol(CGP/1.0)の仕様案を www-talk に出す ksi.cpsc.ucalgary.ca
改訂した仕様案で、名前を CGI(Common Gateway Interface)に改める ksi.cpsc.ucalgary.ca
仕様を HTML の文書にまとめ、確定前の最後の意見募集をする ksi.cpsc.ucalgary.ca
最初の非 alpha 版 NCSA httpd 1.0 が、旧来の htbin の代わりに CGI/1.0 版のスクリプトを同梱して公開される ksi.cpsc.ucalgary.ca
処理を受け持つプロセスを常駐させる FastCGI の仕様 1.0 が出る fastcgi-archives.github.io
CGI/1.1 を記録した RFC 3875 が Informational として出る rfc-editor.org
Python 3.13 が公開され、標準ライブラリから cgi・cgitb モジュールが削除される docs.python.org
系譜
この技術が出てくる物語
出典
- 一次www-talk: Server Scripts(Rob McCool, 1993-11-14) ksi.cpsc.ucalgary.ca
- 一次www-talk: CGP/1.0 specification(Rob McCool, 1993-11-17) ksi.cpsc.ucalgary.ca
- 一次www-talk: revised CGI/1.0 specification(Rob McCool, 1993-11-19) ksi.cpsc.ucalgary.ca
- 一次www-talk: revised CGI/1.0 specification(George Phillips, 1993-11-19) ksi.cpsc.ucalgary.ca
- 一次www-talk: Re: CGP/1.0 specification(Ari Luotonen, 1993-11-18) ksi.cpsc.ucalgary.ca
- 一次www-talk: Re: httpd scripts for WAIS queries(Tony Sanders, 1993-11-11) ksi.cpsc.ucalgary.ca
- 一次www-talk: Re: CGI/1.0 status(Rob McCool, 1993-11-29) ksi.cpsc.ucalgary.ca
- 一次www-talk: NCSA httpd 1.0(Rob McCool, 1993-12-13) ksi.cpsc.ucalgary.ca
- 一次www-talk: a brief explanation of CGI(Rob McCool, 1993-12-13) ksi.cpsc.ucalgary.ca
- 一次www-talk: Execute a shell-script to search(Nathan Torkington, 1993-07-19) ksi.cpsc.ucalgary.ca
- 一次www-talk: gateway WWW - Oraperl(1993-07-22) ksi.cpsc.ucalgary.ca
- 一次Old CERN Server script support(Ari Luotonen, CERN, 1993。ミラー) www6.uniovi.es
- 一次CERN httpd 2.15 Release Notes w3.org
- 一次W3C httpd CGI/1.1 Script Support w3.org
- 一次CGI: Common Gateway Interface(NCSA の入門) hoohoo.ncsa.uiuc.edu 保存版
- 一次CGI Environment Variables(NCSA) hoohoo.ncsa.uiuc.edu 保存版
- 一次RFC 3875: The Common Gateway Interface (CGI) Version 1.1 rfc-editor.org
- 一次FastCGI Specification fastcgi-archives.github.io
- 一次History of mod_perl perl.apache.org
- 一次Apache Module mod_cgi(Apache HTTP Server 2.4) httpd.apache.org
- 一次net/http/cgi(Go) pkg.go.dev
- 一次PEP 594: Removing dead batteries from the standard library peps.python.org
- 一次What's New In Python 3.13 docs.python.org
- 一次perldelta for Perl 5.22.0 perldoc.perl.org