Python - CGIプログラミング: 初心者のガイド
こんにちは、未来のPythonの魔法使いたち!この刺激的なCGIプログラミングの旅であなたのガイドとしてお互いに励まし合えることをとても楽しみにしています。長年コンピュータサイエンスを教えている者として、CGIはあなたのウェブアプリケーションを生き生きとしたものにする秘密のソースといえるでしょう。では、袖をまくって一緒に飛び込みましょう!
なんですかCGI?
CGIはCommon Gateway Interfaceの略で、それは口に出せばものすごい言葉に聞こえるかもしれませんが、それはあなたのウェブサーバとPythonスクリプトの間の翻訳者と考えてください。あなたのサーバとコードがスムーズにコミュニケーションを取るのを助ける優しくて親切な通訳者のようなものです。
CGIは、ユーザーの入力に反応する動的なウェブページを作成することができます。あなたの名前を挨拶するウェブサイトや、パーソナライズされたコンテンツを表示するウェブサイトを想像してみてください - それがCGIの魔法です!
ウェブブラウジング
CGIの詳細に進む前に、ウェブブラウジングの仕組みについて簡単に見ていきましょう。URLをブラウザに入力すると、以下のようなことが起こります:
- あなたのブラウザがウェブサーバにリクエストを送信します。
- ウェブサーバがリクエストを処理します。
- サーバが通常、HTMLページとして応答を送り返します。
- あなたのブラウザがこのHTMLをレンダリングし、見えるウェブページを表示します。
CGIは、ステップ3で動的なコンテンツを生成する際に関与します。
CGIアーキテクチャ図
以下は、CGIがウェブアーキテクチャにどのように適合するかを視覚化する簡単な図です:
+-------------+ HTTPリクエスト +-------------+
| ブラウザ | -----------------> | ウェブサーバ |
| | <----------------- | |
+-------------+ HTTPレスポンス +-------------+
|
| CGI
v
+-------------+
| CGIスクリプト |
| (Python) |
+-------------+
ウェブサーバのサポートと設定
ほとんどのウェブサーバ、ApacheやNginxを含めてもCGIをサポートしています。PythonとCGIを使用するためには、サーバがPythonスクリプトを実行できるよう設定する必要があります。これは通常、CGIスクリプト用の特別なディレクトリを設定し、このディレクトリ内のファイルを実行可能とすることによります。
例えば、Apacheでは以下のように設定ファイルに追加することができます:
<Directory /var/www/cgi-bin>
Options ExecCGI
AddHandler cgi-script .py
</Directory>
これは、/var/www/cgi-binディレクトリ内の.pyファイルをCGIスクリプトとして実行するようApacheに指示しています。
最初のCGIプログラム
最初のCGIプログラムを書いてみましょう!「Hello, World!」の古典的な例から始めます。CGIディレクトリにhello.py
という名前のファイルを作成します:
#!/usr/bin/env python3
print("Content-Type: text/html")
print()
print("<html>")
print("<head>")
print("<title>Hello World - First CGI Program</title>")
print("</head>")
print("<body>")
print("<h2>Hello World! This is my first CGI program</h2>")
print("</body>")
print("</html>")
これを分解してみましょう:
- 最初の行は、サーバにこのスクリプトをPythonで実行するよう指示しています。
-
Content-Type: text/html
は、ブラウザに私たちがHTMLを送信していることを示すHTTPヘッダです。 - 空の
print()
は、ヘッダとボディのレスポンスを分けるためです。 - その他は、動的に生成するHTMLになります。
このスクリプトをブラウザからアクセスすると、「Hello World! This is my first CGI program」と表示されるページが見えるはずです。
HTTPヘッダ
CGIプログラミングでは、コンテンツの前に正しいHTTPヘッダを送信することが重要です。最も一般的なヘッダはContent-Type
で、ブラウザに何のデータを送信しているかを示します。以下にいくつかの例を示します:
Content Type | 説明 |
---|---|
text/html | HTMLコンテンツ |
text/plain | 簡易テキスト |
image/jpeg | JPEG画像 |
application/json | JSONデータ |
常に、コンテンツの前に適切なContent-Typeヘッダを送信することを忘れないでください!
CGI環境変数
CGIスクリプトは、リクエストに関するさまざまな環境変数にアクセスできます。以下のスクリプトは、これらの変数のいくつかを表示します:
#!/usr/bin/env python3
import os
print("Content-Type: text/html")
print()
print("<html><body>")
print("<h2>Environment Variables:</h2>")
for param in os.environ.keys():
print(f"<b>{param:20}</b>: {os.environ[param]}<br>")
print("</body></html>")
このスクリプトは、ユーザーのブラウザタイプ、サーバー名など、CGIスクリプトに利用可能なすべての環境変数を表示します。
GETとPOSTメソッド
データをCGIスクリプトに送信するための2つの主要なメソッドがあります:GETとPOST。それぞれを見ていきましょう:
GETメソッド
GETメソッドは、データをURLの一部として送信します。以下に簡単な例を示します:
#!/usr/bin/env python3
import cgi
print("Content-Type: text/html")
print()
form = cgi.FieldStorage()
name = form.getvalue('name', 'World')
print("<html><body>")
print(f"<h2>Hello, {name}!</h2>")
print("</body></html>")
このスクリプトは、http://yourserver.com/cgi-bin/hello.py?name=Alice
のようなURLを使ってアクセスすると、「Hello, Alice!」と表示されます。
POSTメソッド
POSTメソッドは、HTTPリクエストのボディにデータを送信します。これは通常、フォームに使用されます。以下に例を示します:
#!/usr/bin/env python3
import cgi
print("Content-Type: text/html")
print()
form = cgi.FieldStorage()
name = form.getvalue('name', 'World')
email = form.getvalue('email', 'Not provided')
print("<html><body>")
print(f"<h2>Hello, {name}!</h2>")
print(f"<p>Your email is: {email}</p>")
print("</body></html>")
このスクリプトは、POSTメソッドを使用するHTMLフォームと一緒に使用されます。
異なるフォーム要素の処理
CGIはさまざまなフォーム要素を処理できます。いくつかの例を見ていきましょう:
チェックボックス
#!/usr/bin/env python3
import cgi
print("Content-Type: text/html")
print()
form = cgi.FieldStorage()
hobbies = form.getlist('hobby')
print("<html><body>")
print("<h2>Your hobbies:</h2>")
for hobby in hobbies:
print(f"<p>{hobby}</p>")
print("</body></html>")
ラジオボタン
#!/usr/bin/env python3
import cgi
print("Content-Type: text/html")
print()
form = cgi.FieldStorage()
gender = form.getvalue('gender', 'Not specified')
print("<html><body>")
print(f"<h2>Your gender: {gender}</h2>")
print("</body></html>")
テキストエリア
#!/usr/bin/env python3
import cgi
print("Content-Type: text/html")
print()
form = cgi.FieldStorage()
message = form.getvalue('message', 'No message provided')
print("<html><body>")
print("<h2>Your message:</h2>")
print(f"<p>{message}</p>")
print("</body></html>")
ドロップダウンボックス
#!/usr/bin/env python3
import cgi
print("Content-Type: text/html")
print()
form = cgi.FieldStorage()
country = form.getvalue('country', 'Not selected')
print("<html><body>")
print(f"<h2>Your country: {country}</h2>")
print("</body></html>")
CGIでクッキーを使用する
クッキーは、クライアントサイドで小さなデータを保存する方法です。ユーザーの偏好設定やセッション情報を保持するのに役立ちます。以下に、CGIでクッキーをどのように操作するかを示します:
クッキーの設定
#!/usr/bin/env python3
import cgi
from http import cookies
import datetime
# クッキーを作成
c = cookies.SimpleCookie()
c['lastvisit'] = str(datetime.datetime.now())
c['lastvisit']['expires'] = 365 * 24 * 60 * 60 # 1年後に有効期限切れ
print(c) # これはSet-Cookieヘッダを出力します
print("Content-Type: text/html")
print()
print("<html><body>")
print("<h2>Cookie set!</h2>")
print("</body></html>")
クッキーの取得
#!/usr/bin/env python3
import os
from http import cookies
print("Content-Type: text/html")
print()
if 'HTTP_COOKIE' in os.environ:
cookie_string = os.environ.get('HTTP_COOKIE')
c = cookies.SimpleCookie()
c.load(cookie_string)
lastvisit = c.get('lastvisit')
if lastvisit:
print(f"<h2>Your last visit was: {lastvisit.value}</h2>")
else:
print("<h2>This is your first visit!</h2>")
else:
print("<h2>This is your first visit!</h2>")
ファイルアップロードの例
ファイルアップロードの処理は少し複雑ですが、以下に簡単な例を示します:
#!/usr/bin/env python3
import cgi, os
import cgitb; cgitb.enable()
print("Content-Type: text/html")
print()
form = cgi.FieldStorage()
# ファイル名をここで取得
fileitem = form['filename']
# ファイルがアップロードされたかどうかをテスト
if fileitem.filename:
# ファイル名からパスを除いて、ディレクトリトラバーサリ攻撃を防ぐ
fn = os.path.basename(fileitem.filename)
open('/tmp/' + fn, 'wb').write(fileitem.file.read())
message = f'The file "{fn}" was uploaded successfully'
else:
message = 'No file was uploaded'
print(f"""\
<html>
<body>
<p>{message}</p>
</body>
</html>
""")
ファイルダウンロードのダイアログボックスを起動する方法?
ファイルダウンロードをトリガーするには、適切なヘッダを設定する必要があります:
#!/usr/bin/env python3
import os
filename = "example.txt" # これはあなたのファイル名
filepath = "/path/to/your/file" # これはあなたのファイルのパス
print("Content-Type: application/octet-stream")
print(f"Content-Disposition: attachment; filename={filename}")
print() # 空行、ヘッダの終わり
# ファイルコンテンツを送信
with open(os.path.join(filepath, filename), 'rb') as f:
print(f.read())
このスクリプトは、Content-Typeをapplication/octet-stream
に設定し、ブラウザにファイルをダウンロードさせるよう指示しています。Content-Dispositionヘッダは、ダウンロードするファイルの名前を提案します。
それで、皆さん、私たちのPythonでのCGIプログラミングの基本をカバーしました。覚えるには練習が必要ですので、この例を使って自由に实验し、自分のスクリプトを作成してみてください。幸せなコーディングを!CGIスクリプトが常にスムーズに動作することを願っています!
Credits: Image by storyset