Decoradores

Com os decoradores Python para o Cloud Endpoints Frameworks, é possível descrever a configuração da API, os métodos, os parâmetros e outros detalhes importantes que definem as propriedades e o funcionamento do Endpoints.

Nesta página, você aprende em detalhes sobre os decoradores disponíveis. Para informações sobre como usar decoradores para criar sua API, consulte:

Definindo a API (@endpoints.api)

É possível fornecer vários argumentos para o @endpoints.api para definir a API. A tabela a seguir descreve os argumentos disponíveis:

Argumentos @endpoints.api Descrição Exemplo
allowed_client_ids Obrigatório, se a API usa autenticação. Lista de IDs de clientes com a permissão para solicitar tokens. Para mais informações, consulte IDs do cliente e público permitidos. allowed_client_ids=['1-web-apps.apps.googleusercontent.com','2-android-apps.apps.googleusercontent.com', endpoints.API_EXPLORER_CLIENT_ID]
api_key_required Opcional. Usado para restringir o acesso a solicitações que forneçam uma chave de API. api_key_required=True
audiences Obrigatório se a API exige autenticação e você aceita clientes Android. Para os tokens de ID do Google, pode ser uma lista dos IDs de clientes para os quais são solicitados tokens. Se os tokens são emitidos por provedores de autenticação de terceiros, como o Auth0, isso precisa ser um mapeamento de dicionário dos nomes de emissores de autenticação para as listas de público-alvo. Para mais informações, consulte IDs do cliente e público permitidos. audiences=['1-web-apps.apps.googleusercontent.com'] ou audiences={"auth0": ["aud-1.auth0.com", "aud-2.auth0.com"]}
base_path Opcional. Usado para disponibilizar a API com base no caminho especificado. Se você especificar esse argumento, também deverá alterar a seção handlers no seu arquivo app.yaml. Consulte Como disponibilizar a API de um caminho diferente.
canonical_name Opcional. Usado para especificar um nome distinto ou mais legível para a API na biblioteca de cliente. Esse nome é usado para gerar nomes na biblioteca de cliente; a API de back-end continua a usar o valor especificado na namepropriedade.

Por exemplo, se sua API tiver namedefinida como dfaanalytics, você pode usar essa propriedade para especificar um nome canônico de DFA Group Analytics; as classes de cliente geradas, então, conteriam o nome DfaGroupAnalytics.

Você deve incluir os espaços relevantes entre os nomes, como mostrado; estes são substituídos pelos caracteres mistos de maiúsculas e minúsculas ou por caracteres de sublinhado.
canonical_name='DFA Analytics'
description Uma breve descrição da API. Ela fica exposta no serviço de descoberta para descrever a API e também pode ser usada para gerar documentação, conforme mencionado em Como gerar bibliotecas de cliente. description='Sample API for a simple game'
documentation Opcional. O URL em que os usuários podem encontrar documentação sobre esta versão da API. Isso é exibido no destaque "Saiba mais", na parte superior da página API Explorer, para que os usuários conheçam seu serviço. documentation='http://link_to/docs'
hostname O nome do host do seu aplicativo do App Engine. A ferramenta de linha de comando do Endpoints Frameworks usa o valor especificado aqui ao gerar um documento do Discovery ou um documento OpenAPI. Se você não especificar o nome do host aqui, especifique o nome do host no campo application do seu app.yaml ou especifique o ID do projeto quando implantar o aplicativo do App Engine. hostname='your_app_id.appspot.com'
issuers Opcional. As configurações personalizadas do emissor JWT. Isso precisa ser um mapeamento de dicionário dos nomes de emissores para os objetos endpoints.Issuer. issuers={"auth0": endpoints.Issuer("https://test.auth0.com", "https://test.auth0.com/.well-known/jwks.json")}
name Obrigatório. O nome da API usado como prefixo em todos os métodos e caminhos da API. O valor name:
  • É obrigatório começar com uma letra minúscula.
  • Precisa corresponder à expressão regular [a-z]+[A-Za-z0-9] ; ou seja, o restante do nome pode conter letras maiúsculas e minúsculas ou números.
