Integraciones de proxy de Lambda en API Gateway - Amazon API Gateway

Integraciones de proxy de Lambda en API Gateway

En la siguiente sección se muestra cómo utilizar una integración de proxy de Lambda.

Descripción de la integración de proxy de Lambda en API Gateway

La integración de proxy de Lambda de Amazon API Gateway es un mecanismo sencillo, potente y ágil para desarrollar una API con la configuración de un solo método de API. La integración de proxy de Lambda permite al cliente llamar a una única función de Lambda en el backend. La función obtiene acceso a muchos recursos o características de otros servicios de AWS, incluidas las llamadas a otras funciones Lambda.

En la integración de proxy de Lambda, cuando un cliente envía una solicitud de API, API Gateway pasa a la función de Lambda integrada un evento de objeto, salvo que no se conserve el orden de los parámetros de la solicitud. Estos datos de la solicitud incluyen los encabezados de solicitud, los parámetros de cadena de consulta, las variables de ruta de la URL, la carga y los datos de configuración de la API. Los datos de configuración pueden incluir el nombre de la etapa de implementación actual, las variables de la etapa, la identidad del usuario o el contexto de autorización (si lo hubiera). La función de Lambda del backend analiza los datos de la solicitud entrante para determinar la respuesta que devuelve. Para que API Gateway transmita la salida de Lambda como la respuesta de la API al cliente, la función de Lambda debe devolver el resultado en este formato.

Dado que API Gateway no interviene mucho entre el cliente y la función de Lambda del backend para la integración de proxy de Lambda, el cliente y la función de Lambda integrada pueden adaptarse a los cambios de cada uno sin interrumpir la configuración de integración existente de la API. Para habilitar esto, el cliente debe seguir los protocolos de aplicación promulgados por la función de Lambda del backend.

Puede configurar una integración de proxy de Lambda para cualquier método de API. Sin embargo, una integración de proxy de Lambda es más potente cuando se configura para un método de API que implica un recurso de proxy genérico. El recurso de proxy genérico se puede indicar mediante una variable especial de ruta basada en plantilla de {proxy+}, el marcador de posición del método catch-all ANY o ambos. El cliente puede transmitir la entrada a la función de Lambda del backend en la solicitud entrante según lo soliciten los parámetros o la carga aplicable. Los parámetros de solicitud incluyen encabezados, variables de ruta de la URL, parámetros de cadenas de consulta y la carga aplicable. La función de Lambda integrada verifica todas las fuentes de entrada antes de procesar la solicitud y de responder al cliente con mensajes de error importantes si falta alguna de las entradas requeridas.

Al llamar a un método de API integrado con el método HTTP genérico de ANY y el recurso genérico de {proxy+}, el cliente envía una solicitud con un método HTTP específico en lugar de ANY. El cliente también especifica una ruta de URL específica en lugar de {proxy+} e incluye cualquier encabezado, parámetro de cadena de consulta o una carga aplicable.

En la siguiente lista se resumen los comportamientos de tiempo de ejecución de los diferentes métodos de API con la integración de proxy de Lambda:

  • ANY /{proxy+}: el cliente debe elegir un método HTTP específico, debe establecer una jerarquía de ruta de recursos específica y puede establecer cualquier encabezado, parámetro de cadena de consulta y carga aplicable para transmitir los datos como entrada a la función de Lambda integrada.

  • ANY /res: el cliente debe elegir un método HTTP específico y puede establecer cualquier encabezado, parámetro de cadena de consulta y carga aplicable para transmitir los datos como entrada a la función de Lambda integrada.

  • GET|POST|PUT|... /{proxy+}: el cliente puede establecer una jerarquía de ruta de recursos específica, cualquier encabezado, parámetro de cadena de consulta y carga aplicable para transmitir los datos como entrada a la función de Lambda integrada.

  • GET|POST|PUT|... /res/{path}/...: el cliente debe elegir un segmento de ruta específico (para la variable {path}) y puede establecer cualquier encabezado de solicitud, parámetro de cadena de consulta y carga aplicable para transmitir los datos de entrada a la función de Lambda integrada.

  • GET|POST|PUT|... /res: el cliente puede elegir cualquier encabezado de solicitud, parámetro de cadena de consulta y carga aplicable para transmitir los datos de entrada a la función de Lambda integrada.

