LoginSignup
28
32

More than 5 years have passed since last update.

モダンでフレンドリーな Responder入門 と調べても中々出てこない情報達

Last updated at Posted at 2019-02-24

ResponderとはRequestsやpipenvの作者であるkennethreitz氏によるモダンなwebフレームワークです。

FlaskとFalconの良い部分を合わせるというのがアイデアのようで、確かに多くの機能を受け継いでいます。

さて、では初めて行きましょう。

基礎

まずは、Responder.APIを宣言するところから始めます。

import responder

api = responder.API()

インスタンス名はFlaskのようなappではなくapiとするのがマナー(?)のようです。

ルーティング

ルートを定義するには、@api.route("route_name")で関数をデコレートするか、api.add_route("route_name", callback)で関数をcallbackとして与えることができます。
基本的にはデコレートするほうがわかりやすいと思います。
ファイルが大きくなってきて、ルートを別ファイルに記述するようなときは、callbackとして与える方法ももちろん良いでしょう。

@api.route("/main_page")
def main_page(req, resp):
    resp.text= "Thanks for accessing"  #-------------  text
    resp.media = {"success": True}  #----------------  json, yaml
    resp.html = "<p>Thanks for accessing</p>"  #-----  html
    resp.status_code = 200  #------------------------  http status
    resp.headers["X-Pizza"] = "42"  #----------------  header

このように、respにデータを与えることでレスポンスを操作します。
基本的にresp.status_codeは設定しなければ自動で200となります。ですので、必要な情報のみ与えてください。

また、ルーティングには、f文字列式の動的ルーティングを使うことができます。

@api.route("/main_page/{name}")
def main_page(req, resp, *, name):
    resp.text= f"Thanks for accessing, {name}"

callbackにはキーワード引数で与えられるので、上記のようにしてください。

非同期・バックグラウンド実行

await, async, @api.background.taskを用いることで、バックグラウンドで処理を実行することができます。

@api.route("/taking")
async def some_function(req, resp):

    @api.background.task
    def take_long_time():
        # 時間のかかる処理

    take_long_time()

    resp.media = {'success': True}

実行

api.run()を実行してください。

if __name__ == '__main__':
    api.run()

なかなか出てこない情報達

port, address, デバッグモードの変え方

api.run()の引数に値を与えてください。

api.run(port=8080, address="127.0.0.2", debug=True)

そのほかにも、デバッグレベルなど沢山の引数を取ります。それらは、uvicornのsettingをご覧ください。

リクエストのメソッド確認

req.methodを見てください。

@api.route("/check_method")
def check_method(req, resp):
    if req.method == "get":
        resp.text = "this is get"
    elif req.method == "post":
        resp.text = "this is post"

postデータの受け取り方

await req.media()をasyncで定義したコルーチンの中で呼び出してください。

@api.route("/take_post")
async def take_post(req, resp):
    if req.method == "get":
        resp.text = "please send post"
    else:
        data = await req.media()
        resp.media = data
        resp.text = "I'm giving you back :) "

req.media()の引数にformat="form"format="json"のように指定することで、受け取るものを選ぶことができます。

Cookieに値を設定する、取得する

api.sessionreq.cookiesで取得、api.sessionresp.cookiesで設定。細かく設定するにはresp.set_cookieを使用しましょう。
api.sessionreq.cookiesapi.sessionは辞書で提供されるので、簡単に取得、設定することができます。
resp.set_cookieでは、以下の値を引数に取ります。

  • key : cookieの名前です
  • value : 実際に保存するデータです
  • expires : この cookie が破棄される日付です
  • max_age : この cookie が破棄されるまでの秒数です
  • secure : https のみで利用できるよう制限するかです
  • httponly : http の内部から(javascriptなどを利用して)閲覧できないよう制限するかです

Login Management

ResponderにはFlask-loginのようなログインマネージャは存在しません。
ですから、作りました。(隠しきれないステマ)
Responder-Login --- Docs
下記のように使用できます。

import responder
from responder_login import LoginManager, UserMixin

api = responder.API()
lm = LoginManager(api)

users = []


class User(UserMixin):
    id = None
    name = "Anonymous"
    age = 0

    def __init__(self, name, age):
        global users
        self.name = name
        self.age = age
        users.append(self)
        self.id = users.index(self)

    def get_id(self):
        return self.id

@lm.user_loader
def user_loader(user_id):
    try:
        return users[int(user_id)]
    except IndexError:
        return None


@api.route("/login/{name}/{age}")
@lm.login_prohibited
def login(req, resp, *, name, age):
    user = User(name, age)
    lm.login_user(user)
    resp.text = f"you've logged in as User; name: {user.name}, age: {user.age}"


@api.route("/show")
def show(req, resp):
    user = lm.current_user
    if user.is_authenticated:
        resp.text = f"you're logging in as User; name: {user.name}, age: {user.age}"
    else:
        resp.text = "you're not logging in"


@api.route("/logout")
@lm.login_required
def logout(req, resp):
    lm.logout_user()
    resp.text = "you've logged out"


if __name__ == "__main__":
    api.run()

ガバガバ英語と少ない機能、不適な実装だらけですので、プルリクを沢山送って、issueを沢山立ててもらえると嬉しいです。

28
32
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
32