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 は、

といった URL でアクセスすると、pybitflyer というライブラリを利用して取得した、為替レートの情報を返してくれる。

// http://localhost:5000/api/rate/btc をコールした場合のレスポンス例
{
  "code": "btc",
  "bid" : "10000.5"
}

で、btc でも eth でもないパラメータをもらった場合は、パラメータが足りないということで 403 をレスポンスしたい。やり方を色々調べたが、Flask RESTful の場合は jsonify()json.dumps() で処理することなく直接連想配列を return してやり、return の2つ目でステータスコードを指定することで実現できた。

# この部分 ↓
return { 'message': 'Unknown code' }, 403

ついでに、tryexcept を使って、pybitflyer の処理に失敗した時は 500 を返すよう実装した。

return { 'message': 'Failed to get ticker' }, 500

この return 部分で

のように実装してしまうと、Flask RESTful の場合は TypeError になってしまうので、そのまま連想配列を書けば良い。

ついでに、Flask のデフォルト指定では5000番ポートでサーバが起動するが、コレは外部公開されていないので、80番ポートで外部に公開したい、といった場合は次のようにする必要がある。

# サーバを起動する
if __name__ == '__main__':
  app.run(debug = False, host = '0.0.0.0', port = 80)

ウェルノウン・ポートで公開する場合は root ユーザで実行する必要がある。