Python+FalconでサクッとAPIサーバを作る

APIサーバを作るのにWebアプリケーションフレームワークを使うことは多いと思いますが、そんなに多機能なもの必要無いんだけどなあ、ということありません？
そんな時使えるのがこのFalconです。
[Falcon](https://falconframework.org/)
最低限必要なものはファイル1つのみ。気軽に始められます。

# インストール
`pip`使います。楽ちん。
うまくいかないときは`sudo`でもつけてみてください。

```
$ pip install falcon
```

# 使ってみる
必要なものはファイル1つだけです。`sample.py`とでもしておきます。

## リソースを書く
リソースはリクエストを処理するクラスです。`on_get`や`on_post`を書くと、対応するメソッドのリクエストを処理してくれます。

```python:sample.py
...
class SampleResource:
    def on_get(self, req, resp):
        obj = {
            "header": "Hello!",
            "body": {
                "a": "hoge",
                "b": "fuga",
            }
        }
        resp.body = json.dumps(obj, ensure_ascii=False)
...
```

## ルーティングを書く
`add_route`で、パスとリクエストを処理するクラスを結びつけます。

```python:sample.py
...
app = falcon.API()
app.add_route('/sample', SampleResource())
...
```

## 起動する
アドレスとかポートは適宜変えてください。
`gunicorn `などを使用する場合は、この部分は不要です。

```python:sample.py
...
if __name__ == "__main__":
    from wsgiref import simple_server

    httpd = simple_server.make_server("127.0.0.1", 8000, app)
    httpd.serve_forever()
...
```

## テスト
普通に`python`で動かします。

```
$ python sample.py
```

アクセスしてみると、たしかに動いてそうです。
http://localhost:8000/sample

```
{"body": {"a": "hoge", "b": "fuga"}, "header": "Hello!"}
```

# もう少し使う

## `gunicorn `を使う
インストールは`pip`で。

```
$ pip install gunicorn
```

デフォルトでは8000ポートを使うみたいです。

```
$ gunicorn sample:app
[2016-12-15 20:37:20 +0900] [34136] [INFO] Starting gunicorn 19.6.0
[2016-12-15 20:37:20 +0900] [34136] [INFO] Listening at: http://127.0.0.1:8000 (34136)
...
```

ポート(アドレス)を変えるには`-b`を使います。

```
$ gunicorn -b 127.0.0.1:8888 sample:app
[2016-12-15 20:41:29 +0900] [34225] [INFO] Starting gunicorn 19.6.0
[2016-12-15 20:41:29 +0900] [34225] [INFO] Listening at: http://127.0.0.1:8888 (34225)
...
```

## リスエストパラメータを取得
`on_get`などの引数にいる`req`の中にいます。

```python:sample.py
class ParamsResource:
    def on_get(self, req, resp):
        params = req.params
        resp.body = json.dumps(params, ensure_ascii=False)

app = falcon.API()
app.add_route('/params', ParamsResource())
```

`/params` => `{}`
`/params?a=hoge&b=fuga` => `{"a": "hoge", "b": "fuga"}`

取れました。
リクエストとレスポンスについては、一旦ここに目を通しておくと良いと思います。
[req/resp](http://falcon.readthedocs.io/en/stable/api/request_and_response.html)

## DBにアクセスする
標準では特に手段は用意されていません。自分で用意します。
自分の環境ではMySQLを使っているので、そこにアクセスしてみます。
まず、`MySQL-Python`をインストールします。おなじみ`pip`の登場。

```
$ pip install MySQL-Python
```

そして書きます。DB情報のところは適宜変更してください。

```python:sample.py
...
class BusinnesTermResource:
    def on_get(self, req, resp):

        connection = MySQLdb.connect(
            host='localhost',
            port=3306,
            user='root',
            passwd='password',
            db='sample',
            charset='utf8',
            cursorclass=MySQLdb.cursors.DictCursor
        )
        cursor = connection.cursor()

        sql = "select * from business_term"
        cursor.execute(sql)
        term = cursor.fetchone()

        cursor.close()
        connection.close()

        resp.body = json.dumps(term, ensure_ascii=False)

app = falcon.API()
app.add_route('/businnes_term', BusinnesTermResource())
...
```

取れました。

```
{"term": "ほげ", "meening": "ふが", "example": "さんぷる", "id": 1}
```

# 今回のコード全文

```python:sample.py
# -*- coding: utf-8 -*-
# sample.py
import falcon
import json
import MySQLdb
from MySQLdb.cursors import DictCursor

class BusinnesTermResource:
    def on_get(self, req, resp):

        connection = MySQLdb.connect(
            host='localhost',
            port=3306,
            user='root',
            passwd='password',
            db='sample',
            charset='utf8',
            cursorclass=MySQLdb.cursors.DictCursor
        )
        cursor = connection.cursor()

        sql = "select * from business_term"
        cursor.execute(sql)
        term = cursor.fetchone()

        cursor.close()
        connection.close()

        resp.body = json.dumps(term, ensure_ascii=False)

class SampleResource:
    def on_get(self, req, resp):
        obj = {
            "header": "Hello!",
            "body": {
                "a": "hoge",
                "b": "fuga",
            }
        }
        resp.body = json.dumps(obj, ensure_ascii=False)

class ParamsResource:
    def on_get(self, req, resp):
        params = req.params
        resp.body = json.dumps(params, ensure_ascii=False)

app = falcon.API()
app.add_route('/businnes_term', BusinnesTermResource())
app.add_route('/sample', SampleResource())
app.add_route('/params', ParamsResource())

if __name__ == "__main__":
    from wsgiref import simple_server

    httpd = simple_server.make_server("127.0.0.1", 8000, app)
    httpd.serve_forever()
```

# おわりに
非常に簡単に作れていい感じでした。書くのも起動も速いのでサクサクできます。
一旦テスト用にとか、ユーザ数そんないない適当でいいアプリとかで使っていきたいですね。