Decoradores

Los decoradores de Cloud Endpoints para Python describen los métodos, la configuración, los parámetros y otros detalles fundamentales de la API que definen las propiedades y el comportamiento del extremo.

En esta página, se describen en detalle los decoradores disponibles. Si quieres obtener información acerca del uso de los decoradores para crear tu API, visita los vínculos siguientes:

Define la API (@endpoints.api)

Puedes proporcionar varios argumentos a @endpoints.api para definir tu API. En la siguiente tabla, se describen los argumentos disponibles:

Argumentos de @endpoints.api Descripción Ejemplo
allowed_client_ids Obligatorio si tu API utiliza autenticación. Lista de los ID de cliente de aquellos que pueden solicitar tokens. Para obtener más información, consulta ID de cliente y públicos 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. Se usa para restringir el acceso a las solicitudes que proporcionan una clave de API. api_key_required=True
audiences Obligatorio si tu API necesita autenticación y si tienes compatibilidad con clientes Android. Para los tokens de ID de Google, esta puede ser una lista de ID de cliente en nombre de los cuales se solicitan los tokens. Si los emisores de los tokens son proveedores de autenticación de terceros, como Auth0, esto debe ser una asignación de diccionario desde los nombres de los emisores de la autenticación hasta las listas de público. Para obtener más información, consulta ID de cliente y públicos permitidos. audiences=['1-web-apps.apps.googleusercontent.com'] o audiences={"auth0": ["aud-1.auth0.com", "aud-2.auth0.com"]}
base_path Opcional. Se usa para entregar tu API desde la ruta de acceso especificada. Si especificas este argumento, también debes cambiar la sección handlers en tu archivo app.yaml. Consulta Cómo entregar tu API desde una ruta diferente.
canonical_name Opcional. Se usa con el objetivo de especificar un nombre diferente o más simple para la API en la biblioteca cliente. Este nombre se usa para generar nombres en la biblioteca cliente; la API de backend no deja de usar el valor especificado en la propiedad name.

Por ejemplo, si tu API tiene name configurado como dfaanalytics, podrías usar esta propiedad para especificar un nombre canónico de DFA Group Analytics; las clases de cliente generadas contendrían el nombre DfaGroupAnalytics.

Deberías incluir los espacios relevantes entre los nombres como se muestra; estos se reemplazarán por guiones bajos o mayúsculas y minúsculas según corresponda.
canonical_name='DFA Analytics'
description Una breve descripción de la API. Esto se expone en el servicio de descubrimiento para describir tu API y, de forma opcional, se puede usar a fin de generar documentación como se describe en Generar una biblioteca cliente. description='Sample API for a simple game'
documentation Opcional. La URL en la que los usuarios pueden encontrar documentación sobre esta versión de la API. Esto aparece en el elemento destacado “Más información” del Explorador de API en la parte superior de la página para permitir a los usuarios aprender más sobre tu servicio. documentation='http://link_to/docs'
hostname El nombre de host de tu aplicación de App Engine. La herramienta de línea de comandos de Endpoints Frameworks usa el valor que especificas aquí cuando genera un documento de descubrimiento o de OpenAPI. Si no especificas el nombre de host aquí, debes especificar el nombre de host en el campo application del archivo app.yaml o especificar el ID del proyecto cuando implementes tu aplicación de App Engine. hostname='your_app_id.appspot.com'
issuers Opcional. Las configuraciones personalizadas del emisor de JWT. Esto debería ser una asignación de diccionario desde los nombres de los emisores hasta los objetos endpoints.Issuer. issuers={"auth0": endpoints.Issuer("https://test.auth0.com", "https://test.auth0.com/.well-known/jwks.json")}
name Obligatorio. El nombre de la API, que se usa como un prefijo para todos los métodos y las rutas de la API. El valor name debe cumplir con estos requisitos:
  • Debe comenzar con una letra minúscula.
  • Debe coincidir con la expresión regular [a-z]+[A-Za-z0-9]; es decir, el resto del nombre puede contener letras mayúsculas y minúsculas o números.