Tanto el recurso de proxy de {proxy+} como el recurso personalizado de {custom} se expresan como variables de ruta basada en plantilla. Sin embargo, {proxy+} puede hacer referencia a cualquier recurso en una jerarquía de ruta, mientras que {custom} se refiere únicamente a un segmento de ruta específico. Por ejemplo, una tienda de comestibles podría organizar un inventario de productos en línea por nombres de departamento, categorías de productos y tipos de productos. El sitio web de la tienda de comestibles puede entonces representar los productos disponibles con las siguientes variables de ruta basada en plantilla para los recursos personalizados: /{department}/{produce-category}/{product-type}. Por ejemplo, las manzanas están representadas con /produce/fruit/apple y las zanahorias con /produce/vegetables/carrot. También puede utilizar /{proxy+} para representar a cualquier departamento, cualquier categoría de producto o cualquier tipo de producto que un cliente puede buscar mientras realiza sus compras en la tienda en línea. Por ejemplo, /{proxy+} puede hacer referencia a cualquiera de los siguientes elementos:

  • /produce

  • /produce/fruit

  • /produce/vegetables/carrot

Para que los clientes puedan buscar cualquier producto disponible, su categoría de producto y el departamento asociado en la tienda, puede exponer un único método de GET /{proxy+} con permisos de solo lectura. Del mismo modo, para permitir que un supervisor actualice el inventario del departamento produce, puede configurar otro método único de PUT /produce/{proxy+} con permisos de lectura y escritura. Para permitir que un cajero actualice el total de unidades de una verdura, puede configurar un método POST /produce/vegetables/{proxy+} con permisos de lectura y escritura. Para que el gerente de una tienda pueda realizar cualquier acción posible en cualquier producto disponible, el desarrollador de la tienda en línea puede exponer el método ANY /{proxy+} con permisos de lectura y escritura. En cualquier caso, en el tiempo de ejecución, el cliente o el empleado debe seleccionar un producto específico de un tipo determinado en un departamento elegido o en un departamento específico.

Para obtener más información acerca de la configuración de las integraciones del proxy de API Gateway, consulte Configuración de una integración de proxy con un recurso de proxy.

La integración del proxy requiere que el cliente tenga un conocimiento más detallado de los requisitos del backend. Por lo tanto, para garantizar un óptimo rendimiento de la aplicación y experiencia del usuario, el desarrollador del backend debe comunicar con claridad al desarrollador del cliente los requisitos del backend y proporcionar un mecanismo de comentarios de errores sólido cuando los requisitos no se cumplan.

Compatibilidad con encabezados de varios valores y parámetros de cadenas de consulta

API Gateway ahora es compatible con varios encabezados y parámetros de cadena de consulta que tengan el mismo nombre. Los encabezados de varios valores y los encabezados y parámetros de un solo valor se pueden combinar en las mismas solicitudes y respuestas. Para obtener más información, consulte Formato de entrada de una función de Lambda para la integración de proxy y Formato de salida de una función de Lambda para la integración de proxy.

Formato de entrada de una función de Lambda para la integración de proxy

Con la integración de proxy de Lambda, API Gateway asigna toda la solicitud de cliente al parámetro de entrada event de la función de Lambda del backend. En el siguiente ejemplo, se muestra la estructura de un evento que API Gateway envía a una integración de proxy de Lambda.

{ "resource": "/my/path", "path": "/my/path", "httpMethod": "GET", "headers": { "header1": "value1", "header2": "value1,value2" }, "multiValueHeaders": { "header1": [ "value1" ], "header2": [ "value1", "value2" ] }, "queryStringParameters": { "parameter1": "value1,value2", "parameter2": "value" }, "multiValueQueryStringParameters": { "parameter1": [ "value1", "value2" ], "parameter2": [ "value" ] }, "requestContext": { "accountId": "123456789012", "apiId": "id", "authorizer": { "claims": null, "scopes": null }, "domainName": "id.execute-api.us-east-1.amazonaws.com", "domainPrefix": "id", "extendedRequestId": "request-id", "httpMethod": "GET", "identity": { "accessKey": null, "accountId": null, "caller": null, "cognitoAuthenticationProvider": null, "cognitoAuthenticationType": null, "cognitoIdentityId": null, "cognitoIdentityPoolId": null, "principalOrgId": null, "sourceIp": "IP", "user": null, "userAgent": "user-agent", "userArn": null, "clientCert": { "clientCertPem": "CERT_CONTENT", "subjectDN": "www.example.com", "issuerDN": "Example issuer", "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", "validity": { "notBefore": "May 28 12:30:02 2019 GMT", "notAfter": "Aug 5 09:36:04 2021 GMT" } } }, "path": "/my/path", "protocol": "HTTP/1.1", "requestId": "id=", "requestTime": "04/Mar/2020:19:15:17 +0000", "requestTimeEpoch": 1583349317135, "resourceId": null, "resourcePath": "/my/path", "stage": "$default" }, "pathParameters": null, "stageVariables": null, "body": "Hello from Lambda!", "isBase64Encoded": false }
nota

