D2MatE Top  this page

python CGIサーバ開発

 CGI (Common Gateway Interface) は、標準的なWebサーバから直接起動することで、外部プログラム(クライアント)との間で情報をやり取りするためのインターフェース/プログラムです。Webサーバが実行を許可しているディレクトリ・条件であれば、

  1. URLからquery parameterを解析し、HTTP出力するプログラムを作成する (例えばCGI.pyというファイル名とする)
  2. CGI.py を該当ディレクトリ (例えば public_html/cgi-bin) にコピーし、適切に owner (例えば apache) と permission (例えば rwxr-x---) を設定する
  3. https://server/cgi-bin/CGI.py?query_parameters でアクセス

という簡単な手順でデプロイできること、CGIプログラムも一般的なCLIと大きく変わらない (入力をquery parameterで取得する、出力にHTMLヘッダーとHTMLタグをつけるように変更) ため、CLIプログラム開発の経験があれば、プログラム開発も簡単です。

 一方で、最近では多くのWebフレームワークが普及し、CGIの使用は推奨されなくなりました。pythonでは、version 3.13においてcgiモジュールが廃止されました。
大きな理由は次の通りです。

詳細
  1. セキュリティの問題: CGIプログラムは構造を簡単にできるため、逆にセキュリティが甘くなる危険がある
    => Webフレームワークではセキュリティ対策がされ、コミュニティ・ユーザにより広く検証されている
  2. 機能の問題: CGIを開発する際は、基本的にサーバサイドのみで動かすことを想定しています。
    一方で、ユーザフレンドリでインタラクティブなWebアプリの開発をするには、クライアントサイドとの連携を独自に実装する必要があります。
    => Webフレームワークでは、URLによるrequestを対応する関数に接続する機能 (routing)や、サーバサイドとクライアントサイドの連携をはかる機構が埋め込まれています

しかしながら、先端Webフレームワークは標準的なWebサーバでは動かず、pythonのFlask/Dash/FastAPI/DjangoなどはWSGIと呼ばれる仕組みのサーバシステムが必要であり、Javascript/Node.jsではプログラムをdaemon化する必要があり、デプロイとメンテナンスに若干の手間が追加されます;。

 CGIであっても、適切にセキュリティ機能を実装することで上記のセキュリティの問題をクリアできますし、その開発過程を知ることにより、Webアプリのセキュリティを上げるのに重要な知識と経験が得られます。ただし、それでも、CGIには以下のようなデメリットもあります。

詳細

 本ページでは、Flask、Javascript的な記法が可能で、ユーザ認証、ファイルアクセス制限などのsecurity機能を実装したフレームワークを作ります。
また、JSONの受け渡しによるREST APIサーバとして働く python CGIプログラムの開発例を掲載します。


セキュリティを確保するための重要項目

Webアプリに必要な対策です。

以下はサーバ側の対策です。

セキュリティ対策HTTPヘッダー

ページのリソースの読み込みやスクリプトの実行を制御します

Content-Security-Policy (CSP):

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; object-src 'none'; frame-ancestors 'none';

X-Frame-Options 

 クリックジャッキング攻撃を防ぐために、ページが他のサイトでフレームに埋め込まれるのを制御する


Webアプリに必要な機能: requestの取得と応答

現在ではREST APIの枠組みを使うことが一般的です

REST APIの基本的な特徴:

以下のプログラム例 API_test.py では、一般的なJSONを用いたAPIを実装します。


生成AI (MS365 Copilot) による Flask-like CGIフレームワークの開発例

以下で掲載しているtkCGIApplication.pyは、この例からかなりの修正を行っています


Flask-like CGI Framework tkCGIApplication.py
Javascript-like HTML library tkHTMLDocument.py

以下の機能を実装しています。

Flask-like機能

その他機能

ファイル

API_test.py動作試験 プログラム

以下は古い参考プログラム


CGIアプリの開発手順

デバッグ情報の見方

import cgitb
cgitb.enable()  

を実行すれば、pythonのTracebackメッセージをブラウザに出力できる。
しかし、cgi、cgitbモジュールはpython3.13で廃止されたため、代替としてtracebackを 使うことができる。
import traceback
def handle_exception(exc_type, exc_value, exc_tb):
    """例外をHTML形式で出力"""
    print("Content-Type: text/html\n")
    print("<html><body>")
    print("<h2>Error:</h2>")
    print("<pre>")
    traceback.print_exception(exc_type, exc_value, exc_tb, file=sys.stdout)
    print("</pre>")
    print("</body></html>")
# エラーハンドラを設定
sys.excepthook = handle_exception

開発・デバッグ手順

  1. プログラム hogehoge.py を作成
  2. CLI として hogehoge.py を起動してデバッグ
    > python hogehoge.py
  3. hogehoge.py に query parameter を起動時引数として渡して動作検証
    > python hogehoge.py action=getFiles user=user password=pw
  4. 疑似POST動作で動作検証
     環境変数を設定して疑似POST関数を作って hogehoge.py を起動
     (API_test.py動作試験 プログラム (API_teest.pyを CLI として起動) を参照)
    > python query2cli.py
     
  5. > python http_server_me.py
    HTTPサーバを起動 
  6. hogehoge.pyをCGIとして呼び出すCLIプログラムで動作検証
     (API_test.py動作試験 プログラム (API_teest.pyを CGI として利用) を参照)
    > python query2cgi.py
     
  7. CGIはプログラム起動時のオーバヘッドが大きいため、パフォーマンスが必要な場合は
    FastCGI を使ってWSGIアプリ化する