> ③Python CGIプログラミング – ネットワークエンジニアチュートリアル

③Python CGIプログラミング

Python CGIプログラミング




Common Gateway Interface(CGI)は、Webサーバーとカスタムスクリプトの間で情報を交換する方法を定義する一連の標準です。CGIの仕様は現在NCSAによって定義されています。

CGIとは

  • Common Gateway Interface(CGI)は、外部ゲートウェイプログラムやHTTPサーバーなどの情報サーバーと通信するためのプロトコルです
  • 現在のバージョンはCGI / 1.1であり、CGI / 1.2は現在策定中です。

Webブラウジング

CGIの概念を理解するためには、ハイパーリンクをクリックして特定のWebページまたはURLを参照するときに何が起こるかを見てみましょう。

  • ブラウザがHTTP Webサーバーに接続し、URL、つまりファイル名を要求します。
  • Web ServerはURLを解析し、ファイル名を検索します。そのファイルを見つけたら、それをブラウザに戻します。そうでなければ、あなたが間違ったファイルを要求したことを示すエラーメッセージを送ります。404エラーとかですね。
  • ウェブブラウザはウェブサーバから応答を受け取り、受信したファイルまたはエラーメッセージを表示する。

ただし、特定のディレクトリ内のファイルに対してファイルが返送されないように要求されるたびにHTTPサーバを設定することができます。代わりに、プログラムとして実行され、そのプログラムが出力したものがブラウザに表示されて表示されます。この機能はCommon Gateway InterfaceまたはCGIと呼ばれ、プログラムはCGIスクリプトと呼ばれます。これらのCGIプログラムには、Pythonスクリプト、PERLスクリプト、シェルスクリプト、CまたはC ++プログラムなどがあります。

CGIアーキテクチャ図

Webサーバーのサポートと構成

CGIプログラミングを進める前に、WebサーバーがCGIをサポートし、CGIプログラムを処理するように構成されていることを確認してください。HTTPサーバーによって実行されるすべてのCGIプログラムは、事前に設定されたディレクトリに保存されます。このディレクトリはCGIディレクトリと呼ばれ、慣例として/ var / www / cgi-binという名前が付けられています。慣例により、CGIファイルには拡張子があります。cgiを使用することもできますが、ファイルをPython拡張子.pyで保存することもできます。

デフォルトでは、Linuxサーバは/ var / wwwのcgi-binディレクトリにあるスクリプトのみを実行するように設定されています。他のディレクトリを指定してCGIスクリプトを実行する場合は、httpd.confファイルの次の行にコメントを付けます。

<Directory "/var/www/cgi-bin">
   AllowOverride None
   Options ExecCGI
   Order allow,deny
   Allow from all
</Directory>

<Directory "/var/www/cgi-bin">
Options All
</Directory>

ここでは、Webサーバーを正常に稼働させ、PerlやShellなどの他のCGIプログラムを実行できることを前提としています。

最初のCGIプログラム



#!/usr/bin/python

print "Content-type:text/html\r\n\r\n"
print '<html>'
print '<head>'
print '<title>Hello Word - First CGI Program</title>'
print '</head>'
print '<body>'
print '<h2>Hello Word! This is my first CGI program</h2>'
print '</body>'
print '</html>'

hello.pyをクリックすると、次の出力が生成されます。

Hello Word! This is my first CGI program

HTTPヘッダー

コンテンツタイプ:Content-type:text/html\r\n\r\nがコンテンツを理解するためにブラウザに送信されるHTTPヘッダの一部です。すべてのHTTPヘッダーは次の形式になります。

HTTP Field Name: Field Content

For Example
Content-type: text/html\r\n\r\n

その他の重要なHTTPヘッダーはほとんどありません.HTMLヘッダーは、CGIプログラミングで頻繁に使用します。

ヘッダ 説明
Content-type: 返されるファイルの形式を定義するMIME文字列。例はContent-type:text / htmlです。
Expires: Date 情報が無効になる日。これは、ページを更新する必要があるかどうかを判断するためにブラウザによって使用されます。有効な日付文字列は01 Jan 1998 12:00:00 GMTの形式です。
Location: URL 要求されたURLの代わりに返されるURL。このフィールドを使用して、要求を任意のファイルにリダイレクトできます。
Last-modified: Date リソースの最終変更日。
Content-length: N 返されるデータの長さ(バイト単位)。ブラウザはこの値を使用して、ファイルの推定ダウンロード時間を報告します。
Set-Cookie: String 文字列を渡されたクッキーを設定する

CGI環境変数

すべてのCGIプログラムは、以下の環境変数にアクセスできます。これらの変数は、CGIプログラムを書く際に重要な役割を果たします。

