
コンピューティングにおいて、Common Gateway Interface ( CGI ) は、 Web サーバーが外部プログラムを実行してHTTPまたはHTTPSユーザー要求を 処理できるようにするインターフェイス仕様です。
このようなプログラムはスクリプト言語で書かれることが多く、一般的にCGIスクリプトと呼ばれますが、コンパイルされたプログラムが含まれることもあります。[ 1 ]
典型的な使用例は、ウェブユーザーがCGIを使用するウェブページでウェブフォームを送信する場合です。フォームのデータは、CGIスクリプトを示すURLを含むHTTPリクエストとしてウェブサーバーに送信されます。ウェブサーバーは新しいコンピュータプロセスでCGIスクリプトを起動し、フォームデータを渡します。CGIスクリプトは通常HTML形式で出力をウェブサーバーに渡し、サーバーはブラウザのリクエストへのレスポンスとしてそれをブラウザに返します。 [ 2 ]
1990年代初頭に開発されたCGIは、ウェブページをインタラクティブにするための最も初期の一般的な手法でした。クライアントからのリクエストがあるたびにCGIスクリプトを別のプロセスで実行する必要性があったため、様々な代替手段が開発されました。
歴史
1993年、国立スーパーコンピュータ応用研究所(NCSA)のチームは、www-talkメーリングリストでコマンドライン実行ファイルの呼び出し仕様を作成しました。[ 3 ] [ 4 ] [ 5 ]他のWebサーバー開発者もこれを採用し、それ以来、Webサーバーの標準となっています。 1997年11月、ケン・コー氏が議長を務める作業グループが発足し、NCSAによるCGIの定義をより正式に定義しました。[ 6 ]この作業の結果、CGIバージョン1.1を規定したRFC 3875が作成されました。RFCでは、以下の貢献者が具体的に言及されています。[ 2 ]
- Rob McCool ( NCSA HTTPd Web サーバーの作者)
- John Franks (GN Web サーバーの作者)
- Ari Luotonen ( CERN httpd Web サーバーの開発者)
- トニー・サンダース(Plexus Web サーバーの作者)
- ジョージ・フィリップス(ブリティッシュコロンビア大学のウェブサーバー管理者)
歴史的に、CGIプログラムはCプログラミング言語を使用して記述されることが多かった。RFC 3875「The Common Gateway Interface (CGI)」では、Cを使用したCGIを部分的に定義しており、[ 2 ]環境変数は「 Cライブラリルーチンgetenv()または変数environ によってアクセスされる」としている。
CGIという名称は、Webの黎明期に由来しています。当時、Webマスターはデータベースなどの既存の情報システムをWebサーバーに接続したいと考えていました。CGIプログラムはサーバー側で実行され、Webサーバーと既存の情報システムの間に 共通の「ゲートウェイ」を提供しました。
目的
伝統的に、Webサーバーには、ドキュメントコレクション、つまりサーバーに接続されたWebブラウザに送信できるファイルのセットとして指定されたディレクトリがあります。 [ 7 ]たとえば、Webサーバーが完全修飾ドメイン名www.example.comを持ち、そのドキュメントコレクションが/usr/local/apache/htdocs/ローカルファイルシステム(ドキュメントルート)に保存されている場合、Webサーバーはブラウザへの要求に応答して、http://www.example.com/index.htmlファイルのコピー/usr/local/apache/htdocs/index.html(存在する場合)を ブラウザに送信します
オンザフライで構築されるページの場合、サーバー ソフトウェアは要求を別のプログラムに延期し、結果を要求元のクライアント (通常はエンド ユーザーにページを表示する Web ブラウザー) に中継することがあります。
このようなプログラムでは通常、クエリ文字列やCookieなどの追加情報をリクエストに指定する必要があります。逆に、スクリプトはレスポンスを返す際に、リクエストのHTTPステータス、ドキュメントの内容(存在する場合)、ドキュメントの種類(HTML、PDF、プレーンテキストなど)など、HTTPがリクエストへのレスポンスに必要とするすべての情報を提供する必要があります。
当初、ブラウザ、ブラウザが通信するHTTPサーバー、そしてデータを処理して最終的にブラウザに結果を返すことが期待されるサーバー上のスクリプトの間でデータ交換を行うための標準化された方法は存在していませんでした。その結果、異なるHTTPサーバー間で相互に互換性がなく、スクリプトの移植性が損なわれていました。
この問題の認識により、データ交換の実行方法が仕様化され、CGIが開発されました。CGI仕様に準拠したサーバーソフトウェアによって呼び出されるWebページ生成プログラムは、実際にはC言語などの非スクリプト言語で記述されている場合でも、CGIスクリプトと呼ばれます。
CGI 仕様はすぐに採用され、Apache、Microsoft IIS、(拡張子付きの) Node.jsベースのサーバーなど、すべてのよく知られた HTTP サーバー パッケージで引き続きサポートされています。
CGIスクリプトの初期の使用法は、フォームの処理でした。HTMLの初期段階では、HTMLフォームには通常「action」属性と「submit」ボタンが用意されていました。submitボタンが押されると、「action」属性で指定されたURIがサーバーに送信され、フォームのデータがクエリ文字列として送信されます。「action」属性にCGIスクリプトが指定されている場合は、そのCGIスクリプトが実行され、HTMLページが生成されます。
展開
CGIをサポートするWebサーバーは、CGIスクリプトへの参照として機能するURLを解釈するように設定できます。一般的な慣例としては、ディレクトリツリーのベースにcgi-bin/ディレクトリを配置し、このディレクトリ内のすべての実行可能ファイル(セキュリティ上の理由から、他のディレクトリは含めない)をCGIスクリプトとして扱うことです。WebブラウザがCGIディレクトリ内のファイル(例:)を指すURLを要求するとhttp://example.com/cgi-bin/printenv.pl/with/additional/path?and=a&query=string、HTTPサーバーは単にそのファイル(/usr/local/apache/htdocs/cgi-bin/printenv.pl)をWebブラウザに送信するのではなく、指定されたスクリプトを実行し、スクリプトの出力をWebブラウザに渡します。つまり、スクリプトが標準出力に送信するものはすべて、Webサーバーを起動した端末ウィンドウに表示されるのではなく、Webクライアントに渡されます。もう1つの一般的な慣例として、ファイル名拡張子を使用することがあります。たとえば、CGIスクリプトに一貫して拡張子が付けられている場合.cgi、WebサーバーはそのようなファイルをすべてCGIスクリプトとして解釈するように設定できます。これは便利であり、多くのパッケージ化されたスクリプトで必要とされますが、リモートユーザーが適切な拡張子を持つ実行可能コードをアップロードできる場合、サーバーが攻撃を受ける可能性があります
CGI仕様では、リクエストとともに渡される追加情報がスクリプトに渡される方法が定義されています。Webサーバーは、渡された環境変数のサブセットを作成し、HTTP環境に関連する詳細を追加します。たとえば、スクリプト名の直後にスラッシュと追加のディレクトリ名がURLに追加された場合(この例では)、スクリプトが呼び出される前にそのパスが環境変数/with/additional/pathに格納されます。パラメータがHTTP GETリクエストを介してスクリプトに送信された場合(URLに疑問符が付加され、その後にparam=valueのペアが続く。この例では)、スクリプトが呼び出される前にそれらのパラメータが環境変数に格納されます。HTTP POSTリクエストを介して送信されたフォームパラメータなどのリクエストHTTPメッセージ本体は、スクリプトの標準入力に渡されます。スクリプトはこれらの環境変数またはデータを標準入力から読み取り、Webブラウザのリクエストに適応することができます。[ 8 ]PATH_INFO?and=a&query=stringQUERY_STRING
用途
CGIは、ユーザーからの入力情報を処理し、適切な出力を生成するためによく使用されます。CGIプログラムの例としては、Wikiを実装するプログラムがあります。ユーザーエージェントがエントリ名を要求すると、WebサーバーはCGIプログラムを実行します。CGIプログラムは、そのエントリのページのソース(存在する場合)を取得し、HTMLに変換して結果を出力します。WebサーバーはCGIプログラムからの出力を受け取り、ユーザーエージェントに送信します。次に、ユーザーエージェントが「ページを編集」ボタンをクリックすると、CGIプログラムはHTMLtextareaまたはその他の編集コントロールにページの内容を入力します。最後に、ユーザーエージェントが「ページを公開」ボタンをクリックすると、CGIプログラムは更新されたHTMLをそのエントリのページのソースに変換して保存します
セキュリティ
CGIプログラムは、デフォルトではWebサーバーのセキュリティコンテキストで実行されます。最初に導入されたとき、NCSA、Apache、CERN Webサーバーのリファレンスディストリビューションには、新しいCGIを利用するためのシェルスクリプトやCプログラムをどのようにコーディングできるかを示すサンプルスクリプトがいくつか提供されていました。そのようなサンプルスクリプトの1つは、シンプルな電話帳を実装したPHFと呼ばれるCGIプログラムでした
当時の他の多くのスクリプトと同様に、このスクリプトは関数 を利用していましたescape_shell_cmd()。この関数は、ユーザー入力から取得した引数をサニタイズし、その入力をUnixシェルに渡してWebサーバーのセキュリティコンテキストで実行することを目的としていました。しかし、このスクリプトはすべての入力を正しくサニタイズしておらず、シェルに改行を渡すことを許可していたため、複数のコマンドを実行できていました。これらのコマンドの実行結果はWebサーバーに表示されていました。Webサーバーのセキュリティコンテキストがこれを許可した場合、攻撃者によって悪意のあるコマンドが実行される可能性がありました。
これは、コードインジェクションと呼ばれる新しいタイプのWebベースの攻撃が広く蔓延した最初の事例でした。コードインジェクションは、WebユーザーからのサニタイズされていないデータによってWebサーバー上でコードが実行される可能性がある攻撃です。サンプルコードはデフォルトでインストールされていたため、攻撃は広範囲に広がり、1996年初頭には多くのセキュリティ勧告が発行されました。[ 9 ]
代替案
Webサーバーは、HTTPリクエストを受信するたびに、それを処理するための新しいCGIプロセスを作成し、HTTPリクエストの処理が完了したらCGIプロセスを破棄します。プロセスの作成と破棄は、プロセスの出力を生成する実際の作業よりも多くのCPU時間とメモリリソースを消費する可能性があります。特に、CGIプログラムを仮想マシンで解釈する必要がある場合は顕著です。HTTPリクエストの数が多い場合、結果として生じるワークロードはWebサーバーをすぐに圧倒する可能性があります
CGI プロセスの作成と破棄に伴う計算オーバーヘッドは、次の手法によって削減できます。
- インタプリタによって実行されるCGI プログラム( Perl、PHP、Pythonプログラムなど) ではなく、マシン コードにプリコンパイルされた CGI プログラム(CまたはC++プログラムからプリコンパイルされたものなど) 。
- Apache モジュール(
mod_perl、、mod_phpなどmod_python)、NSAPIプラグイン、ISAPIプラグインなどの Web サーバー拡張機能。これにより、Web サーバー内でホストされ、長時間実行されるアプリケーション プロセスで複数の要求を処理できるようになります。 - FastCGI、SCGI、およびAJP を使用すると、複数のリクエストを処理する長時間実行されるアプリケーション プロセスを外部で、つまり Web サーバーから独立してホストできます。各アプリケーション プロセスはソケットをリッスンします。Web サーバーは HTTP リクエストを処理し、動的コンテンツの場合のみ別のプロトコル (FastCGI、SCGI、または AJP) 経由でソケットに送信し、静的コンテンツは通常、Web サーバーによって直接処理されます。このアプローチでは必要なアプリケーション プロセス数が少なくなるため、Web サーバー拡張アプローチよりもメモリの消費量が少なくなります。また、アプリケーション プログラムを Web サーバー拡張に変換する場合とは異なり、FastCGI、SCGI、および AJP アプリケーション プログラムは Web サーバーから独立したままです。
- Jakarta EEは、 Jakarta ServletアプリケーションをWebコンテナ内で実行し、動的コンテンツとオプションで静的コンテンツを提供します。これにより、プロセスの作成と破棄のオーバーヘッドが、スレッドの作成と破棄のオーバーヘッドに置き換えられ、大幅に削減されます。また、プログラマーは、現在使用しているJakarta EEのバージョンのベースとなっているJava SEに付属するライブラリを利用できるようになります。
- スタンドアロンHTTPサーバー
- Webサーバーゲートウェイインターフェース(WSGI)は、 Pythonプログラミング言語で書かれた最新のアプローチです。PEP 3333 [ 10 ]
mod_wsgiで定義されており、Apacheモジュール、Gunicornウェブサーバー(NginxとDjangoのようなスクリプト/フレームワークの中間)、UWSGIなど、さまざまな方法で実装されています
ウェブアプリケーションにとって最適な構成は、アプリケーション固有の詳細、トラフィック量、トランザクションの複雑さによって異なります。これらのトレードオフを分析し、特定のタスクと時間予算に最適な実装を決定する必要があります。ウェブフレームワークは、ユーザーエージェントとのやり取りにおいて、CGIスクリプトを使用する代わりに、代替手段を提供します 。
参照
- CGI.pm – ウェブアプリケーション用Perlモジュール
- DOSゲートウェイインターフェース – DOSおよびLinux用のグラフィカルウェブブラウザリダイレクト先の簡単な説明を表示するページ
- Perlウェブサーバーゲートウェイインターフェース
- Rack(Webサーバーインターフェース) - プログラミング言語RubyのWebアプリケーション向けAPI仕様
- サーバーサイドインクルード – 解釈型サーバーサイドスクリプト言語
参考文献
- ^ D. Robinson、K. Coar(2004年10月)。Common Gateway Interface(CGI)バージョン1.1。doi : 10.17487 / RFC3875。RFC 3875情報。セクション1.4。
- ^ a b c D. Robinson; K. Coar (2004年10月). Common Gateway Interface (CGI) バージョン1.1 . doi : 10.17487/RFC3875 . RFC 3875 .情報提供
- ^ McCool, Rob (1993年11月14日). 「サーバースクリプト」 . www-talk (メーリングリスト) . 2019年5月15日閲覧
- ^ 「The Common Gateway Interface」 hoohoo.ncsa.uiuc.edu国立スーパーコンピュータ応用研究所(NCSA). 2010年1月27日時点のオリジナルよりアーカイブ。
- ^ 「CGI: Common Gateway Interface」 . w3.org . World Wide Web Consortium. 2009年12月19日時点のオリジナルよりアーカイブ。 2019年5月15日閲覧。
- ^ 「Common Gateway Interface RFCプロジェクトページ」 。2013年8月25日時点のオリジナルよりアーカイブ。
- ^ 「URLをファイルシステムの場所へマッピングする Apache HTTP Server バージョン2.2」。2014年7月15日時点のオリジナルよりアーカイブ。2014年7月16日閲覧。
- ^ネルソン、アン・フルチャー、ネルソン、ウィリアム・ハリス・モアヘッド (2001). 『Webデータベース構築による電子商取引の構築』 ボストン、マサチューセッツ州:アディソン・ウェスレー.
- ^ 「phf CGIスクリプトは改行文字を保護できない」。ソフトウェアエンジニアリング研究所CERTコーディネーションセンター。2020年7月28日時点のオリジナルよりアーカイブ。 2019年11月21日閲覧。
- ^ "PEP 3333 – Python Web Server Gateway Interface v1.0.1 | peps.python.org" . Python Enhancement Proposals (PEPs) . 2024年4月5日閲覧。
外部リンク
- CGIの発明
- RFC 3875 – 共通ゲートウェイ・インターフェース(CGI)バージョン1.1
- CGIプログラミング101:今日からCGIを学ぼう!、CGIチュートリアル