Symfoware

Symfowareについての考察blog

Falcon JSON形式のAPIとしてのカスタマイズ(リクエスト処理前にデータ加工)

表現が難しいのですが、例えばJSONデータのPOSTのみを受け付けるAPIサーバーを作成する場合、
リクエストの処理で毎回JSON形式のチェックやデータのパース処理を書くのは面倒です。

Falconでは、処理前に共通して行いたい処理をmiddlewareとして定義できます。

こちらのサンプルを参考に試してみます。
https://github.com/falconry/falcon/blob/master/README.rst


middleware



サンプルを参考に、事前にjson形式に変換。
レスポンスも自動的にjson形式に変換するmiddlewareはこんな感じになりました。


  1. # -*- coding:utf-8 -*-
  2. import json
  3. import falcon
  4. # 事前に処理を行うクラス
  5. class JSONTranslator(object):
  6.     def process_request(self, req, resp):
  7.         
  8.         # リクエストヘッダーをチェック
  9.         if not req.client_accepts_json:
  10.             raise falcon.HTTPNotAcceptable(
  11.                 'This API only supports responses encoded as JSON.')
  12.         if req.method in ('POST', 'PUT'):
  13.             if 'application/json' not in req.content_type:
  14.                 raise falcon.HTTPUnsupportedMediaType(
  15.                     'This API only supports requests encoded as JSON.')
  16.         
  17.         # req.stream corresponds to the WSGI wsgi.input environ variable,
  18.         # and allows you to read bytes from the request body.
  19.         #
  20.         # See also: PEP 3333
  21.         if req.content_length in (None, 0):
  22.             # Nothing to do
  23.             return
  24.         
  25.         # post値をjson形式に変換
  26.         body = req.stream.read()
  27.         if not body:
  28.             raise falcon.HTTPBadRequest('Empty request body')
  29.         try:
  30.             req.context['doc'] = json.loads(body.decode('utf-8'))
  31.         except (ValueError, UnicodeDecodeError):
  32.             raise falcon.HTTPError(falcon.HTTP_753, 'Malformed JSON')
  33.     def process_response(self, req, resp, resource):
  34.         if 'result' not in req.context:
  35.             return
  36.         
  37.         # resultの値をjson形式に変換して返却
  38.         resp.body = json.dumps(req.context['result'])
  39. # 処理の本体
  40. class HelloResource(object):
  41.     
  42.     # postされた時の動作
  43.     def on_post(self, req, res):
  44.         
  45.         doc = req.context['doc']
  46.         
  47.         req.context['result'] = {'hello': doc['name']}
  48. # 事前処理を行うクラスを指定
  49. app = falcon.API(middleware=[
  50.     JSONTranslator()
  51. ])
  52. # URLパラメータを指定
  53. app.add_route("/", HelloResource())
  54. if __name__ == "__main__":
  55.     from wsgiref import simple_server
  56.     httpd = simple_server.make_server("0.0.0.0", 8000, app)
  57.     httpd.serve_forever()




テスト用のプログラムです。


  1. # -*- coding:utf-8 -*-
  2. import json
  3. import urllib2
  4. url = 'http://192.168.1.102:8000'
  5. values = {'name' : 'symfo'}
  6. data = json.dumps(values)
  7. headers = { 'Content-type' : 'application/json' }
  8. req = urllib2.Request(url, data, headers)
  9. response = urllib2.urlopen(req)
  10. # 戻り値を解析
  11. body = response.read()
  12. response.close()
  13. data = json.loads(body)
  14. print(data['hello'])




狙い通りの結果が得られました。


$ python api_test.py
symfo




関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2016/05/14(土) 21:35:50|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<APIフレームワークFalconをbjoernで動作させる | ホーム | Falcon URLによる分岐と値の取得>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1883-a3b9253a
この記事にトラックバックする(FC2ブログユーザー)