デコレータ

Python 用 Cloud Endpoints Frameworks のデコレータは、API の構成、メソッド、パラメータなど、Endpoints のプロパティや動作を定義する重要な詳細を記述します。

このページでは、使用可能なデコレータについて詳しく説明します。デコレータを使用して API を作成する方法については、次をご覧ください。

API の定義(@endpoints.api

@endpoints.api に複数の引数を渡して API を定義できます。使用可能な引数は、以下の表のとおりです。

@endpoints.api の引数 説明
allowed_client_ids API で認証を使用する場合は必須。トークンをリクエストすることを許可されたクライアント ID のリスト。詳しくは、許可されたクライアント ID とオーディエンスをご覧ください。 allowed_client_ids=['1-web-apps.apps.googleusercontent.com','2-android-apps.apps.googleusercontent.com', endpoints.API_EXPLORER_CLIENT_ID]
api_key_required 省略可。API キーを提供するリクエストだけに限定的にアクセスを許可する場合に使用します。 api_key_required=True
audiences API に認証が必要で、Android クライアントをサポートしている場合は必須です。Google ID トークンの場合はクライアント ID のリストであり、これらの ID の代わりにトークンがリクエストされます。トークンの発行元がサードパーティの認証プロバイダ(Auth0 など)である場合は、認証の発行元の名前からオーディエンス リストにマッピングするディクショナリが必要です。詳しくは、許可されたクライアント ID とオーディエンスをご覧ください。 audiences=['1-web-apps.apps.googleusercontent.com'] または audiences={"auth0": ["aud-1.auth0.com", "aud-2.auth0.com"]}
base_path 省略可。指定されたパスから API を提供するために使用されます。この引数を指定する場合は、app.yaml ファイルの handlers セクションも変更する必要があります。 別のパスから API を提供するをご覧ください。
canonical_name 省略可。クライアント ライブラリで API に別のわかりやすい名前を付ける場合に使用します。この名前は、クライアント ライブラリで名前を生成するために使用されます。バックエンド API は、name プロパティで指定された値を引き続き使用します。

たとえば、API の namedfaanalytics に設定されている場合、このプロパティを使用して正規名を DFA Group Analytics と指定できます。こうすると、生成されるクライアント クラスに DfaGroupAnalytics という名前が含められます。

名前の間にはスペースを入れることをおすすめします。これらは、適宜キャメルケースまたはアンダースコアに置き換えられます。
canonical_name='DFA Analytics'
description API の簡単な説明。API を説明するために検出サービスで公開されます。クライアント ライブラリの生成に記述されているように、ドキュメントを生成するために使用することもできます。 description='Sample API for a simple game'
documentation 省略可。ユーザーがこのバージョンの API に関するドキュメントを参照できる URL。これは、API Explorer ページの上部にある API Explorer の [詳細] リンクに関連付けられており、このリンクをクリックすることで、サービスの詳細を知ることができます。 documentation='http://link_to/docs'
hostname App Engine アプリケーションのホスト名。Endpoints Frameworks コマンドライン ツールはディスカバリ ドキュメントまたは OpenAPI ドキュメントを生成する際、ここに指定された値を使用します。ここでホスト名を指定しない場合は、app.yaml ファイルの application フィールドにホスト名を指定するか、App Engine アプリケーションをデプロイする際にプロジェクト ID を指定する必要があります。 hostname='your_app_id.appspot.com'
issuers 省略可。JWT 発行元のカスタムの構成です。これは、発行元の名前から endpoints.Issuer オブジェクトにマッピングする、ディクショナリである必要があります。 issuers={"auth0": endpoints.Issuer("https://test.auth0.com", "https://test.auth0.com/.well-known/jwks.json")}
name 必須。API のメソッドとパスすべてに使用される接頭辞となる API の名前です。name の値は以下の条件を満たす必要があります。
  • 先頭は小文字でなければなりません
  • 正規表現 [a-z]+[A-Za-z0-9] と一致していなければなりません。すなわち、名前の残りの部分は大文字、小文字、数字のどれからでも構成できます。
単一サービスの一部として複数の API をデプロイする場合、すべての API 名は正規表現 [a-z][a-z0-9]{0,39} と一致している必要があります。つまり、名前の先頭は小文字にし、残りの部分は小文字または数字にして、長さを 40 文字以下にする必要があります。
name='yourApi' または name='yourapi'
limit_definitions 省略可。API の割り当てを定義するときに使用します。詳細については、limit_definitions をご覧ください。
owner_domain 省略可。API を所有する組織のドメイン名です。owner_name とともに使用され、この API のクライアント ライブラリを生成するときに適切な名前を付けるヒントを提供します。パッケージパスを指定する場合は、owner_domainpackage_path を逆順で指定します。デフォルトでは appid.apppost.com を使用します。 owner_domain='your-company.com'
owner_name 省略可。API を所有する組織の名前です。owner_domain とともに使用され、この API のクライアント ライブラリを生成するときに適切な名前を付けるヒントを提供します。 owner_name='Your-Company'
package_path 省略可。この API が属する「パッケージ」のスコープを広げるときに使用します。/ で値を区切ることにより、API の論理的なグループ分けを行います。

たとえば、cloud/platform を指定すると、クライアント ライブラリのパスが cloud/platform/<ApiName> に設定され、クライアント ライブラリ パッケージは cloud.plaform.<ApiName> に設定されます。
package_path='cloud/platform'
scopes 指定しない場合は、OAuth の使用に必須であるメールのスコープ(https://www.googleapis.com/auth/userinfo.email)がデフォルトとして使用されます。必要に応じてこれをオーバーライドし、より多くの OAuth 2.0 スコープを指定できます。また、@endpoints.method デコレータで異なるスコープを指定することにより、特定の API メソッド用に指定されたスコープをオーバーライドすることもできます。ただし複数のスコープを定義する場合は、指定されたいずれかのスコープ用のトークンが作成されると、スコープ チェックが成功することに注意してください。複数のスコープを要求するには、各スコープをスペースで区切り、1 つの文字列にして指定します。 scopes=['ss0', 'ss1 and_ss2']
title 省略可。API のタイトルとして API Explorer に表示されるテキストです。検索や検索サービスにも表示されます。 title='My Backend API'
version 必須。Cloud Endpoints のバージョンを指定します。この値は API のパスに含まれます。SemVer 標準と互換性のあるバージョン文字列を指定すると、API のデプロイ時にメジャー バージョン番号のみが API のパスに含まれます。たとえば、バージョン 2.1.0echo という API のパスは /echo/v2 に類似したものになります。echo API をバージョン 2.2.0 に更新し、下位互換性のある変更をデプロイすると、このパスは /echo/v2 のままになります。これにより、下位互換性のある変更を行うときに、クライアントの既存のパスを変更せずに API バージョン番号を更新できます。しかし、echo API をバージョン 3.0.0 に更新すると(互換性が失われる変更をデプロイするため)、パスは /echo/v3 に変更されます。 version='v1' または version='2.1.0'

limit_definitions

API の割り当てを定義するには、オプションの limit_definitions 引数を @endpoints.api に指定します。割り当てを構成するには、次のことも行う必要があります。

  • Endpoints Frameworks ライブラリのバージョン 2.4.5 以降をインストールします。
  • 割り当ての適用対象となる各メソッドのメソッド デコレータに、metric_costs 引数を追加します。

割り当ての設定に必要なすべての手順については、割り当ての構成をご覧ください。

次のように、1 つ以上の LimitDefinition インスタンスのリストを指定します。

quota_limits = [
              endpoints.LimitDefinition(
                "name",
                "Display name",
                limit)
]

LimitDefinition インスタンスには、次の値が必要です。

要素 説明
name API リクエスト カウンタの名前。通常、これは割り当てを一意に識別するリクエストのタイプ(「read-requests」または「write-requests」など)です。
表示名

[エンドポイント] > [サービス] ページの [割り当て] タブに表示される、割り当てを識別するテキスト。このテキストは、[IAM と管理] および [API とサービス] の [割り当て] ページで、API コンシューマに対しても表示されます。表示名の最大文字数は 40 文字です。

読みやすくするため、[割り当て] ページの表示名に「プロジェクトあたり毎分」というテキストが自動的に追加されます。 API コンシューマに対して表示される [割り当て] ページにリスト表示される Google サービスの表示名との整合性を保つため、次のような表示名を使用することをおすすめします。

  • 指標が 1 つしかない場合は「Requests」を使用します。
  • 指標が複数ある場合は、それぞれにリクエストのタイプを示す単語と「requests」という単語を含めます(「read-requests」または「write-requests」など)。
  • この割り当てに対するコストのいずれかが 1 より大きい場合は、「Requests」の代わりに「Quota units」を使用します。

limit 割り当てで、コンシューマ プロジェクトあたりのリクエスト最大数/分を示す整数値。

quota_limits = [
  endpoints.LimitDefinition('read-requests', 'Read Requests', 1000),
  endpoints.LimitDefinition('list-requests', 'List Requests', 100),
  endpoints.LimitDefinition('write-requests', 'Write Requests', 50)
]

@endpoints.api(name='bookstore',
               version='v1',
               limit_definitions=quota_limits)

許可されたクライアント ID とオーディエンス

OAuth2 による認証では、OAuth2 トークンは特定のクライアント ID に対して発行されます。つまり、クライアント ID によって API へのアクセスが制限されています。Google Cloud コンソールで Android アプリケーションを登録するときは、このためのクライアント ID を作ります。このクライアント ID は認証用に Google に対して OAuth2 トークンをリクエストします。バックエンド API が認証によって保護されている場合、OAuth2 アクセス トークンが送信され、App Engine 用 Endpoints Frameworks によって開かれます。このトークンからクライアント ID が抽出され、バックエンドが宣言した、許容可能なクライアント ID のリスト(allowed_client_ids リスト)と比較されます。

allowed_client_ids リストには、ウェブアプリ、Android アプリなどのクライアント アプリに対して Google Cloud コンソール から取得したすべてのクライアント ID を含めます。つまり、API のビルド時にこれらのクライアントを把握しておく必要があります。空のリストを指定した場合、どのクライアントも API にアクセスできません。

適切な認証を確認する各 API メソッドでは、endpoints.get_current_user() を呼び出す必要があります。 詳細については、ユーザーの認証をご覧ください。

allowed_client_ids 引数を使用し、API Explorer を使用して API への認証済み呼び出しをテストするには、そのクライアント ID を allowed_client_ids のリストに指定する必要があります。これには、定数 endpoints.API_EXPLORER_CLIENT_ID を指定します。allowed_client_idsendpoints.API_EXPLORER_CLIENT_ID のみが含まれた状態で API をデプロイすると、API は一般に検索可能となり、API Explorer でも一般にアクセス可能となることに注意してください。

オーディエンスについて

allowed_client_ids リストは、権限のないクライアントからバックエンド API を保護します。ただし、認証トークンが対象のバックエンド API のみに対して機能するようにクライアントを保護するには、さらなる措置が必要です。Android クライアントの場合は、そのための機能が audiences 引数です。この引数を使用すると、バックエンド API のクライアント ID を指定できます。

Google Cloud コンソール プロジェクトを作成するときは、そのプロジェクトで使用するデフォルトのクライアント ID が自動で作成され、命名されることに注意してください。App Engine にバックエンド API をアップロードするときは、そのクライアント ID が使用されます。これは、API 認証で説明されているウェブ クライアント ID です。

サードパーティの認証トークン発行元

Google ID トークンではなく、サードパーティから発行される認証トークンをアプリケーションで受け入れる場合は、@endpoints.apiaudiencesissuers の引数を適切に設定し、このサードパーティ発行元の情報を提供する必要があります。次に例を示します。

@endpoints.api(
        audiences={'auth0': ['aud-1.auth0.com', 'aud-2.auth0.com']},
        issuers={'auth0': endpoints.Issuer('https://test.auth0.com',
                                           'https://test.auth0.com/.well-known/jwks.json')})
class GreetingApi(remote.Service):

API メソッドの定義(@endpoints.method

audiencesscopesallowed_client_ids を API 全体に設定するには、@endpoints.api を使用し、メソッドに設定するには @endpoints.method を使用します。これらの設定が API とメソッド両方のレベルで指定された場合は、メソッドの設定が優先します。

API にメソッドを作成するには、@endpoints.method を使って対応する Python のメソッドを修飾し、メソッドの構成方法を設定する引数を指定します。たとえば、使用するリクエストとレスポンスの Message クラスを指定します。

利用可能な引数のリストは、下表のとおりです。

@endpoints.method の引数 説明
allowed_client_ids この設定は @endpoints.api に指定された対応する属性をオーバーライドします。詳しくは、許可されたクライアント ID とオーディエンスをご覧ください。 ['1-web-apps.apps.googleusercontent.com', '2-android-apps.apps.googleusercontent.com']
api_key_required 省略可。API キーを伴うリクエストに限りアクセスを許可する場合に使用します。 api_key_required=True
audiences @endpoints.api に指定された対応する引数をオーバーライドします。詳しくは、許可されたクライアント ID とオーディエンスをご覧ください。 ['1-web-apps.apps.googleusercontent.com']
metric_costs 省略可。メソッドに割り当て制限があることを指定します。これは、次の Key-Value ペアを含むディクショナリです。
  • name: API デコレータの limit_definitions 引数に指定した名前。
  • cost: 各リクエストのコストを指定する整数値。コストを使用することによって、さまざまなメソッドから同じ割り当てを異なるレートで消費できます。たとえば、割り当ての上限が 1,000 で、コストが 1 の場合、呼び出し元のアプリケーションは、上限内で 1 分間に 1,000 回のリクエストを行えます。同じ割り当てでコストが 2 の場合、呼び出し元のアプリケーションは、1 分間に 500 回のリクエストのみ行えます。
metric_costs={'read-requests': 1}
http_method 使用する HTTP メソッド。設定しない場合、デフォルトで 'POST' が使用されます。 'GET'
name このメソッドの代替名。name の値は以下の条件を満たす必要があります。
  • 先頭は小文字でなければなりません
  • 正規表現 [a-z]+[A-Za-z0-9]* と一致する必要があります
'yourApi'
path このメソッドのアクセスに使用する URI パス。設定しない場合は、Python メソッドの名前が使用されます。API 管理を追加する予定の場合は、パスの末尾にスラッシュを含めないでください。 'yourapi/path'
Request Message クラス メソッドの呼び出しで使用される Google Protocol RPC Request Message クラス。代わりにクラス名を入力することもできます。 YourRequestClass
Response Message クラス メソッドの呼び出しで使用される Google Protocol RPC Response Message クラス。代わりにクラス名を入力することもできます。 YourResponseClass

パスまたはクエリの文字列の引数に ResourceContainer を使用する

リクエストにパスまたはクエリの文字列の引数が含まれている場合は、API の作成で説明されているように、単純な Message クラスを作成することはできません。 その場合は、次のようにして ResourceContainer クラスを使用する必要があります。

  1. リクエスト本文に渡される引数をすべて含む Message クラスを定義します。リクエスト本文に引数がまったく含まれない場合は、Message クラスを定義する必要はなく、単純に message_types.VoidMessage を使用します。次に例を示します。

    class Greeting(messages.Message):
        """Greeting that stores a message."""
    
        message = messages.StringField(1)
  2. 最初のパラメータとして、前の手順で定義した Message クラスを使用して ResourceContainer を定義します。以降のパラメータには、パスとクエリの文字列の引数を指定します。次に例を示します。

    MULTIPLY_RESOURCE = endpoints.ResourceContainer(
        Greeting,
        times=messages.IntegerField(2, variant=messages.Variant.INT32, required=True),

    ここでは、リクエスト本文にあるデータの Message クラスが 1 つ目の引数であり、times はリクエストが持つパスかクエリ文字列に含まれる数字です。

  3. リクエストを処理するメソッドに ResourceContainer を渡して、1 つ目のパラメータを、その位置に入力されるリクエストの Message クラスと置き換えます。次のスニペットは、ResourceContainerendpoints.method の両方を示します。

    # This ResourceContainer is similar to the one used for get_greeting, but
    # this one also contains a request body in the form of a Greeting message.
    MULTIPLY_RESOURCE = endpoints.ResourceContainer(
        Greeting,
        times=messages.IntegerField(2, variant=messages.Variant.INT32, required=True),
    )
    
    @endpoints.method(
        # This method accepts a request body containing a Greeting message
        # and a URL parameter specifying how many times to multiply the
        # message.
        MULTIPLY_RESOURCE,
        # This method returns a Greeting message.
        Greeting,
        path="greetings/multiply/{times}",
        http_method="POST",
        name="greetings.multiply",
    )
    def multiply_greeting(self, request):
        return Greeting(message=request.message * request.times)
    
  4. 示されたとおりに API を含む path パラメータを追加します。

  5. ResourceContainer に必須の引数がある場合、クライアント リクエストのクエリ文字列(yourApi?times=2 など)または URL パス(yourApi/2 など)にその引数を含める必要があります。ただし、この URL パスを使用して API が引数値を受け取るようにするには、path='yourApi/{times} の引数 {times} に示すように、引数名も API パスに追加する必要があります。

次のステップ