技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

Flask 1.0.2 入門してみた

見通しよく、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 にしか公開しないとかねーのかと思ったのだけど、

flask.pocoo.org

まぁこういう振り分けこそコントローラの仕事だし仕方ないのか(汗