Para implantar várias APIs como parte de um único serviço, todos os nomes de API devem corresponder à expressão regular [a-z][a-z0-9]{0,39}, ou seja, o nome deve começar com uma letra minúscula, o resto dos caracteres deve ser letras minúsculas ou números com o tamanho máximo de 40 caracteres.
name='yourApi' ou name='yourapi'
limit_definitions Opcional. Usado para definir cotas para sua API. Consulte limit_definitions para mais informações.
owner_domain Opcional. O nome de domínio da entidade proprietária da API. Usado junto com o owner_name para fornecer dicas para nomear corretamente a biblioteca de cliente quando ela for gerada para esta API. O caminho do pacote é o contrário de owner_domain e package_path, se fornecido. O padrão é usar o appid.apppost.com owner_domain='your-company.com'
owner_name Opcional. O nome da entidade proprietária da API. Usado junto com o owner_domain para fornecer dicas para nomear corretamente a biblioteca de cliente quando ela for gerada para esta API. owner_name='Your-Company'
package_path Opcional. É usado para ampliar o escopo do "pacote" ao qual a API pertence, com valores separados por / especificando agrupamentos lógicos de APIs.

Por exemplo, especificar resultados cloud/platform no caminho da biblioteca de cliente definido como cloud/platform/<ApiName> e pacote de biblioteca de cliente definido como cloud.plaform.<ApiName>.
package_path='cloud/platform'
scopes Se não for fornecido, o padrão é o escopo do e-mail (https://www.googleapis.com/auth/userinfo.email), que é obrigatório para o OAuth. Modifique-o para especificar mais escopos de OAuth 2.0, se você quiser. Também é possível substituir os escopos especificados aqui para um método de API determinado, definindo diferentes escopos no decorador @endpoints.method. No entanto, se mais de um escopo for definido, observe que a verificação de escopo será aprovada se o token for criado para qualquer um dos escopos especificados. Para exigir vários escopos, especifique uma única string com um espaço entre cada um deles. scopes=['ss0', 'ss1 and_ss2']
title Opcional. O texto exibido no API Explorer como título da API e exposto na descoberta e nos serviços de diretório. title='My Backend API'
version Obrigatório. Especifica a versão do Cloud Endpoints. Esse valor é exibido no caminho da API. Se você especificar uma string de versão compatível com o SemVer padrão , apenas o número da versão principal aparecerá no caminho da API quando você implantar a API. Por exemplo, uma API chamada echo com a versão 2.1.0 teria um caminho semelhante a /echo/v2. Se você atualizar a API echo para a versão 2.2.0 e implantar uma alteração compatível com as versões anteriores, o caminho permanecerá /echo/v2. Com essas ações, você atualiza o número da versão da API durante a alteração compatível com versões anteriores sem alterar os caminhos existentes para seus clientes. Mas se você atualizar a API echo para a versão 3.0.0 (porque está implantando uma alteração interruptiva), o caminho será alterado para /echo/v3. version='v1' ou version='2.1.0'

limit_definitions

Para definir cotas para sua API, especifique o argumento opcional limit_definitions para @endpoints.api. Para configurar uma cota, você também precisa:

  • instalar a versão 2.4.5 ou posterior da biblioteca do Endpoints Frameworks;
  • Adicione o argumento metric_costs ao decorador de método para cada método que queira aplicar uma cota.

Acesse este link para saber mais sobre todas as etapas necessárias para configurar uma cota.

Especifique uma lista de uma ou mais instâncias LimitDefinition, como a seguir:

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

Cada instância LimitDefinition deve ter os seguintes valores:

Elemento Descrição
nome O nome do contador de solicitações à API. Normalmente é o tipo de solicitação (por exemplo, "read-requests" ou "write-requests") que identifica exclusivamente a cota.
Display name

O texto exibido para identificar a cota na guia Cotas, localizada na página Endpoints > Serviços. Esse texto também é exibido para os consumidores da API na página Cotas em "IAM e administrador" e em "API e serviços". O nome de exibição precisa ter no máximo 40 caracteres.

Para facilitar a leitura, o texto "per minute per project" é anexado automaticamente ao nome de exibição nas páginas "Cotas". Para manter a consistência com os nomes de exibição dos serviços do Google listados nas páginas "Cotas" que aparecem para os consumidores da API, temos as seguintes recomendações para o nome de exibição:

  • Use "Requests" quando tiver apenas uma métrica.
  • Quando você tem várias métricas, cada uma precisa descrever o tipo de solicitação e conter a palavra "requests" (por exemplo, "Read requests" ou "Write requests").
  • Use "Quota units" em vez de "Requests" quando qualquer um dos custos dessa cota for maior que 1.

limit Um valor inteiro que é o número máximo de solicitações por minuto por projeto de consumidor para a cota.

Exemplo

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)

