Python
JSON
HttpServer
Python3

python3にてJSONを受け取ってJSONを返す簡単なサーバを立てる

More than 1 year has passed since last update.


やりたいこと

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'])をしているためです。


参考


その他

(モックだけなら手を抜いてもよいですが)入力チェックとエラー処理もちゃんとする方がよいです。

一応、エラー処理を追加しました。

コードをgithubにもおいています。

https://github.com/komorin0521/python_sandbox/blob/master/python3/server.py