見通しよく、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 にしか公開しないとかねーのかと思ったのだけど、
まぁこういう振り分けこそコントローラの仕事だし仕方ないのか(汗