やりたいこと
python3で標準モジュールだけでPOSTしたら、JSONで結果を返すようにする
なにかモックで作成するときとかはさくっとできるので便利かなと思います。
Flaskとかもあるけど、ぱっと試したいときには便利かもです。
環境
- OS: Ubuntu 14.04
- Python : python 3.4.7
コード
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = "omori"
__version__ = "1.0.0"
import argparse
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
class MyHandler(BaseHTTPRequestHandler):
"""
Received the request as json, send the response as json
please you edit the your processing
"""
def do_POST(self):
try:
content_len=int(self.headers.get('content-length'))
requestBody = json.loads(self.rfile.read(content_len).decode('utf-8'))
response = { 'status' : 200,
'result' : { 'hoge' : 100,
'bar' : 'bar' }
}
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
responseBody = json.dumps(response)
self.wfile.write(responseBody.encode('utf-8'))
except Exception as e:
print("An error occured")
print("The information of error is as following")
print(type(e))
print(e.args)
print(e)
response = { 'status' : 500,
'msg' : 'An error occured' }
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
responseBody = json.dumps(response)
self.wfile.write(responseBody.encode('utf-8'))
def importargs():
parser = argparse.ArgumentParser("This is the simple server")
parser.add_argument('--host', '-H', required=False, default='localhost')
parser.add_argument('--port', '-P', required=False, type=int, default=8080)
args = parser.parse_args()
return args.host, args.port
def run(server_class=HTTPServer, handler_class=MyHandler, server_name='localhost', port=8080):
server = server_class((server_name, port), handler_class)
server.serve_forever()
def main():
host, port = importargs()
run(server_name=host, port=port)
if __name__ == '__main__':
main()
たった、こんだけ!楽ですね~。
python3系では、HTTPのサーバ関連は、http.serverに集約されたとのこと。
BaseHTTPRequestHandlerの中の'do_POST'をオーバライドすることで、
リクエストに応じて、結果を返すようにできる
json.loads(self.rfile.read(content_len).decode('utf-8'))
で、リクエストのボディを読み込んだ後、
json.loads
にて、jsonをパースしてます。
self.send_response'と
self.send_header で、HTTPのレスポンスコードと、ヘッダ部を書いてます。 そして、
responseに結果を格納したうえで、jsonにdumpして、
self.wfile.write`にて結果を返してます。
確認
上記のコードをtest_server.py
などとして、
python test_server.py
を実行
そして、別ターミナルで下記のようにリクエストしてみてください。
リクエスト例
curl -XPOST -d '{ "hoge" : 1, "bar" : "bar" }' http://localhost:8080
サーバ側でbar
というキーをprintしているので、上記のコードのままだとbar
がなければエラーになりますので、ご注意を。
レスポンス
{"bar": "bar", "hoge": 100}
(responseで定義した辞書型がjsonになって出力される)
サーバ側の出力例
127.0.0.1 - - [05/Oct/2017 23:18:36] "POST / HTTP/1.1" 200 -
barが出力されるのは、サーバ側で、print(requestBody['bar'])
をしているためです。
参考
-
pythonの公式ドキュメント
https://docs.python.jp/3/library/http.server.html -
PythonでJSONを受けて処理をする
http://d.hatena.ne.jp/matasaburou/20151003/1443882557 -
BaseHTTPServer – web サーバを実装するベースクラス
http://ja.pymotw.com/2/BaseHTTPServer/
その他
(モックだけなら手を抜いてもよいですが)入力チェックとエラー処理もちゃんとする方がよいです。
一応、エラー処理を追加しました。
コードをgithubにもおいています。