小さな Python サーバーで HTTP ステータスをローカルテストする
ステータスコードだけでは応答が利用可能だとは分かりません。200 で HTML が返ったり、成功の 204 でデコードする本文がなかったりします。ローカルのモックなら、外部の応答サービスなしでこれらを再現できます。
この例は Python 3.11 以降と標準ライブラリだけを使います。127.0.0.1 にバインドし、少数の固定ルートに GET を実装します。開発用のモックであり、アプリケーションサーバーではありません。
処理の流れ
ハンドラーはヘッダーの前にステータスと表現を選びます。204 分岐は本文と Content-Length なしで終了し、それ以外は宣言したバイト数を書き込みます。
完全なサーバーを status_server.py に保存する
import argparse
import json
import re
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from urllib.parse import urlsplit
SUPPORTED = {200, 201, 204, 400, 404, 429, 500, 503}
class StatusHandler(BaseHTTPRequestHandler):
def do_GET(self):
path = urlsplit(self.path).path
match = re.fullmatch(r"/status/([0-9]{3})", path)
requested = int(match.group(1)) if match else None
status = requested if requested in SUPPORTED else 404
content_type = "application/json; charset=utf-8"
body = json.dumps({"status": status}).encode("utf-8")
if path == "/html/200":
status = 200
content_type = "text/html; charset=utf-8"
body = b"<html><body>not JSON</body></html>"
self.send_response(status)
if status == 204:
self.end_headers()
return
self.send_header("Content-Type", content_type)
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def log_message(self, format, *args):
pass
def make_server(port=8089):
return ThreadingHTTPServer(("127.0.0.1", port), StatusHandler)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--port", type=int, default=8089)
args = parser.parse_args()
if not 0 <= args.port <= 65535:
parser.error("port must be from 0 through 65535")
with make_server(args.port) as server:
print(f"http://127.0.0.1:{server.server_port}", flush=True)
try:
server.serve_forever()
except KeyboardInterrupt:
pass
Python HTTP サーバー API がリクエスト処理とスレッド化されたリスナーを提供します。未対応のパスやステータス番号には、モックの JSON 404 を返します。/html/200 は意図的に成功ステータスで HTML を返します。
一つのターミナルでサーバーを実行し、別のターミナルからリクエストを送ります。
python3 status_server.py --port 8089
curl -i http://127.0.0.1:8089/status/500
curl -i http://127.0.0.1:8089/html/200
curl -i http://127.0.0.1:8089/status/204
ポート 0 なら OS が空きポートを選び、サーバーが実際の URL を表示します。Ctrl+C で停止します。エラー応答も確認できるよう、curl コマンドは意図的に --fail を付けていません。
| リクエスト | ステータス | 表現 |
|---|---|---|
/status/200 |
200 | ステータス 200 を含む JSON |
/html/200 |
200 | JSON ではなく HTML |
/status/500 |
500 | ステータス 500 を含む JSON |
/status/204 |
204 | 本文も Content-Length もなし |
RFC 9110 は 204 応答の Content-Length を禁止しています。本文の有無は 2xx の確認とは分けて扱います。このモックはステータス・メディア型・メッセージの区切りを確認しますが、遅い応答、TLS、認証、リトライのタイミングは再現しません。クライアントのデコードとエラーシグナルは WebClient 応答テストへ進んでください。
コメント