31
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-10-05

やりたいこと

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にもおいています。

31
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?