変数名 説明
CONTENT_TYPE コンテンツのデータ型。クライアントが添付されたコンテンツをサーバーに送信しているときに使用されます。たとえば、ファイルのアップロード。
CONTENT_LENGTH クエリ情報の長さ。POST要求に対してのみ使用できます。
HTTP_COOKIE キーと値のペアの形で設定されたクッキーを返します。
HTTP_USER_AGENT User-Agentのrequest-headerフィールドには、要求元のユーザエージェントに関する情報が含まれています。ウェブブラウザの名前です。
PATH_INFO CGIスクリプトのパス。
QUERY_STRING GETメソッド要求と共に送信されるURLエンコードされた情報。
REMOTE_ADDR 要求を行っているリモートホストのIPアドレス。これは、有用なロギングまたは認証のためのものです。
REMOTE_HOST 要求を行ったホストの完全修飾名。この情報が利用できない場合は、REMOTE_ADDRを使用してIRアドレスを取得できます。
REQUEST_METHOD 要求を行うために使用されたメソッド。最も一般的な方法はGETとPOSTです。
SCRIPT_FILENAME CGIスクリプトのフルパス。
SCRIPT_NAME CGIスクリプトの名前。
サーバーの名前 サーバーのホスト名またはIPアドレス
SERVER_SOFTWARE サーバーが実行しているソフトウェアの名前とバージョン。

 

#!/usr/bin/python

import os

print "Content-type: text/html\r\n\r\n";
print "<font size=+1>Environment</font><\br>";
for param in os.environ.keys():
  print "<b>%20s</b>: %s<\br>" % (param, os.environ[param])

GETメソッドとPOSTメソッド

あなたのブラウザからWebサーバーに、そして最終的にはあなたのCGIプログラムに情報を渡す必要がある場合、多くの困難に遭遇しているに違いありません。ほとんどの場合、ブラウザは2つの方法を使用して2つの情報をWebサーバーに渡します。これらのメソッドは、GETメソッドとPOSTメソッドです。

GETメソッドを使用した情報の受け渡し

GETメソッドは、ページリクエストに付加されたエンコードされたユーザー情報を送信します。ページとエンコードされた情報はどうなるか? 以下のようになります

http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2

GETメソッドは、ブラウザからWebサーバーに情報を渡すためのデフォルトのメソッドで、ブラウザのLocation:ボックスに表示される長い文字列を生成します。パスワードやその他の機密情報をサーバーに渡す場合は、GETメソッドを使用しないでください。GETメソッドにはサイズ制限があります。要求文字列には1024文字しか送信できません。GETメソッドは、QUERY_STRINGヘッダーを使用して情報を送信し、QUERY_STRING環境変数を介してCGIプログラムにアクセスできます。

キーと値のペアを任意のURLとともに連結するだけで情報を渡すことも、HTMLの<FORM>タグを使用してGETメソッドを使用して情報を渡すこともできます。

単純なURLの例:メソッドの取得

 

以下は、Webブラウザからの入力を処理するhello_get.pyスクリプトです。私たちはcgiモジュールを使用することで渡された情報に簡単にアクセスできるようになります。

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Hello - Second CGI Program</title>"
print "</head>"
print "<body>"
print "<h2>Hello %s %s</h2>" % (first_name, last_name)
print "</body>"
print "</html>"


この例では、HTML FORMと送信ボタンを使用して2つの値を渡します。この入力を処理するには、同じCGIスクリプトhello_get.pyを使用します。

簡単なフォームの例:GETメソッド

<form action="/cgi-bin/hello_get.py" method="get">
First Name: <input type="text" name="first_name">  <br />

Last Name: <input type="text" name="last_name" />
<input type="submit" value="Submit" />
</form>

上記のフォームの実際の出力は次のとおりです。姓と名を入力し、Submitボタンをクリックして結果を確認します。

ファーストネーム: 
苗字:  

POSTメソッドを使用した情報の受け渡し

CGIプログラムに情報を渡す信頼性の高い方法は、POSTメソッドです。これは、GETメソッドとまったく同じ方法で情報をパッケージ化します

以下はGETメソッドとPOSTメソッドを扱う同じhello_get.pyスクリプトです。

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Hello - Second CGI Program</title>"
print "</head>"
print "<body>"
print "<h2>Hello %s %s</h2>" % (first_name, last_name)
print "</body>"
print "</html>"

上記の例と同じ例をもう一度見てみましょう.HTMLフォームと送信ボタンを使用して2つの値を渡します。この入力を処理するには、同じCGIスクリプトhello_get.pyを使用します。

<form action="/cgi-bin/hello_get.py" method="post">
First Name: <input type="text" name="last_name"><br />
Last Name: <input type="text" name="last_name" />

<input type="submit" value="Submit" />
</form>

上記のフォームの実際の出力は次のとおりです。姓と名字を入力して[送信]ボタンをクリックすると結果が表示されます。