En la entrada:

  • La clave headers solo puede contener encabezados de un solo valor.

  • La clave multiValueHeaders puede contener encabezados de varios valores y encabezados de un solo valor.

  • Si especifica valores para headers y multiValueHeaders, API Gateway los combina en una sola lista. Si se especifica el mismo par de clave-valor en ambos, solo los valores de multiValueHeaders aparecerán en la lista combinada.

En la entrada a la función de Lambda de backend, el objeto requestContext es un mapa de pares de clave-valor. En cada par, la clave es el nombre de una propiedad de la variable $context y el valor es el valor de esa propiedad. API Gateway podría agregar nuevas claves al mapa.

En función de las características habilitadas, el mapa requestContext puede variar de API en API. Por ejemplo, en el ejemplo anterior, no se especifica ningún tipo de autorización, por lo que no hay propiedades $context.authorizer.* o $context.identity.* presentes. Cuando se especifica un tipo de autorización, esto hace que API Gateway transfiera información del usuario autorizado al punto de enlace de integración en un objeto requestContext.identity tal y como se indica a continuación:

  • Cuando el tipo de autorización es AWS_IAM, la información del usuario autorizado incluye propiedades $context.identity.*.

  • Cuando el tipo de autorización es COGNITO_USER_POOLS (autorizador de Amazon Cognito), la información del usuario autorizado incluye las propiedades $context.identity.cognito* y $context.authorizer.claims.*.

  • Cuando el tipo de autorización es CUSTOM (autorizador de Lambda), la información del usuario autorizado incluye las propiedades $context.authorizer.principalId y otras propiedades $context.authorizer.* aplicables.

Formato de salida de una función de Lambda para la integración de proxy

Con la integración de proxy de Lambda, API Gateway requiere que la función de Lambda del backend devuelva la salida de acuerdo con el siguiente formato JSON:

{ "isBase64Encoded": true|false, "statusCode": httpStatusCode, "headers": { "headerName": "headerValue", ... }, "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... }, "body": "..." }

En la salida:

  • Las claves headers y multiValueHeaders pueden no estar especificadas si no se van a devolver más encabezados de respuesta.

  • La clave headers solo puede contener encabezados de un solo valor.

  • La clave multiValueHeaders puede contener encabezados de varios valores y encabezados de un solo valor. Puede utilizar la clave multiValueHeaders para especificar todos los encabezados adicionales, incluidos los que solo contienen un valor.

  • Si especifica valores para headers y multiValueHeaders, API Gateway los combina en una sola lista. Si se especifica el mismo par de clave-valor en ambos, solo los valores de multiValueHeaders aparecerán en la lista combinada.

Para habilitar CORS para la integración de proxy de Lambda, debe agregar Access-Control-Allow-Origin:domain-name a la salida headers. domain-name puede ser * para cualquier nombre de dominio. La salida body se serializa en el frontend como la carga de respuesta del método. Si body es un blob binario, puede codificarlo como una cadena codificada en Base64 estableciendo isBase64Encoded en true y configurando */* como Binary Media Type (Tipo de medio binario). De lo contrario, puede establecerlo en false o dejarlo sin especificar.

nota

Para obtener más información acerca de cómo habilitar la compatibilidad con datos binarios, consulte Habilitar la compatibilidad con datos binarios mediante la consola de API Gateway. Para ver una función de Lambda de ejemplo, consulte Devolución de medios binarios desde una integración de proxy de Lambda en API Gateway.

Si la salida de la función tiene un formato diferente, API Gateway devuelve una respuesta de error 502 Bad Gateway.

Para devolver una respuesta en una función de Lambda de Node.js, puede utilizar comandos como los siguientes:

  • Para devolver un resultado correcto, llame a callback(null, {"statusCode": 200, "body": "results"}).

  • Para producir una excepción, llame a callback(new Error('internal server error')).

  • En caso de que se produzca un error del lado del cliente (por ejemplo, si falta un parámetro necesario), puede llamar a callback(null, {"statusCode": 400, "body": "Missing parameters of ..."}) para devolver el error sin iniciar una excepción.

En una función de Lambda de async de Node.js, la sintaxis correspondiente sería:

  • Para devolver un resultado correcto, llame a return {"statusCode": 200, "body": "results"}.

  • Para producir una excepción, llame a throw new Error("internal server error").

  • En caso de que se produzca un error del lado del cliente (por ejemplo, si falta un parámetro necesario), puede llamar a return {"statusCode": 400, "body": "Missing parameters of ..."} para devolver el error sin iniciar una excepción.