IDs de cliente e público permitidos

Para autenticação OAuth2, um token OAuth2 é emitido para um ID do cliente específico, o que significa que esse ID do cliente pode ser usado para restringir o acesso às suas APIs. Ao registrar aplicativos Android no Console do Google Cloud, você cria um ID do cliente para eles. O ID do cliente é o que solicita um token OAuth2 do Google para fins de autenticação. Quando a API de back-end é protegida por autenticação, um token de acesso do OAuth2 é enviado e aberto pelo Endpoints Frameworks no App Engine. Além disso, o ID do cliente é extraído do token e, em seguida, comparado à lista de IDs do cliente aceitáveis e declarados do back-end. (a lista allowed_client_ids).

A lista allowed_client_ids precisa consistir em todos os IDs do cliente obtidos pelo Console do Google Cloud para a Web, Android e outros apps clientes. Isso significa que você precisa saber quais são os clientes no momento da criação da API. Se você especificar uma lista vazia, nenhum cliente terá acesso à API.

Em cada método de API em que você quer verificar se a autenticação está correta, é necessário chamar endpoints.get_current_user(). Consulte Como autenticar usuários para mais informações.

Se você usar o argumento allowed_client_ids e quiser testar as chamadas autenticadas à API usando a API Explorer, será necessário fornecer o respectivo ID do cliente na lista allowed_client_ids ao especificar a constante endpoints.API_EXPLORER_CLIENT_ID. Se allowed_client_ids contiver apenas endpoints.API_EXPLORER_CLIENT_ID e você implantar a API, ela continuará sendo publicamente descoberta e acessada na API Explorer.

Sobre públicos-alvo

A lista allowed_client_ids protege a API de back-end contra clientes não autorizados. No entanto, é necessária uma proteção adicional para proteger os clientes, para que o token de autenticação deles funcione somente para a API de back-end desejada. Para clientes Android, esse mecanismo é o argumento audiences, no qual você especifica o ID do cliente da API de back-end.

Observe que, quando você cria um projeto do Console do Google Cloud, um ID do cliente padrão é criado automaticamente e nomeado para o projeto. Quando você faz o upload do seu API de back-end no App Engine, ele usa esse ID do cliente. Esse é o ID do cliente da Web mencionado na autenticação da API.

Emissor de token de autenticação de terceiros

Será necessário definir adequadamente os argumentos audiencese issuers em @endpoints.api para fornecer informações sobre emissores terceirizados se o aplicativo aceitar tokens de autenticação que não sejam do ID do Google, mas emitidos por terceiros. Exemplo:

@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):

Como definir um método de API (@endpoints.method)

Você pode definir as configurações de audiences, scopes e allowed_client_ids para toda a API usando @endpoints.api, ou para um método, usando @endpoints.method. Se essas configurações forem definidas no nível de API e de método, a configuração do método será modificada.

Para criar um método na API, decore o método Python correspondente com @endpoints.method, fornecendo argumentos para configurar o uso do método. Por exemplo, especifique quais classes de solicitação e de resposta Message devem ser usadas.