Para implementar varias API como parte de un solo servicio, solo los nombres de API deben coincidir con la expresión regular [a-z][a-z0-9]{0,39}, es decir, el nombre debe comenzar con una letra minúscula, el resto de los caracteres deben ser letras minúsculas o números y la longitud máxima no debe superar los 40 caracteres.
name='yourApi' o name='yourapi'
limit_definitions Opcional. Se usa para definir cuotas para tu API. Consulta limit_definitions para obtener más información.
owner_domain Opcional. El nombre de dominio de la entidad que es propietaria de la API. Se usa junto con owner_name para proporcionar sugerencias que permitan darle un nombre apropiado a la biblioteca cliente cuando se genera para esta API. (La ruta del paquete será la forma invertida de owner_domain y package_path si se proporcionan). El valor predeterminado es appid.apppost.com. owner_domain='your-company.com'
owner_name Opcional. El nombre de la entidad que es propietaria de la API. Se usa junto con owner_domain para proporcionar sugerencias que permitan darle un nombre apropiado a la biblioteca cliente cuando se genera para esta API. owner_name='Your-Company'
package_path Opcional. Se usa para ampliar el alcance del “paquete” al que pertenece esta API, con valores separados por / que especifican agrupaciones lógicas de API.

Por ejemplo, especificar resultados de cloud/platform en la ruta de la biblioteca cliente configurada como cloud/platform/<ApiName> y el paquete de la biblioteca cliente configurado como cloud.plaform.<ApiName>.
package_path='cloud/platform'
scopes Si no se proporciona, la opción predeterminada es el alcance de correo electrónico (https://www.googleapis.com/auth/userinfo.email), que es obligatorio para OAuth. Si quieres, puedes anular esto para especificar más alcances de OAuth 2.0. También puedes anular los alcances especificados aquí para un método de API en particular si especificas diferentes alcances en el decorador @endpoints.method. Sin embargo, si defines más de un alcance, ten en cuenta que la verificación de alcance se aprueba si el token se acuña para cualquiera de los alcances especificados. Para requerir varios alcances, especifica una sola string con un espacio entre cada alcance. scopes=['ss0', 'ss1 and_ss2']
title Opcional. El texto que se muestra como título de tu API en el explorador de API y que se expone en los servicios de descubrimiento y de directorio. title='My Backend API'
version Obligatorio. Especifica tu versión de Cloud Endpoints. Este valor aparece en la ruta de acceso de tu API. Si especificas una string de la versión compatible con el estándar de SemVer, solo aparecerá el número de versión principal en la ruta de tu API cuando la implementes. Por ejemplo, una API llamada echo con la versión 2.1.0 tendrá una ruta similar a /echo/v2. Si actualizas la API echo a la versión 2.2.0 y, luego, implementas un cambio compatible con versiones anteriores, la ruta permanece como /echo/v2. Esto te permite actualizar el número de versión de la API cuando realizas un cambio compatible con versiones anteriores sin romper las rutas existentes para tus clientes. Pero si actualizas la API echo a la versión 3.0.0 (porque implementas un cambio rotundo), la ruta de acceso se cambia a /echo/v3. version='v1' o version='2.1.0'

limit_definitions

Si quieres definir quotas para tu API, especifica el argumento opcional limit_definitions como @endpoints.api. Para configurar una cuota, también debes hacer lo siguiente:

  • Instala la biblioteca de Endpoints Frameworks, versión 2.4.5 o posterior.
  • Agrega el argumento metric_costs al decorador de métodos para cada método al que quieras aplicar una cuota.

Consulta Cómo configurar cuotas para ver todos los pasos necesarios a fin de configurar una cuota.

Especificas una lista de una o más de instancias de LimitDefinition, similar a la siguiente:

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

Cada instancia de LimitDefinition debe tener los siguientes valores:

Elemento Descripción
name El nombre del contador de solicitudes a la API. En general, este es el tipo de solicitud (por ejemplo, "solicitudes de lectura" o "solicitudes de escritura") que identifica la cuota de forma única.
Nombre comercial

El texto que se muestra para identificar la cuota en la pestaña Cuotas, en la página Endpoints > Servicios. Este texto también se muestra a los consumidores de tu API en la página Cuotas de IAM y administración y API y servicios. El nombre que se muestra debe contener un máximo de 40 caracteres.

Para facilitar la lectura, el texto “por minuto por proyecto” se agrega de manera automática al nombre que se muestra en las páginas Cuotas. Para mantener la coherencia con los nombres que se muestran de los servicios de Google que aparecen en las páginas Cuotas y que pueden ver los consumidores de tu API, recomendamos tener en cuenta los siguientes elementos para el nombre que se muestra:

  • Utiliza "Solicitudes" cuando solo tengas una métrica.
  • Cuando tengas múltiples métricas, cada una debe describir el tipo de solicitud y debe contener la palabra “solicitudes” (por ejemplo, “Solicitudes de lectura” o “Solicitudes de escritura”).
  • Usa “Unidades de cuota” en lugar de “Solicitudes” cuando alguno de los costos de cuotas sea mayor que 1.

limit Un valor entero que representa el máximo de solicitudes por minuto por proyecto del consumidor para la cuota.

Ejemplo

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 de cliente y públicos permitidos

Para la autenticación de OAuth2, se emite un token de OAuth2 a un ID de cliente específico, lo que significa que este ID de cliente se puede usar para restringir el acceso a tus API. Cuando registras aplicaciones para Android en la consola de Google Cloud, creas un ID de cliente para estas. Este ID de cliente es el que solicita un token de OAuth2 desde Google con fines de autenticación. Cuando la autenticación protege a la API de backend, se envía un token de acceso de OAuth2, y Endpoints Frameworks para App Engine lo abre. Luego, se extrae el ID de cliente del token y se compara con la lista de ID de cliente declarada como aceptada del backend (la lista allowed_client_ids).

La lista allowed_client_ids debe contener todos los IDs de cliente que obtuviste a través de la consola de Google Cloud para tus apps cliente, Android y la Web. Esto significa que se deben tener todos los ID de cliente al momento de compilar la API. Si se especifica una lista vacía, ningún cliente puede acceder a la API.

Ten en cuenta que debes llamar a endpoints.get_current_user() en cada método de API donde quieras verificar la autenticación correcta. Consulta Cómo autenticar usuarios para obtener más información.

Si usas el argumento allowed_client_ids y quieres probar las llamadas a tu API autenticadas mediante el Explorador de API, debes proporcionar su ID de cliente en la lista de allowed_client_ids mediante la determinación de la constante endpoints.API_EXPLORER_CLIENT_ID. Ten en cuenta que tu API aún tendrá visibilidad pública y que se podrá acceder a ella con el Explorador de API si allowed_client_ids solo contiene endpoints.API_EXPLORER_CLIENT_ID y tú implementas la API.

Acerca de los públicos

La lista allowed_client_ids protege a la API de backend de clientes no autorizados. Aun así, se necesita una protección mayor para proteger a los clientes, de manera que el token de autenticación solo funcione con la API de backend deseada. Para clientes Android, este mecanismo es el argumento audiences, en el cual se especifica el ID de cliente de la API de backend.

Ten en cuenta que, cuando creas un proyecto de la consola de Google Cloud, se crea automáticamente un ID de cliente predeterminado y se lo nombra para que lo use el proyecto. Cuando subes tu API de backend en App Engine, en esta se usa el ID de cliente. Este es el ID de cliente web mencionado en la autenticación de la API.

Emisor de tokens de autenticación de terceros

Si tu aplicación acepta tokens de autenticación que no son tokens de ID de Google y están provistos por emisores de terceros, debes configurar de forma correcta los argumentos audiences y issuers en @endpoints.api para proporcionar la información sobre los emisores de terceros. Por ejemplo:

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

Cómo definir un método de API (@endpoints.method)

Puedes configurar audiences, scopes y allowed_client_ids para toda la API mediante @endpoints.api, o para un método mediante @endpoints.method. Si esta configuración se especifica en el nivel de la API y en el del método, se anula la configuración de este último.

Para crear un método en tu API, decora el método de Python correspondiente con @endpoints.method y proporciona argumentos a fin de configurar el uso del método. Por ejemplo, se puede especificar qué clase Message de solicitud y respuesta usar.

Los argumentos disponibles se enumeran en la siguiente tabla:

Argumentos @endpoints.method Descripción Ejemplo
allowed_client_ids Esta configuración anula el atributo equivalente especificado en @endpoints.api. Para obtener más información, consulta ID de cliente y públicos permitidos. ['1-web-apps.apps.googleusercontent.com', '2-android-apps.apps.googleusercontent.com']
api_key_required Opcional. Se usa para restringir el acceso a las solicitudes que proporcionan una clave de API. api_key_required=True
audiences Anula el argumento equivalente especificado en @endpoints.api. Para obtener más información, consulta ID de cliente y públicos permitidos. ['1-web-apps.apps.googleusercontent.com']
metric_costs Opcional. Indica que el método tiene un límite de cuota. Es un diccionario con los pares siguientes de clave-valor:
  • name: un nombre especificado en el argumento limit_definitions para el decorador de la API.
  • cost: un número entero que especifica el costo de cada solicitud. El costo permite que los métodos realicen un consumo de la misma cuota a velocidades diferentes. Por ejemplo, si una cuota tiene un límite de 1,000 y un costo de 1, la aplicación que realiza la llamada puede hacer 1,000 solicitudes por minuto antes de sobrepasar el límite. Con un costo de 2 por la misma cuota, mediante la aplicación con la que se hace la llamada, se pueden hacer solo 500 solicitudes por minuto antes de sobrepasar el límite.
metric_costs={'read-requests': 1}
http_method El método HTTP para usar. Si no configuras esta opción, 'POST' se usará de forma predeterminada. 'GET'
name Un nombre alternativo para este método. El valor name debe cumplir con estos requisitos:
  • Debe comenzar con minúsculas.
  • Debe coincidir con la expresión regular [a-z]+[A-Za-z0-9]*.
'yourApi'
path La ruta del URI para acceder a este método. Si no configuras esto, se usa el nombre del método de Python. Si planeas agregar la administración de la API, no incluyas una barra al final de la ruta. 'yourapi/path'
Clase Request Message La clase Request Message del RPC del protocolo de Google que se usa en la llamada del método. Como alternativa, puedes proporcionar el nombre de la clase. YourRequestClass
Clase Response Message La clase Response Message del RPC del protocolo de Google que se usa en la llamada del método. Como alternativa, puedes proporcionar el nombre de la clase. YourResponseClass

Utiliza ResourceContainer para los argumentos de ruta o de string de consulta

Si la solicitud contiene argumentos de ruta o de string de consulta, no puedes usar una clase Message simple como se describe en Cómo crear la API. En su lugar, debes usar una clase ResourceContainer, de la siguiente manera:

  1. Define una clase Message que tenga todos los argumentos que se pasan en el cuerpo de la solicitud. Si no hay argumentos en el cuerpo de la solicitud, no necesitas definir una clase Message, solo usa message_types.VoidMessage. Por ejemplo:

    class Greeting(messages.Message):
        """Greeting that stores a message."""
    
        message = messages.StringField(1)
  2. Define un ResourceContainer con la clase Message que definiste en el paso anterior como el primer parámetro. Especifica la ruta y los argumentos de string de consulta en los parámetros subsiguientes. Por ejemplo:

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

    En el ejemplo anterior, el primer argumento es la clase Message para los datos en el cuerpo de la solicitud y times es un número esperado en la ruta o string de consulta que acompaña a la solicitud.

  3. Proporciona el ResourceContainer al método que maneja la solicitud, en el primer parámetro que reemplaza la clase Message de solicitud que, de lo contrario, se proporcionaría en esa ubicación. Este fragmento muestra el ResourceContainer y el 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. Agrega el parámetro path como se muestra para incluir tu API.

  5. Si tu ResourceContainer tiene un argumento obligatorio, mediante una solicitud del cliente, se debe incluirlo en una string de consulta (por ejemplo, yourApi?times=2) o en la ruta de URL (por ejemplo, yourApi/2). Sin embargo, para que en la API se reciba un valor de argumento con la ruta de URL, también debes agregar el nombre del argumento a la ruta de API como se muestra para el argumento {times} en path='yourApi/{times}.

¿Qué sigue?