PythonにおけるWSGIに対応したリクエスト処理となります。Python 3系におけるWSGIアプリケーションでは、returnで結果を返す際にencodeでbytesへ変換する必要があります。
※CGIでのリクエストの取得方法は「リクエストの取得 (CGI)」をご覧ください。
GET
GETリクエストの処理方法は下記の通りとなります。
import cgi
from wsgiref.simple_server import make_server
# HTML文字列
html = '''
<!DOCTYPE html>
<html>
<head>
<title>WSGI</title>
<meta charset="UTF-8">
</head>
<body>
{}
<hr>
{}
<hr>
{}
</body>
</html>
'''
def parse_query(params):
name = '未入力'
email = '未入力'
for param, value in params:
if param == 'name':
name = value
elif param == 'email':
email = value
errors = []
if name == '未入力':
errors.append('メールアドレスの入力がありません。')
if email == '未入力':
errors.append('お名前の入力がありません。')
return name, email, errors
def test_app(environ, start_response):
start_response('200 OK', [('Content-Type','text/html')])
# フォームから値を取得( GET )
query = cgi.parse_qsl(environ.get('QUERY_STRING'))
name, email, errors = parse_query(query)
result = 'お名前:{}<br />'.format(name)
result += 'メールアドレス: {}'.format(email)
# 結果を表示
return [html.format(
'リクエストは {} です。'.format(environ.get('REQUEST_METHOD')),
result,
'<br />'.join(errors)
).encode('UTF-8')]
# WSGIテストサーバーの作成
with make_server('', 8000, test_app) as httpd:
# テストサーバーによる待ち受け
print('Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...')
httpd.serve_forever()
47行目のcgi.parse_qslの戻り値はリストで、内包される値は各パラメータを保持したタプルとなります。たとえば次のようなURLでアクセスした場合の戻り値は[(‘name’, ‘test_user’), (‘email’, ‘test_user@example.com’)]のような形となります。
POST
POSTリクエストの処理方法は下記の通りとなります。次の例はGETでアクセスしてきたときには入力フォームを、POSTでアクセスしてきたときには入力値を表示する形です。
import cgi
from wsgiref.simple_server import make_server
# 入力HTML文字列
input_html = '''
<!DOCTYPE html>
<html>
<head>
<title>CGI</title>
<meta charset="UTF-8">
</head>
<body>
<form method="POST" action="/">
<input type="text" name="name">
<input type="text" name="email">
<input type="submit">
</form>
</body>
</html>
'''
# 結果HTML文字列
result_html = '''
<!DOCTYPE html>
<html>
<head>
<title>CGI</title>
<meta charset="UTF-8">
</head>
<body>
{}
<hr>
{}
<hr>
{}
</body>
</html>
'''
def parse_query(query):
name = '未入力'
email = '未入力'
for param, value in query:
if param == b'name':
name = value.decode('UTF-8')
elif param == b'email':
email = value.decode('UTF-8')
errors = []
if name == '未入力':
errors.append('メールアドレスの入力がありません。')
if email == '未入力':
errors.append('お名前の入力がありません。')
return name, email, errors
def test_app(environ, start_response):
start_response('200 OK', [('Content-Type','text/html')])
method = environ.get('REQUEST_METHOD')
# フォームから値を取得
if method == 'POST':
wsgi_input = environ['wsgi.input']
content_length = int(environ.get('CONTENT_LENGTH', 0))
query = cgi.parse_qsl(wsgi_input.read(content_length))
name, email, errors = parse_query(query)
result = 'お名前:{}<br />'.format(name)
result += 'メールアドレス: {}'.format(email)
# 結果を表示
return [result_html.format(
'リクエストは {} です。'.format(method),
result,
'<br />'.join(errors)
).encode('UTF-8')]
return [input_html.encode('UTF-8')]
# WSGIテストサーバーの作成
with make_server('', 8000, test_app) as httpd:
# テストサーバーによる待ち受け
print('Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...')
httpd.serve_forever()
cgi.parse_qslを用いるのはGETと変わりませんが、その過程が異なります。先に述べた通りGET/POSTで処理が分岐するため、次のURLへアクセスした時には入力フォームが表示されます。submitボタンを押すとPOSTアクセスとなるため、その入力値を取得・表示します。
またPOSTでは入力値がbytesで取得されます( [(b’name’, b’test_user’), (b’email’, b’test_user@example.com’)] のような形)。47行目、49行目でdecodeしてから値を格納している点に注意してください。
テストサーバーでの動作確認
先の例をmain.pyとして保存し、次のようなディレクトリ階層で配置するものとします。WSGIテストサーバーの処理はすでにソースコード内に記述してあるので、それを起動するだけです。
- c:
- python
- main.py
次のコマンドを入力し、まずはc:/pythonへ移動します。
cd c:/python
次に簡易テストサーバーを起動します。
python main.py
待ち受け状態となったらウェブブラウザを開き次のURLを入力してください。あとに続く画像がPOSTのサンプルプログラムにおけるウェブブラウザでの表示例です。

何も入力せずに送信ボタンを押すと、次のような画面となります。入力値を取得できなかったので、お名前やメールアドレスが未入力となっているはずです。

最初の入力フォームへ戻り、値を入力してから送信ボタンを押すと次のようになります。POSTで値を取得できたので、その入力値が表示されます。また「〇〇の入力がありません。」というエラーメッセージがなくなっています。

