Cgi
python3
Windows10
webserver

python でお気楽Webサーバを構築してCGIのテスト。

はじめに

phtonを使ってお気楽にWebサーバを構築してみます。

  • Webサーバ用のドキュメントルートの作成
  • index.html の作成
  • Webサーバの起動
  • ブラウザで確認
  • CGIオプションを付けてWebサーバの起動
  • CGIの動作確認
  • POST/GETでCGIにデータの引き渡し確認

という手順で構築してみます。

前提

python3環境が構築されていること。
OSにはWindows10を利用する。

Webサーバ用のドキュメントルートの作成

どこに作成してもいいです。
適当に python_http_server などという名前のフォルダを作成してみましょう。

C:\> cd \
C:\> mkdir python_http_server
C:\> cd python_http_server
C:\python_http_server>

index.html の作成

C:\python_http_server> 直下に index.html を作成する。

index.html
<html>
<head>
<title>
Title: Hello Python World
</title>
</head>
<body>
<h1>
Hello Python World
</h1>
</body>
</html>

このように見えます。

C:\python_http_server>dir/w
 ドライブ C のボリューム ラベルは Windows です
 ボリューム シリアル番号は xxxx です

 C:\python_http_server のディレクトリ

[.]          [..]         index.html
               1 個のファイル                  97 バイト
               2 個のディレクトリ  xxxx バイトの空き領域

Webサーバの起動

python には標準でWebサーバライブラリが存在します。
ドキュメントルートとして作成済のC:\python_http_server で以下のコマンドを実行します。

C:\python_http_server>python -m http.server 8080

※ポート番号を省略した場合デフォルト値は8000です。

python3は http.server ですが、python2 だとコマンドが異なります。

python -m SimpleHTTPServer 8080

ブラウザで確認

http://localhost:8080 にアクセスしてみます。

index_html.png

と出力されました。

なお Microsoft Edgeではセキュリティの観点からlocalhostというURLは標準では見られないので about:flags にアクセスして解除する必要があるります。

about_flags_setting.png

変更してもダメな場合は、Chromeなど別のブラウザで確認してください。

CGI の実行

python3 でCGIを作成して実行させる場合は、

C:\python_http_server>python -m http.server 8080 --cgi

という “--cgi” オプションを付けて実行します。このとき cgi-bin というフォルダを作成し、その中にpython で作成したCGIを格納する必要があります。

例えば、

helloworld_jp.py
print ("Content-Type: text/html\n");
print ("こんにちは 日本語!");

と記載してcgi-binフォルダに保存してみます。

ブラウザで確認

http://localhost:8080/cgi-bin/helloworld_jp.py にアクセスすると…

hello_japanese.png

と表示されます。

日本語でエラー発生

python3で作成したCGIをSJISコード(ANSI)で保存していた場合、文字コードによる以下のようなエラーが起動したコマンドプロンプトで発生します。ブラウザは真白で何も表示されないので必ずUTF-8で保存してください。

127.0.0.1 - - [xx/xx/xx xx:xx:xx] command: C:\Anaconda3\python.exe -u C:\python_http_server\cgi-bin\helloworld_jp_sjis.py ""
127.0.0.1 - - [xx/xx/xx xx:xx:xx] b'  File "C:\\python_http_server\\cgi-bin\\helloworld_jp_sjis.py", line 2\r\nSyntaxError: Non-UTF-8 code starting with \'\\x82\' in file C:\\python_http_server\\cgi-bin\\helloworld_jp_sjis.py on line 2, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details\r\n'
127.0.0.1 - - [xx/xx/xx xx:xx:xx] CGI script exit status 0x1

日本語でおかしなことがあったらここをチェック!
https://qiita.com/goodboy_max/items/a35fd133141543f26845

POST/GETでデータの引き渡し

POST/GETが簡単に実行できるようにHTMLファイルを作成します。
保存する文字コードはくれぐれも注意するように!

post_get_test.html
<html>
<head>
<title>テストフォーム</title>
<meta http-equiv="content-type" charset="utf-8">
</head>
<body>
■POST
<form action="http://localhost:8080/cgi-bin/post_get_test.py" method="post">
  <div>
    <label for="name">名前</label>
    <input name="name" id="name" value="POST 名前">
  </div>
  <div>
    <label for="addr">住所</label>
    <input name="addr" id="addr" value="POST 住所">
  </div>
  <div>
    <button>POST実行</button>
  </div>
</form>
<hr>
■GET
<form action="http://localhost:8080/cgi-bin/post_get_test.py" method="get">
  <div>
    <label for="name">名前</label>
    <input name="name" id="name" value="GET 名前">
  </div>
  <div>
    <label for="addr">住所</label>
    <input name="addr" id="addr" value="GET 住所">
  </div>
  <div>
    <button>GET実行</button>
  </div>
</form>

参考<br>
https://docs.python.jp/3/library/cgi.html

</body>
</html>

実行するCGIのpythonファイルを作成し、cgi-bin 以下に配置します。
python の cgiモジュールは変数取得のためにGET/POSTメソッドによって
処理を変更する必要はないのでメチャ楽だ!

post_get_test.py
import cgi
import os

# デバッグ用
import cgitb
cgitb.enable()

print ("Content-Type: text/html")
print()

print ("<html><body>")

form = cgi.FieldStorage()
form_check = 0

# formでの変数有無チェック
if "name" not in form or "addr" not in form:
  form_check = 1

print ("<h1>{0}変数出力</h1>".format(os.environ['REQUEST_METHOD']))

# パラメータエラー時の対応 
# python の cgiモジュールは変数取得のためにGET/POSTメソッドによって
# 処理を変更する必要はないのでメチャ楽だ!
if form_check == 1 :
  print ("<h2>ERROR !</h2>")
  print ("Please fill in the name and addr fields.")
else :
  print ("<b>名前: </b>", form["name"].value)
  print ("<b>住所: </b>", form["addr"].value)

print ("</body></html>")

http://localhost:8080/post_get_test.html にアクセスしてみます。

post_get_test_html.png

POST実行してみます。

post_test_cgi.png

GET実行してみます。

get_test_cgi.png

以上です。