GAE(python)のRESTfulなAPIのフレームワークのrest_gae

budowski/rest_gae · GitHubというGoogle App Engine上で動くpythonのRESTfulなWeb APIフレームワークを使っているが、とても便利。

日本語での参考サイトがないので、メモとしてまとめる。

 

[概要]

Web APIなんて結局、jsonリクエストを受け取って、パラメータチェックして、レスポンスをjsonで返すだけのもの。

そのほとんどの機能をrest_gaeは提供する。インタフェースはREST。

 

1. ユーザ管理API

ユーザ作成、変更、削除などをのAPIがある。

 

1-1. 独自ユーザクラスの定義

from rest_gae.users import User
class MyUser(User):
    """Our own user class"""
    prop1 = ndb.StringProperty(required=True)
    prop2 = ndb.StringProperty()

独自のユーザ情報(この場合は、prop1とprop2)が必要なければ、デフォルトで提供されているUserクラスを使えば良い。

Userクラスが持っているプロパティは、

・email

・ユーザ名

・パスワード(ハッシュ化)

・adminユーザかどうか

・email認証済みかどうか

・作成日時と変更日時

※ドキュメントには書いてなかったので、ソースコードと実際に追加されたDataStoreから解析した!

 

そして、これを動かすには下記を記述する。

from rest_gae import * # This imports RESTHandler and the PERMISSION_ constants
from rest_gae.users import UserRESTHandler

# Make sure we initialize our WSGIApplication with this config (used for initializing webapp2_extras.sessions)
config = {}
config['webapp2_extras.sessions'] = {
    'secret_key': 'my-super-secret-key',
}

app = webapp2.WSGIApplication([
    UserRESTHandler(
        '/api/users', # The base URL for the user management endpoints
        user_model='models.MyUser', # Use our own custom User class
        user_details_permission=PERMISSION_LOGGED_IN_USER,
        verify_email_address=True,
        verification_email={
            'sender': 'John Doe <john@doe.com>',
            'subject': 'Verify your email',
            'body_text': 'Hello {{ user.full_name }}, click here: {{ verification_url }}',
            'body_html': 'Hello {{ user.full_name }}, click <a href="{{ verification_url }}">here</a>'
        },
        verification_successful_url='/verified-user',
        verification_failed_url='/verification-failed',
        reset_password_url='/reset-password',
        reset_password_email={
            'sender': 'John Doe <john@doe.com>',
            'subject': 'Reset your password',
            'body_text': 'Hello {{ user.name }}, click here: {{ verification_url }}',
            'body_html': 'Hello {{ user.name }}, click <a href="{{ verification_url }}">here</a>'
        },
        send_email_callback=my_send_email,
        allow_login_for_non_verified_email=False,
        user_policy_callback=lambda user, data: if len(data['password']) < 8: raise ValueError('Password too short')
   )], config=config)

 

UserRESTHandlerの中を見ていく。

'/api/users', # The base URL for the user management endpoints

URLを定義する。この場合、

http://ホスト名/api/users

でユーザ管理APIにアクセスすることになる。

 

user_model='models.MyUser', # Use our own custom User class

ユーザモデルの定義。先ほど作ったMyUserを使う。

 

user_details_permission=PERMISSION_LOGGED_IN_USER,

ユーザ情報を取得できるユーザの権限を設定している。ここでは、PERMISSION_LOGGED_IN_USERという(そのアカウントで)ログインしたユーザ以上に権限がある。

ユーザの権限には、下記がある。下に行くに従い、権限が強くなる。

・PERMISSION_ANYONE

・PERMISSION_LOGGED_IN_USER

・PERMISSION_OWNER_USER

・PERMISSION_ADMIN

 

その他の部分は、メール認証に関する機能で今回は無視する。

 

 1-2. ユーザ管理APIの呼び出し

【実行サンプルあり】

A) POST /users : ユーザ情報の登録。誰でも可。
B) POST /users/login : ログイン。誰でも可。

C) GET /users/エンティティキー : あるユーザ情報の取得。前述の通りログインユーザ以上で可。

 

【実行サンプルなし】

GET /users : 全ユーザ情報の取得。adminユーザのみ可。
PUT /users/エンティティキー : ユーザ情報変更。パスワードも変更できる。ログインユーザ以上で可。
DELETE /users/エンティティキー : ユーザ情報削除。ログインユーザ以上で可。 

 

【実行サンプルあり】のAPI実際に呼び出してみる。

 A) POST /users : ユーザ情報の登録。誰でも可。

f:id:tsuboi_sj:20150416064615p:plain

email, user_name, passwordがUserクラスの必須のパラメータ。MyUserクラスでprop1を必須で定義したので、prop1も必須。

レスポンスでエンティティキーがidという名で返ってくる。

 

DataStore Viewerで中身をチェックすると、

f:id:tsuboi_sj:20150416064714p:plain

ちゃんと値が入っている。

 

B) POST /users/login : ログイン。誰でも可。

f:id:tsuboi_sj:20150416064938p:plain

 れクエストはuser_nameとパスワードが必須。

レスポンスではuser_idが返される。これはMyUserエンティティのIDに一致する。つまり、ログインではMyUserエンティティキーは返却されない。

 

これがC) GET /users/エンティティキーの呼び出しで問題になる。エンティティキーがログインで取得できないので、下の2つのどちらかで対応する必要がある。

ア)アカウント作成時にローカルに保存(スマホアプリのみ可)

イ)エンティティキーを取得するAPIを別途用意する。

 

)の場合のサーバ側での処理は、

1.IDをクライアントから受け取る

2.ndb.Key(MyUser, IDの値).urlsafe()でエンティティキーを取得(※これがわからず苦労した)。

(例)ndb.Key(MyUser,4677872220372992).urlsafe()

3.クライアントに返却

ア)、イ)以外にもっと良いやり方があるかもしれないが、わからなかったのでこれで進めている。(誰か知っていたら教えて下さい。 )

 

※2015/4/18 追記

※ /users/me で自分のアカウントにアクセスできる(と分かった)ので、エンティティキーの取得は不要だった。

 

C) GET /users/エンティティキー : あるユーザ情報の取得。前述の通りログインユーザ以上で可。

f:id:tsuboi_sj:20150416065539p:plain

 取得成功。

 

Modelを追加してAPIを呼び出しもだいたい同じ感じ。次回書く。