【Mac】PythonでCGIが動く簡単なHTTPサーバー作りたい

# やること
CGIが動く簡単なローカルのHTTPサーバーをPythonで構築します。

簡単なものだとPerlではなくて、PythonでもCGIスクリプト書けそうということでやってみました。

# 環境
- MacOS Mojave
- Python 3.7.5

# CGIって何
> *CGIとはCommon Gateway Interfaceの略で、Webサーバー上でプログラムを使って処理した結果を表示させる機能のことです。*

（[CGIってなあに](http://www5.plala.or.jp/vaio0630/hp/cgi.htm)より引用）

要は、動的なウェブページを作ったりするのにブラウザから値取ってきたりしてサーバー側で処理してまた返すみたいなことが出来る機能のことだと思います。

# ローカルのHTTPサーバーの準備
まずはサーバーをたてないといけないのでローカルでHTTPサーバーをたてて、ウェブページを表示させます。

表示したいページを作成するために、作業したいディレクトリの中にIndex.htmlを書きます。
今回は送信するデータをfoodとseasonにします。

```index.html
<html>
    <head>
        <title>サーバーテスト</title>
        <meta http-equiv="content-type" charset="utf-8">
    </head>
    <body>
    <form action="/cgi-bin/cgi_test.py" method="POST">
        <div>
            <label for="name">好きな食べ物</label>
            <input type="text" name="food" value="りんご">
            <label for="season">好きな季節</label>
            <input type="text" name="season" value="冬">
            <button>送信</button>
        </div>
    </form>
    </body>
</html>
```

ここで注意しないといけないのは、アクションのパスを

```
"/cgi-bin/CGIスクリプトファイル名"
```
とすることです。
これがCGIスクリプトファイルへの相対パスとなっており、あとでここで指定したスクリプトファイル名を使ってスクリプトファイルを作成します。

# サーバーの起動テスト
一度サーバーを起動してみます。
ターミナルで起動させます。

```
$ python3 -m http.server 8080
```
実行すると下のようになると思います。
とりあえず8080番を使いましたが、使える番号であれば他の番号でも大丈夫です。

```
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
```
では、動いているか確認してみてください。
http://localhost:8080/
うまくいっていれば以下のようになると思います。
ちなみにまだ送信ボタンを押してもエラーになるはずです。
<img width="554" alt="server_test.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225947/16e4b6bc-11a4-8fd5-b7c0-ebb7e33ce93e.png">


# CGIスクリプトの記述
では、CGIスクリプトをPyhonで記述します。
作業ディレクトリ(index.htmlがあるディレクトリ)にcgi-binという名のディレクトリを作成し、その中にCGIスクリプトを記述していきます。
ファイル構造はこのようになります。

```
.
├── cgi-bin
│   └── cgi_test.py
└── index.html
```

また、ここでのファイル名は先ほどindex.html内で指定した名前を使用してください。

```cgi_test.py
#!/usr/bin/env python

import cgi
import cgitb
cgitb.enable()

print("Content-Type: text/html; charset=utf-8\n\n")

print("<html><body>")
form = cgi.FieldStorage()

for key in form:
    value = form[key].value
    print('<p>%s: %s</p>' % (key, value))

print("</body></html>")
```
ここでは1行目に必ず``#!/usr/bin/env python``と書くようにしてください。
これを書かないと``OSError: [Errno 8] Exec format error:``というエラーが発生します。
これはインタプリタの指定をしているのですが、詳しくは以下の記事などを参照してみてください。
[#!/bin/sh は ただのコメントじゃないよ！ Shebangだよ！(Qiita)](https://qiita.com/mohira/items/566ca75d704072bcb26f)

# CGIスクリプトを実行してみよう
では、実行していきます。
先ほどと同様にターミナルでサーバーを起動させます。
ここではCGIを実行させるために`--cgi`オプションを追加してください。

```
python3 -m http.server 8080 --cgi
```

http://localhost:8080/ で起動を確認したら、今回は送信を押して確認してみてください。
<img width="166" alt="cgi_test.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225947/e2dfd472-cb3e-1796-4854-26826e198e0d.png">
表示できていれば成功です。

# もしもエラーが出たら
送信ボタンを押しても表示されない場合、まずはどのようなエラーが出ているのかターミナルで確認してください。

### ・ パーミッションが755ではない(許可されていない)

```
code 403, message CGI script is not executable
```
→ cgi-binディレクトリ上のターミナルで`chmod 755 CGIスクリプト名.py`とする。

### ・ 文字コードが設定されていない

```
SyntaxError: Non-ASCII character '\xe5'
```

→ ファイルの一番上に`# coding:utf-8`と追加する。

# 参考
[python でお気楽Webサーバを構築してCGIのテスト。(Qiita)](https://qiita.com/goodboy_max/items/833d482827bf0efab45a)