ファーストネーム: 
苗字:  

チェックボックスデータをCGIプログラムに渡す

チェックボックスは、複数のオプションを選択する必要がある場合に使用されます。

ここに2つのチェックボックスを持つフォームのHTMLコードの例を示します。

<form action="/cgi-bin/checkbox.cgi" method="POST" target="_blank">
<input type="checkbox" name="maths" value="on" /> Maths
<input type="checkbox" name="physics" value="on" /> Physics
<input type="submit" value="Select Subject" />
</form>

このコードの結果は、次の形式です。

 maths physics 

以下はcheckbox.cgiスクリプトで、チェックボックスボタンのWebブラウザからの入力を処理します。

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('maths'):
   math_flag = "ON"
else:
   math_flag = "OFF"

if form.getvalue('physics'):
   physics_flag = "ON"
else:
   physics_flag = "OFF"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Checkbox - Third CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> CheckBox Maths is : %s</h2>" % math_flag
print "<h2> CheckBox Physics is : %s</h2>" % physics_flag
print "</body>"
print "</html>"

ラジオボタンデータをCGIプログラムに渡す

ラジオボタンは、1つのオプションだけを選択する必要がある場合に使用されます。

ここには、2つのラジオボタンがあるフォームのHTMLコード例があります。

<form action="/cgi-bin/radiobutton.py" method="post" target="_blank">
<input type="radio" name="subject" value="maths" /> Maths
<input type="radio" name="subject" value="physics" /> Physics
<input type="submit" value="submit" />
</form>

このコードの結果は、次の形式です。

 maths physics 

以下は、ラジオボタンのWebブラウザからの入力を処理するradiobutton.pyスクリプトです:

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('subject'):
   subject = form.getvalue('subject')
else:
   subject = "Not set"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Radio - Fourth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"

テキストエリアデータをCGIプログラムに渡す

TEXTAREA要素は、複数行のテキストをCGIプログラムに渡す必要がある場合に使用されます。

以下は、TEXTAREAボックスを持つフォームのHTMLコード例です。

<form action="/cgi-bin/textarea.py" method="post" target="_blank">
<textarea name="textcontent" cols="40" rows="4">
Type your text here...
</textarea>
<input type="submit" value="Submit" />
</form>

このコードの結果は、次の形式です。

 

以下は、Webブラウザからの入力を処理するためのtextarea.cgiスクリプトです。

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('textcontent'):
   text_content = form.getvalue('textcontent')
else:
   text_content = "Not entered"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>";
print "<title>Text Area - Fifth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Entered Text Content is %s</h2>" % text_content
print "</body>"

ボックスデータをCGIプログラムに渡す

ドロップダウンボックスは、利用可能なオプションが多数ある場合に使用されますが、1つまたは2つだけが選択されます。

1つのドロップダウンボックスを持つフォームのHTMLコードの例を次に示します。

<form action="/cgi-bin/dropdown.py" method="post" target="_blank">
<select name="dropdown">
<option value="Maths" selected>Maths</option>
<option value="Physics">Physics</option>
</select>
<input type="Submit" value="Submit"/>
</form>

このコードの結果は、次の形式です。

 

以下は、Webブラウザからの入力を処理するdropdown.pyスクリプトです。

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('dropdown'):
   subject = form.getvalue('dropdown')
else:
   subject = "Not entered"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Dropdown Box - Sixth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"

CGIでのCookieの使用

HTTPプロトコルはステートレスプロトコルです。商用ウェブサイトでは、異なるページ間でセッション情報を維持する必要があります。たとえば、多数のページを完了した後に1人のユーザー登録が終了します。すべてのWebページでユーザーのセッション情報を維持する方法は?

多くの状況で、クッキーを使用することは、より良い訪問者体験やサイト統計に必要な設定、購入、手数料、およびその他の情報を覚えて追跡する最も効率的な方法です。

使い方

あなたのサーバーは、クッキーの形で訪問者のブラウザにデータを送信します。ブラウザはクッキーを受け入れるかもしれません。そうであれば、訪問者のハードドライブにプレーンテキストレコードとして保存されます。今、訪問者があなたのサイトの別のページに到着すると、そのクッキーを取得することができます。取得したサーバーは、格納された内容を知っている/記憶しています。

Cookieは、5つの可変長フィールドのプレーンテキストのデータレコードです。

  • Expires:クッキーが期限切れになる日付。これが空白の場合、訪問者がブラウザを終了するとCookieの有効期限が切れます。
  • ドメイン:サイトのドメイン名。
  • パス: Cookieを設定するディレクトリまたはWebページへのパス。任意のディレクトリまたはページからCookieを取得する場合は、空白になることがあります。
  • セキュア:このフィールドに「secure」という単語が含まれている場合、クッキーはセキュアサーバーでのみ取得できます。このフィールドが空白の場合、そのような制限は存在しません。
  • Name = Value: Cookieは、キーと値のペアの形式で設定および取得されます。

