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で値を取得できたので、その入力値が表示されます。また「〇〇の入力がありません。」というエラーメッセージがなくなっています。