見通しよく、REST API を書きたいと思ったのだけど、Flask-restful がなんともしっかりした REST 特化しすぎてて微妙だったので、Flask 単品でちょっと実験したメモ
Install といっても…
Python だとこれだけ。
$ pip install Flask
ルーティング機構
と言っても非常にみたまま素直な感じ。
とてもわかりやすくてよい。
from flask import Flask, request app = Flask(__name__) @app.route('/seminers', methods=['GET', 'POST']) def seminers(): print(request) print(request.data) print(request.form) print(request.args) return 'Example message' app.run(debug = True, port = 3000)
リクエスト等の受け取り
で、どうなるのか気になったのがここなので、色々上記に流し込んで試してみた。
まずは単純リクエスト
$ curl http://localhost:3000/seminers
実行結果…まぁそうね。
null になってないあたり個人的に好き
<Request 'http://localhost:3000/seminers' [GET]> b'' ImmutableMultiDict([]) ImmutableMultiDict([])
URL パラメータ突っ込むと
$ curl http://localhost:3000/seminers?welcome=data
args が反応する
<Request 'http://localhost:3000/seminers?welcome=data' [GET]> b'' ImmutableMultiDict([]) ImmutableMultiDict([('welcome', 'data')])
今度は Form POST
$ curl -F "key=value" -F "msg=ひゃっはー" http://localhost:3000/seminers
request.form
が反応
<Request 'http://localhost:3000/seminers' [POST]> b'' ImmutableMultiDict([('key', 'value'), ('msg', 'ひゃっはー')]) ImmutableMultiDict([])
ファイルを送信してみる。適当に ss.png ファイルをキャプチャで作って食わせた
$ curl -F "key=value" -F "file=@ss.png" http://localhost:3000/seminers
えーっと(汗
<Request 'http://localhost:3000/seminers' [POST]> b'' ImmutableMultiDict([('key', 'value')]) ImmutableMultiDict([])
調べてみたら files
フィールドに格納されるらしい
@app.route('/seminers', methods=['GET', 'POST']) def seminers(): print(request) print(request.data) print(request.files) print(request.form) print(request.args) return 'Example message'
書き換えたリトライ。
でたでた。form/maltipart-formdata の区別は自動でやってくれてるらしい。
<Request 'http://localhost:3000/seminers' [POST]> b'' ImmutableMultiDict([('file', <FileStorage: 'ss.png' ('application/octet-stream')>)]) ImmutableMultiDict([('key', 'value')]) ImmutableMultiDict([])
なら、JSON はどうだろう?
$ curl -H 'Content-Type:application/json' -d "{"key":"val","key2":",val2"}" http://localhost:3000/seminers
ここにきて data
が反応。
application/json
にはデフォルトでは対応していない模様。
<Request 'http://localhost:3000/seminers' [POST]> b'{key:val,key2:,val2}' ImmutableMultiDict([]) ImmutableMultiDict([]) ImmutableMultiDict([])
json
パッケージとか使えばどうとでもなりそう。
import json @app.route('/seminers', methods=['GET', 'POST']) def seminers(): print(request) print(request.data) print(request.files) print(request.form) print(request.args) if request.headers['Content-Type'] == 'application/json': json_value = json.loads(request.data) print(json_value) return 'Example message'
そして投げ直す
$ curl -H 'Content-Type:application/json' -d "{\"key\":\"val\",\"key2\":\"val2\"}" http://localhost:3000/seminers
うまく行ったけど、あまりにダサい。
if とか腹立たしいのだけど…
<Request 'http://localhost:3000/seminers' [POST]> b'{"key":"val","key2":"val2"}' ImmutableMultiDict([]) ImmutableMultiDict([]) ImmutableMultiDict([]) {'key': 'val', 'key2': 'val2'}
application/json
にしか公開しないとかねーのかと思ったのだけど、
まぁこういう振り分けこそコントローラの仕事だし仕方ないのか(汗