クッキーの設定

ブラウザにクッキーを送信するのはとても簡単です。これらのCookieは、Content-typeフィールドの前にHTTP Header beforeとともに送信されます。ユーザーIDとパスワードをクッキーとして設定すると仮定します。クッキーの設定は以下のように行います –

#!/usr/bin/python

print "Set-Cookie:UserID=XYZ;\r\n"
print "Set-Cookie:Password=XYZ123;\r\n"
print "Set-Cookie:Expires=Tuesday, 31-Dec-2007 23:12:40 GMT";\r\n"
print "Set-Cookie:Domain=www.tutorialspoint.com;\r\n"
print "Set-Cookie:Path=/perl;\n"
print "Content-type:text/html\r\n\r\n"
...........Rest of the HTML Content....

この例から、Cookieの設定方法を理解している必要があります。Cookieを設定するには、Set-Cookie HTTPヘッダーを使用します。

Expires、Domain、PathなどのCookie属性を設定することはオプションです。マジックライン“Content-type:text / html \ r \ n \ r \ n”を送信する前にクッキーが設定されていることに注目してください。

クッキーの取得

すべての設定されたクッキーを取得することは非常に簡単です。クッキーはCGI環境変数HTTP_COOKIEに格納され、以下の形式をとります –

key1=value1;key2=value2;key3=value3....

次に、Cookieを取得する方法の例を示します。

# Import modules for CGI handling 
from os import environ
import cgi, cgitb

if environ.has_key('HTTP_COOKIE'):
   for cookie in map(strip, split(environ['HTTP_COOKIE'], ';')):
      (key, value ) = split(cookie, '=');
      if key == "UserID":
         user_id = value

      if key == "Password":
         password = value

print "User ID  = %s" % user_id
print "Password = %s" % password

これは上記のスクリプトで設定されたクッキーに対して以下の結果をもたらします。

User ID = XYZ
Password = XYZ123

ファイルアップロードの例

ファイルをアップロードするには、HTMLフォームのenctype属性にmultipart / form-dataを設定する必要があります。ファイルタイプの入力タグは、「参照」ボタンを作成します。

<html>
<body>
   <form enctype="multipart/form-data" 
                     action="save_file.py" method="post">
   <p>File: <input type="file" name="filename" /></p>
   <p><input type="submit" value="Upload" /></p>
   </form>
</body>
</html>

このコードの結果は、次の形式です。

ファイル: 

上記の例は、サーバーにファイルをアップロードするユーザーを意図的に保存することはできませんが、サーバーで上記のコードを試すことができます。

ここに、ファイルのアップロードを処理するためのスクリプトsave_file.pyがあります。

import cgi, os
import cgitb; cgitb.enable()

form = cgi.FieldStorage()

# Get filename here.
fileitem = form['filename']

# Test if the file was uploaded
if fileitem.filename:
   # strip leading path from file name to avoid 
   # directory traversal attacks
   fn = os.path.basename(fileitem.filename)
   open('/tmp/' + fn, 'wb').write(fileitem.file.read())

   message = 'The file "' + fn + '" was uploaded successfully'
   
else:
   message = 'No file was uploaded'
   
print """\
Content-Type: text/html\n
<html>
<body>
   <p>%s</p>
</body>
</html>
""" % (message,)

Unix / Linuxで上記のスクリプトを実行すると、ファイルセパレータを次のように置き換える必要があります。そうでなければ、open()文の上のWindowsマシンでうまく動作するはずです。

fn = os.path.basename(fileitem.filename.replace("\\", "/" ))

「ファイルのダウンロード」ダイアログボックスを表示する方法

場合によっては、ユーザーがリンクをクリックできるオプションを提供し、実際のコンテンツを表示するのではなく、「ファイルのダウンロード」ダイアログボックスをユーザーにポップアップさせることが望ましい場合があります。これは非常に簡単で、HTTPヘッダーで実現できます。このHTTPヘッダーは、前のセクションで説明したヘッダーとは異なります。

たとえば、指定したリンクからFileNameファイルをダウンロードできるようにするには、その構文は次のとおりです。

#!/usr/bin/python

# HTTP Header
print "Content-Type:application/octet-stream; name=\"FileName\"\r\n";
print "Content-Disposition: attachment; filename=\"FileName\"\r\n\n";

# Actual File Content will go here.
fo = open("foo.txt", "rb")

str = fo.read();
print str

# Close opend file
fo.close()

前のページ②Pythonの正規表現

次のページ④Pythonデータベースアクセス

スポンサーリンク

ネットワークエンジニアになりたければ下記から無料相談会に参加!
なんと無料で授業を受けれてエンジニアになれます

投稿日:

執筆者: