Flask RESTful でステータスコードとともにレスポンスする
Flask RESTful (pipenv install flask_restful
) の小ネタ。
リクエストパラメータに応じてレスポンスを変えていくが、パラメータがない場合や、中での処理に失敗した時に、403 とか 500 とかをレスポンスしたいことがある。Flask RESTful では次のように実装すれば上手くいく。
from flask import Blueprint, request
from flask_restful import Api, Resource
# BitFlyer API
import pybitflyer
bit_flyer_api = pybitflyer.API()
# Blueprint
blueprint_api = Blueprint('api', __name__, url_prefix = '/api')
api = Api(blueprint_api)
# 指定の仮想通貨の為替レートを取得する (pybitflyer 使用)
class Rate(Resource):
def get(self, code):
try:
if(code == 'btc'):
return { 'code': code, 'bid': str(bit_flyer_api.ticker(product_code = 'BTC_JPY')['best_bid']) }
if(code == 'eth'):
return { 'code': code, 'bid': str(bit_flyer_api.ticker(product_code = 'ETH_JPY')['best_bid']) }
return { 'message': 'Unknown code' }, 403
except:
return { 'message': 'Failed to get ticker' }, 500
api.add_resource(Rate, '/rate/<string:code>')
この API は、
http://localhost:5000/api/rate/btc
http://localhost:5000/api/rate/eth
といった URL でアクセスすると、pybitflyer というライブラリを利用して取得した、為替レートの情報を返してくれる。
// http://localhost:5000/api/rate/btc をコールした場合のレスポンス例
{
"code": "btc",
"bid" : "10000.5"
}
- 参考 : Quickstart — Flask-RESTful 0.3.6 documentation
api.add_resource(Rate, '/rate/<string:code>')
部分の Resourceful Routing で実現している
で、btc
でも eth
でもないパラメータをもらった場合は、パラメータが足りないということで 403 をレスポンスしたい。やり方を色々調べたが、Flask RESTful の場合は jsonify()
や json.dumps()
で処理することなく直接連想配列を return
してやり、return
の2つ目でステータスコードを指定することで実現できた。
# この部分 ↓
return { 'message': 'Unknown code' }, 403
ついでに、try
・except
を使って、pybitflyer の処理に失敗した時は 500 を返すよう実装した。
return { 'message': 'Failed to get ticker' }, 500
この return
部分で
flask.jsonify({ 'message': '...' })
json.dumps({ 'message': '...' })
のように実装してしまうと、Flask RESTful の場合は TypeError
になってしまうので、そのまま連想配列を書けば良い。
- Flask のエラーハンドラメモ - ようへいの日々精進XP
- Flask の場合。
abort()
を使う手法
- Flask の場合。
- flaskでhttpステータスを返却する方法 - Qiita
- Flask の場合。
return
の2つ目でステータスコードを指定する
- Flask の場合。
- python - Flask API TypeError: Object of type 'Response' is not JSON serializable - Stack Overflow
is not JSON serializable
といったエラーの対処法を調べていた時の記事
- Flask RESTfulを試す - CLOVER🍀
- コレが答えだった
ついでに、Flask のデフォルト指定では5000番ポートでサーバが起動するが、コレは外部公開されていないので、80番ポートで外部に公開したい、といった場合は次のようにする必要がある。
# サーバを起動する
if __name__ == '__main__':
app.run(debug = False, host = '0.0.0.0', port = 80)
ウェルノウン・ポートで公開する場合は root ユーザで実行する必要がある。