Os argumentos disponíveis estão listados na seguinte tabela:

Argumentos @endpoints.method Descrição Exemplo
allowed_client_ids Esta configuração modifica o atributo equivalente especificado em @endpoints.api. Para mais informações, consulte IDs do cliente e público permitidos. ['1-web-apps.apps.googleusercontent.com', '2-android-apps.apps.googleusercontent.com']
api_key_required Opcional. Usado para restringir o acesso a solicitações que fornecem uma chave de API. api_key_required=True
audiences Modifica o argumento equivalente especificado em @endpoints.api. Para mais informações, consulte IDs do cliente e público permitidos. ['1-web-apps.apps.googleusercontent.com']
metric_costs Opcional. Indica que o método tem um limite de cota. É um dicionário com os seguintes pares de chave-valor:
  • nome: um nome que você especificou no argumento limit_definitions para o decorador da API.
  • custo: um número inteiro que especifica o custo de cada solicitação. O custo permite que os métodos consumam taxas diferentes da mesma cota. Por exemplo, se uma cota tiver um limite de 1.000 e um custo de 1, o aplicativo que faz a chamada pode fazer 1.000 solicitações por minuto antes de ultrapassar o limite. Com o custo de 2 para a mesma cota, um aplicativo de chamada só pode fazer 500 solicitações por minuto antes de passar do limite.
metric_costs={'read-requests': 1}
http_method O método HTTP a ser usado. Caso isto não seja definido, 'POST' será usado por padrão. 'GET'
name Um nome alternativo desse método. O valor name:
  • Precisa começar com letra minúscula.
  • Precisa corresponder à expressão regular [a-z]+[A-Za-z0-9]*.
'yourApi'
path O caminho de URI para acessar esse método. Se você não o definir, o nome do método Python será usado. Se você planeja adicionar o gerenciamento de API, não inclua uma barra no final do caminho. 'yourapi/path'
Classe Request Message A classe de Request Message do RPC do protocolo do Google a ser usada na chamada do método. Como alternativa, forneça o nome da classe. YourRequestClass
Classe Response Message A classe de Response Message do RPC do protocolo do Google a ser usada na chamada do método. Como alternativa, forneça o nome da classe. YourResponseClass

Como usar ResourceContainer para caminhos ou argumentos de string de consulta

Se a solicitação tiver argumentos de string de consulta ou caminho, não será possível usar uma classe de Message simples, conforme mencionado em Criar a API. Em vez disso, será preciso usar uma classe de ResourceContainer, como indicado a seguir:

  1. Defina uma classe Message que tenha todos os argumentos que são passados no corpo da solicitação. Se não houver argumentos no corpo da solicitação, você não precisará definir uma classe Message: basta usar message_types.VoidMessage. Por exemplo:

    class Greeting(messages.Message):
        """Greeting that stores a message."""
        message = messages.StringField(1)
  2. Defina um ResourceContainer com a classe Message que você definiu na etapa anterior como o primeiro parâmetro. Especifique os argumentos caminho e string de consulta nos parâmetros posteriores. Exemplo:

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

    em que o primeiro argumento é a classe Message dos dados no corpo da solicitação e times é um número esperado no caminho ou string de consulta que acompanha a solicitação.

  3. Forneça ResourceContainer ao método que processa a solicitação no primeiro parâmetro substituindo a classe Message da solicitação que seria fornecida nesse local. Este snippet mostra ResourceContainer e endpoints.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. Adicione o parâmetro path, conforme mostrado, para incluir sua API.

  5. Se ResourceContainer tiver um argumento obrigatório, uma solicitação do cliente deve incluí-lo em uma string de consulta (por exemplo, yourApi?times=2) ou o caminho do URL (por exemplo, yourApi/2). No entanto, para que a API receba um valor de argumento usando o caminho do URL, você também precisa adicionar o nome do argumento ao caminho da API, conforme mostrado no argumento {times} em path='yourApi/{times}.

A seguir