falconを使ってみた


Published on 2018-10-16

はじめに

Hugoをおいているwebサーバーに画像や、mdファイルをアップロードするためのapiサーバーとしてfalconを使ってみた。ORMなど必要なく、簡単なアップロードができれば良いということで、軽量さとシンプルさが特徴のfalconを使う。

簡単なtipsをメモしておく。

シンプルな例

falconの公式に乗っているように、シンプルな例は次のようになる。

# sample.py

import falcon

class QuoteResource:
    def on_get(self, req, resp):
        """Handles GET requests"""
        quote = {
            'quote': (
                "I've always been more interested in "
                "the future than in the past."
            ),
            'author': 'Grace Hopper'
        }

        resp.media = quote

api = falcon.API()
api.add_route('/quote', QuoteResource())

処理シーケンス

falconにはmiddlewareの他に、hooksというものが使える。 hooksを含めた処理シーケンスは次のようになる。

Middleware's process_request
Middleware's process_resource
Hook's before
Resource's on_****
Hook's after
Middleware's process_response

引用:https://qiita.com/yohjizzz/items/f46bb3bc7b7c40768836

middlewareを使った、認証系の共通処理はよく見るが、hookが使えるのは良いですね。

hooks

hooksは以下のように使う。(公式)

def validate_image_type(req, resp, resource, params):
	....

@falcon.before(validate_image_type)
def on_post(self, req, resp):
    pass

処理を差し込みたいメソッドにでコレーターでつけるだけ。

middleware

corsくらいしか使わなかったが、dbのconnection poolとかに使うようのものとかあるんだろう。(公式)

class CORSMiddleware:
    def process_request(self, req, resp):
        resp.set_header('Access-Control-Allow-Origin', '*')

エラーハンドリング

routeが見つからなかった時に、エラーリスポンスを返したいときは以下のようにする。(公式)

class Index(object):
    def on_get(self, req, resp):
        resp.body = json.dumps({"message":"ok"})

app = falcon.API()
app.add_route("/", Index())
app.add_sink(handle_404, '')

if __name__ == "__main__":
    from wsgiref import simple_server
    httpd = simple_server.make_server("127.0.0.7", 8000, app)
    httpd.serve_forever()

exceptionなどが起きた場合でも、200のリスポンスを返し、レスポンスボディの中でエラーコードとメッセージを返したかったが、うまく行かなかったので、これは次の機会にやる。

requestの取得

requsetの取得は以下のようになる。(公式)

class HealthCheck(object):
def on_get(self, req, resp):
	print(req.headers) # headerの取得
	print(req.params['name']) # request paramの取得

   # request bodyの取得
    body = req.stream.read().decode("utf-8")
    data = json.loads(body)
    name = data['name']

app = falcon.API()
app.add_route("/", index())

if __name__ == "__main__":
    from wsgiref import simple_server
    httpd = simple_server.make_server("127.0.0.7", 8000, app)
    httpd.serve_forever()

If you like it, share it!