素人がWebアプリケーション制作の過程を書いてみる（Flask RESTful-API実装）

[前回](https://qiita.com/prayer1981/items/b1bd982b3f2bc50cf890)に引き続きFlaskにいろいろ実装をしてみます。今回作成するアプリケーションはJavascript側でUIを描画していくため、サーバサイドではデータのやり取りのための最低限の実装をしたいと思います。

### REST-APIの実装
まずREST(Representational state transfer)ful APIについてですが、実際にどのようなものかは、[チュートリアルサイト](https://www.restapitutorial.com/)のようなものもありますので、そちらを参照いただければと思います。
簡単に言えばHTTPプロトコルの各種メソッド（GET/PUT/POST/DELETE）とJSON形式のデータをもとに、サーバクライアント間でデータのやり取りを行うAPIになります。

例えば、下記のような感じです。curlコマンドにてPOSTメソッドを用いてhogeの中のid=1のデータを取ってくるイメージです。

```shell
$ curl -X GET http://example.com/api/v1/hoge/id/1
{
  meta: {
  },
  hoge: {
    id: 1,
    data: 'fuga',
  }
}
```
このようにクライアント側のJavascriptとサーバ側がデータのみをやり取りし、クライアント側の描画を動的に更新することにより、あたかもアプリケーションライクな動作を行うことができます。このようなAPIは他にもありますが、有名どころではSOAP（Simple Object Access Protocol）がよく比較として挙げられます。

早速Flaskで実装してみましょう。（いくつかflask専用の[ライブラリ](https://flask-restful.readthedocs.io/en/latest/)が出ているようですが、勉強のためにそのまま実装します。）

前回実装したapp.pyに追記してみます。

```python

from flask import Flask, render_template, request  # requestを追加

app = Flask("__name__")

database = []

@app.route("/")
def root():
    return render_template("index.html")


# 今回の実装箇所　----
@app.route("/api/v1/<string:userId>", methods=['GET','POST','PUT','DELETE'])
def api_get(userId):

    # GETの場合はuserIDにマッチするデータをデータベースから取得しJSON形式でデータを返却
    if request.method == 'GET':
        for i in xrange(len(database)):
            if database[i]['id'] == userId:
                return '{"data" : "%s"}' %(database[i]['data'])
        return '{"result" : "error"}'

    # POST/PUTは送信されたJSON形式のデータを受け取り、データベースに格納
    elif request.method in ['POST','PUT']:
        query_json = request.get_json()
        data = {}

        if (query_json.has_key('data')):
            data['id'] = userId
            data['data'] = query_json['data']
            database.append(data)
            return '{"result" : "success"}'
        else:
            return '{"result" : "error"}'

    # DELETEは送信されたJSON形式のデータを受け取り、データベースから削除
    elif request.method == 'DELETE':
        for i in xrange(len(database)):
            if database[i]['id'] == userId:
                del(database[i])
                return '{"result" : "success"}'

        return '{"result" : "error"}'

    return '{"result" : "error"}'
#---

if __name__ == "__main__":
    app.run(debug=True)
```
実際にサーバを起動し、curlコマンドで動作を確認してみます。

```shell
# サーバ側
$ python app.py runserver
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
127.0.0.1 - - [01/Sep/2018 00:10:38] "POST /api/v1/1 HTTP/1.1" 200 -
127.0.0.1 - - [01/Sep/2018 00:10:49] "POST /api/v1/2 HTTP/1.1" 200 -
127.0.0.1 - - [01/Sep/2018 00:10:53] "GET /api/v1/2 HTTP/1.1" 200 -
127.0.0.1 - - [01/Sep/2018 00:11:06] "DELETE /api/v1/2 HTTP/1.1" 200 -
127.0.0.1 - - [01/Sep/2018 00:11:19] "GET /api/v1/2 HTTP/1.1" 200 -
```

curlでJSONを送付する際には、データがJSON形式だとわかるように-H "Content-Type: application/json"を付与して送付する必要があります。（app.pyのrequest.get_json()はContent-Type: application/jsonをもとにJSON形式を判定しているため、ヘッダをつけない場合、データが格納されません。）

```shell
# クライアント側
$ curl -X POST http://127.0.0.1:5000/api/v1/1 -d '{"data":"hoge"}' -H "Content-Type: application/json"
{"result" : "success"}
$ curl -X POST http://127.0.0.1:5000/api/v1/2 -d '{"data":"hoge2"}' -H "Content-Type: application/json"
{"result" : "success"}
$ curl -X GET http://127.0.0.1:5000/api/v1/2
{"data" : "hoge2"}
$ curl -X DELETE http://127.0.0.1:5000/api/v1/2
{"result" : "success"}
$ curl -X GET http://127.0.0.1:5000/api/v1/2
{"result" : "error"}
```

次回もFlaskの機能を使った実装を進めていきたいと思います。