目的
この記事はpythonで最もシンプルなコードでテスト用スタブHTTPサーバを作成する方法を紹介します。
背景
プロジェクト開発の時に、別チームが開発するサーバへHTTP通信する場合があります。しかし、開発進捗など理由で相手のプロジェクトが使えない時に、こちらのシステムを先に制作または試験の指示が来たことがあります。では、セキュリティやパフォーマンスなど考慮せず、最低のコストで、一時的なスタブを作成する方法はありますか。
解決案
-
スタブの機能
GETリクエストを受信し、HTMLページを戻します。
POSTリクエストを受信し、特定値によって、事前に用意する結果をレスポンスとして戻します。 -
実装
BaseHTTPRequestHandlerを拡張し、GETとPOSTを処理するメソッドを作るimport os import sys import urllib.parse import html from http.server import BaseHTTPRequestHandler from http.server import HTTPServer from http import HTTPStatus PORT = 8000 #------------------------------------------------------- data = {} data["1234123412341234"] = "test1,test2,123,455,24,5,6,,4,,4344356,,34,ert" data["0000000000000000"] = "testdata2" #------------------------------------------------------- class StubHttpRequestHandler(BaseHTTPRequestHandler): server_version = "HTTP Stub/0.1" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def do_GET(self): enc = sys.getfilesystemencoding() title = "HTTP Stub" r = [] r.append('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" ' '"http://www.w3.org/TR/html4/strict.dtd">') r.append('<html>\n<head>') r.append('<meta http-equiv="Content-Type" ' 'content="text/html; charset=%s">' % enc) r.append('<title>%s</title>\n</head>' % title) r.append('<body>\n<h1>%s</h1>' % title) r.append('<hr>\n<ul>') r.append("Stub Opened.") r.append('</ul>\n<hr>\n</body>\n</html>\n') encoded = '\n'.join(r).encode(enc, 'surrogateescape') self.send_response(HTTPStatus.OK) self.send_header("Content-type", "text/html; charset=%s" % enc) self.send_header("Content-Length", str(len(encoded))) self.end_headers() self.wfile.write(encoded) def do_POST(self): enc = sys.getfilesystemencoding() length = self.headers.get('content-length') nbytes = int(length) rawPostData = self.rfile.read(nbytes) decodedPostData = rawPostData.decode(enc) postData = urllib.parse.parse_qs(decodedPostData) pan = postData["PAN"] resultData = [] for p in pan: resultData.append(data[p]) encoded = '\n'.join(resultData).encode(enc) self.send_response(HTTPStatus.OK) self.send_header("Content-type", "text/plain; charset=%s" % enc) self.send_header("Content-Length", str(len(encoded))) self.end_headers() self.wfile.write(encoded) handler = StubHttpRequestHandler httpd = HTTPServer(('',PORT),handler) httpd.serve_forever()
-
検証
まずはGETしてみます。ブラウザでアクセスして、ページが正常に表示できるはずです。
次にPOSTを確認します。import urllib.request import urllib.parse # 特定HEADER送信の例です。このサンプルに未使用 reqAddtionalHeaders = { 'X-Request=Process':"01" } data = urllib.parse.urlencode({"PAN":"1234123412341234"}) data = data.encode('utf-8') req = urllib.request.Request("http://localhost:8000", data,reqAddtionalHeaders) with urllib.request.urlopen(req) as f: print(f.read().decode('utf-8'))
検証環境
Windows10
Python3.7
最後
同機能なものは他の言語、例えばC#でのWCFかASP.NET、あるいはJAVAでのspringbootなどはもちろん、数多くのフレームワークができます。しかし、テスト用の一時的なもので、セキュリティ問題もエラー処理問題も不要な場合、やはりPythonが一番だと思います。環境の配置はほとんど必要なく、開発も短時間でできます。