たった数行で作るWebサーバー【Python x HTTPServer】
Pythonで簡易的なWebサーバーをたてられる HTTPServer の使い方・プログラミングを解説していきます(Python 3.9.4で動かします)。
Webサーバーを作る最小限のプログラム
simplest_server.py
from http.server import HTTPServer, SimpleHTTPRequestHandler
ip = "0.0.0.0"
port = 8887
httpd = HTTPServer(('', port), SimpleHTTPRequestHandler)
httpd.serve_forever()
はい、とても簡単ですね。 http://0.0.0.0:8887 へブラウザからアクセスできます。
ですが、このままだと httpd.serve_forever() で止まってしまい、それ移行のプログラムは実行されません。そこでPythonのスレッドをつかってサーバーを実行してみます。
PythonでHTTPサーバーをスレッドで動かす
こんな感じです。
server_with_thread.py
import threading
from http.server import HTTPServer, SimpleHTTPRequestHandler
html_root = "../html" # HTMLが格納されているディレクトリ
class Handler(SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, directory=html_root, **kwargs)
def log_message(self, format, *args):
pass # ログ出力を無視
def begin_dummy_server():
ip = "0.0.0.0"
port = 8887
httpd = HTTPServer(('', port), Handler)
print('HTTPServer began -> http://{}:{}'.format(ip, port))
# httpd.serve_forever()
server_thread = threading.Thread(target=httpd.serve_forever) # スレッドで動かす
# server_thread.daemon = True
server_thread.start()
if __name__ == "__main__":
begin_dummy_server()
print("hoge")
次の部分でスレッド登録させてます。
py
server_thread = threading.Thread(target=httpd.serve_forever)
server_thread.start()
threadingをインポートして、対象となる関数を target に登録&スタートさせればOKです。
HTMLディレクトリを指定したい
SimpleHTTPRequestHandlerを継承したハンドラーを使うことでHTMLファイルが格納されているディレクトリを指定できます。SimpleHTTPRequestHandlerのコンストラクターで、directory=引数にディレクトリを指定します。ログを非表示にしたい
サーバーへアクセスするとターミナルにいちいちログが出力されますが、ログを出力したくない場合は上のプログラムのとおり、 log_message をオーバーライドして pass させます。
自分のLAN IPアドレスを取得する
HTTPServer とは直接関係ありませんが、LAN内の端末からWebサーバーへアクセスしたい場合にIPアドレスを表示できると便利です。macOS上で実行するPythonでは、次のようにするとLAN内の自分のIPアドレスを取得できます。get_my_ip.py
import socket
host_list = socket.gethostbyname_ex(socket.gethostname())
lan_address = host_list[2][1]
ただし、PCにファイアーウォールがかかってるとアクセスできませんのでご注意ください。
リクエストされたヘッダーを表示したい
リクエストヘッダーを詳細に見たい場合があります。そんな時は do_GET をオーバライドして、 logging で標準出力させます。POSTデータの場合は do_POST も同様に追加してください。
capturing_header_server.py
from http.server import HTTPServer, SimpleHTTPRequestHandler
import socket
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
host_list = socket.gethostbyname_ex(socket.gethostname())
lan_address = host_list[2][1]
ip = "0.0.0.0"
port = 8887
class Handler(SimpleHTTPRequestHandler):
def do_GET(self):
logger.info(self.headers)
SimpleHTTPRequestHandler.do_GET(self)
httpd = HTTPServer(('', port), Handler)
print('HTTPServer began -> http://{}:{}'.format(lan_address, port))
httpd.serve_forever()