RestAPIを提供する際にHTTPリクエストにカスタムヘッダーを付けてもらって、チェック処理を入れたい場合、脳死状態で書くと下記のようになると思います。
このようにならないイケてる方は以降を見なくても大丈夫ですよ
from bottle import route, run, request, HTTPResponse
import json
@route('/version')
def version():
"""バージョン情報を返戻します。"""
api_key = request.get_header('X-Api-Key')
# ここでAPIキーのチェック
if api_key == 'XXXXXXXX':
resp = HTTPResponse(status=200, body=json.dumps({'version': '1.0.0'}))
resp.set_header('Content-Type', 'application/json')
return resp
else:
resp = HTTPResponse(status=401, body=json.dumps({'message': 'Illegal key'}))
resp.set_header('Content-Type', 'application/json')
return resp
if __name__ == "__main__":
run(host="0.0.0.0", port=8080, reloader=True)
これでもチェックするという要件は満たしているのですが、チェック処理が複数あるとどうでしょう?
どんどんif文
が入れ子になっていってソースコードの見通しが非常に悪くなってしまいます。
そこで、大活躍するのがデコレータ
です。
デコレータについては本記事の下部にある参考をご参照ください。
デコレータを使ったチェックの実装方法
FlaskでもBottleでも実装方法は一緒です。
コードがスッキリしましたね
もし複数のチェック処理が必要であればcheck_api_key
のようなデコレータを作ってエンドポイントに追加してください。
チェック処理は上から順に実行されますので、実行順序を気にされる場合は注意しましょう。
Bottleの例
from bottle import route, run, request, HTTPResponse
import functools
import json
def check_api_key(f):
"""X-Api-Keyを検証します。"""
@functools.wraps(f)
def _wrapper(*args, **kwargs):
api_key = request.get_header('X-Api-Key')
# ここでAPIキーのチェック
if api_key == 'XXXXXXXX':
return f(*args, **kwargs)
else:
resp = HTTPResponse(status=401, body=json.dumps({'message': 'Illegal key'}))
resp.set_header('Content-Type', 'application/json')
return resp
return _wrapper
@route('/version')
@check_api_key
def version():
"""バージョン情報を返戻します。"""
resp = HTTPResponse(status=200, body=json.dumps({'version': '1.0.0'}))
resp.set_header('Content-Type', 'application/json')
return resp
if __name__ == "__main__":
run(host="0.0.0.0", port=8080, reloader=True)
下記のようにHTTPリクエストを投げて動作確認しましょう。
curl -H "X-Api-Key: XXXXXXXX" http://localhost:8080/version