Configurar integrações de proxy do Lambda no API Gateway - Amazon API Gateway

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Configurar integrações de proxy do Lambda no API Gateway

Compreender a integração de proxy do Lambda do API Gateway

A integração de proxy do Lambda do Amazon API Gateway é um mecanismo simples, potente e ágil para criar uma API com uma configuração de um único método de API. A integração de proxy do Lambda permite que o cliente chame uma única função do Lambda no backend. A função acessa muitos recursos ou recursos de outros AWS serviços, incluindo a chamada de outras funções do Lambda.

Na integração de proxy do Lambda, quando um cliente envia uma solicitação de API, o API Gateway repassa um objeto do evento para a função do Lambda integrada, exceto pelo fato de que a ordem dos parâmetros da solicitação não é preservada. Esses dados de solicitação incluem cabeçalhos de solicitação, parâmetros de strings de consulta, variáveis de caminho URL, carga e dados de configuração da API. Os dados de configuração podem incluir o nome do estágio de implantação atual, variáveis de estágio, identidade do usuário ou contexto de autorização (se houver). A função do Lambda do backend analisa os dados da solicitação recebida para determinar a resposta que ela retorna. Para que o API Gateway passe a saída do Lambda como a resposta da API para o cliente, a função do Lambda deve retornar o resultado neste formato.

Como o API Gateway não interfere muito entre o cliente e a função do Lambda do backend para a integração de proxy do Lambda, o cliente e a função do Lambda integrada podem se adaptar às alterações mútuas sem quebrar a configuração de integração existente da API. Para permitir isso, o cliente deve seguir os protocolos de aplicação promulgados pela função do Lambda de backend.

É possível configurar uma integração de proxy do Lambda para qualquer método de API. Mas uma integração de proxy do Lambda é mais potente quando configurada para um método de API que envolve um recurso de proxy genérico. O recurso de proxy genérico pode ser identificado por um modelo variável de caminho especial de {proxy+}, pelo espaço reservado de método ANY ou ambos. O cliente pode passar a entrada da função do Lambda de backend na solicitação recebida como parâmetros da solicitação ou carga aplicável. Os parâmetros de solicitação incluem cabeçalhos, variáveis de caminho URL, parâmetros de string de consulta e a carga aplicável. A função do Lambda integrada verifica todas as fontes de entrada antes de processar a solicitação e responder ao cliente com mensagens de erro significativas se qualquer uma das entradas obrigatórias estiver ausente.

Ao chamar um método de API integrado ao método HTTP genérico de ANY e o recurso genérico de {proxy+}, o cliente envia uma solicitação com um método HTTP específico em vez de ANY. O cliente também especifica determinado caminho URL em vez de {proxy+}, e inclui todos os cabeçalhos necessários, parâmetros de strings de consulta ou uma carga aplicável.

A lista a seguir resume comportamentos de tempo de execução de diferentes métodos de API com a integração de proxy do Lambda:

  • ANY /{proxy+}: o cliente deve escolher determinado método HTTP, definir determinada hierarquia de caminho de recursos e pode definir todos os cabeçalhos, parâmetros de strings de consulta e carga aplicáveis para passar os dados como entrada para a função do Lambda integrada.

  • ANY /res: o cliente deve escolher determinado método HTTP e pode definir todos os cabeçalhos, parâmetros de strings de consulta e carga aplicáveis para passar os dados como entrada para a função do Lambda integrada.

  • GET|POST|PUT|... /{proxy+}: o cliente pode definir determinada hierarquia de caminho de recursos, cabeçalhos, parâmetros de strings de consulta e carga aplicáveis para passar os dados como entrada para a função do Lambda integrada.

  • GET|POST|PUT|... /res/{path}/...: o cliente deve escolher determinado segmento de caminho (para a variável {path}) e pode definir os cabeçalhos de solicitação, parâmetros de strings de consulta e carga aplicáveis para passar os dados de entrada para a função do Lambda integrada.

  • GET|POST|PUT|... /res: o cliente pode escolher os cabeçalhos de solicitação, parâmetros de strings de consulta e carga aplicáveis para passar dados de entrada para a função do Lambda integrada.

Tanto o recurso de proxy de {proxy+} quanto o recurso personalizado de {custom} são expressos como modelos de variáveis de caminho. No entanto, {proxy+} pode indicar qualquer recurso ao longo de uma hierarquia de caminho, enquanto {custom} refere-se apenas a determinado segmento de caminho. Por exemplo, um supermercado pode organizar seu inventário de produtos online por nomes de departamento, categorias de produtos e tipos de produtos. O site do supermercado pode representar os produtos disponíveis pelos seguintes modelos de variáveis de caminho de recursos personalizados: /{department}/{produce-category}/{product-type}. Por exemplo, maçãs são representadas por /produce/fruit/apple e cenouras por /produce/vegetables/carrot. Ele também pode usar /{proxy+} para representar qualquer departamento, categoria ou tipo de produto que o cliente pode procurar ao fazer compras na loja online. Por exemplo, /{proxy+} pode indicar qualquer um dos seguintes itens:

  • /produce

  • /produce/fruit

  • /produce/vegetables/carrot

Para permitir que os clientes procurem qualquer produto disponível, a categoria do produto e o departamento associado, você pode expor um único método de GET /{proxy+} com permissões somente leitura. Da mesma forma, para permitir que um supervisor atualize o inventário do departamento do produce, você pode configurar outro método único de PUT /produce/{proxy+} com as permissões de leitura/gravação. Para permitir que um caixa atualize o total de um vegetal, você pode configurar um método POST /produce/vegetables/{proxy+} com permissões de leitura/gravação. Para permitir que um gerente de loja realize qualquer ação possível em qualquer produto disponível, o desenvolvedor da loja online pode expor o método ANY /{proxy+} com permissões de leitura/gravação. Em qualquer caso, na ocasião da execução, o cliente ou o funcionário deve selecionar um produto específico de determinado tipo em um departamento escolhido, uma categoria de produto específica em um departamento escolhido ou um departamento específico.

Para obter mais informações sobre como configurar integrações de proxy do API Gateway, consulte Configurar a integração de proxy com um recurso de proxy.

A integração de proxy exige que o cliente tenha um conhecimento mais detalhado dos requisitos de backend. Portanto, para garantir uma melhor performance das aplicações e da experiência do usuário, o desenvolvedor de backend deve comunicar claramente ao desenvolvedor cliente os requisitos do backend e fornecer um mecanismo de feedback de erro robusto quando os requisitos não são atendidos.

Suporte para cabeçalhos de vários valores e parâmetros de string de consulta

Agora o API Gateway oferece suporte a vários cabeçalhos e parâmetros de string de consulta que possuem o mesmo nome. Cabeçalhos de vários valores, bem como cabeçalhos e parâmetros de valor único, podem ser combinados nas mesmas solicitações e respostas. Para ter mais informações, consulte Formato de entrada de uma função do Lambda para integração de proxy e Formato de saída de uma função do Lambda para integração de proxy.

Configurar um recurso de proxy com a integração de proxy do Lambda

Para configurar um recurso de proxy com o tipo de integração de proxy do Lambda, crie um recurso de API com um parâmetro de caminho voraz (por exemplo, /parent/{proxy+}) e integre esse recurso a um backend da função do Lambda (por exemplo, arn:aws:lambda:us-west-2:123456789012:function:SimpleLambda4ProxyResource) no método ANY. O parâmetro de caminho voraz deve estar no final do caminho do recurso da API. Como no caso de um recurso não proxy, é possível configurar o recurso de proxy usando o console do API Gateway, importando um arquivo de definição do OpenAPI ou chamando diretamente a API REST do API Gateway.

O seguinte arquivo de definição de API do OpenAPI mostra um exemplo de uma API com um recurso de proxy que está integrado à função do Lambda chamada SimpleLambda4ProxyResource.

OpenAPI 3.0
{ "openapi": "3.0.0", "info": { "version": "2016-09-12T17:50:37Z", "title": "ProxyIntegrationWithLambda" }, "paths": { "/{proxy+}": { "x-amazon-apigateway-any-method": { "parameters": [ { "name": "proxy", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": {}, "x-amazon-apigateway-integration": { "responses": { "default": { "statusCode": "200" } }, "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:SimpleLambda4ProxyResource/invocations", "passthroughBehavior": "when_no_match", "httpMethod": "POST", "cacheNamespace": "roq9wj", "cacheKeyParameters": [ "method.request.path.proxy" ], "type": "aws_proxy" } } } }, "servers": [ { "url": "https://gy415nuibc.execute-api.us-east-1.amazonaws.com/{basePath}", "variables": { "basePath": { "default": "/testStage" } } } ] }
OpenAPI 2.0
{ "swagger": "2.0", "info": { "version": "2016-09-12T17:50:37Z", "title": "ProxyIntegrationWithLambda" }, "host": "gy415nuibc.execute-api.us-east-1.amazonaws.com", "basePath": "/testStage", "schemes": [ "https" ], "paths": { "/{proxy+}": { "x-amazon-apigateway-any-method": { "produces": [ "application/json" ], "parameters": [ { "name": "proxy", "in": "path", "required": true, "type": "string" } ], "responses": {}, "x-amazon-apigateway-integration": { "responses": { "default": { "statusCode": "200" } }, "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:SimpleLambda4ProxyResource/invocations", "passthroughBehavior": "when_no_match", "httpMethod": "POST", "cacheNamespace": "roq9wj", "cacheKeyParameters": [ "method.request.path.proxy" ], "type": "aws_proxy" } } } } }

Na integração de proxy do Lambda, em tempo de execução, o API Gateway mapeia uma solicitação de entrada no parâmetro event de entrada da função do Lambda. A entrada inclui o método de solicitação, o caminho, os cabeçalhos, qualquer parâmetro de consulta, qualquer carga, o contexto associado e quaisquer variáveis de estágio definidas. O formato de entrada é explicado em Formato de entrada de uma função do Lambda para integração de proxy. Para o API Gateway mapear a saída do Lambda para respostas HTTP com êxito, a função do Lambda deve processar a saída do resultado no formato descrito em Formato de saída de uma função do Lambda para integração de proxy.

Com a integração de proxy do Lambda de um recurso de proxy por meio do método ANY, a função do Lambda de back-end única serve como o manipulador de eventos para todas as solicitações por meio do recurso de proxy. Por exemplo, para registrar padrões de tráfego, você pode fazer com que um dispositivo móvel envie suas informações de localização de estado, cidade, rua e edifício, enviando uma solicitação com /state/city/street/house no caminho da URL para o recurso de proxy. Dessa forma, a função do Lambda de backend pode analisar o caminho da URL e inserir as tuplas de localização em uma tabela do DynamoDB.

Configure a integração do proxy Lambda usando o AWS CLI

Nesta seção, mostramos como usar AWS CLI para configurar uma API com a integração do proxy Lambda.

nota

Para obter instruções detalhadas sobre como usar o console do API Gateway para configurar um recurso de proxy com a integração de proxy do Lambda, consulte Tutorial: Criar uma API REST Hello World com integração de proxy do Lambda.

Como exemplo, usamos a seguinte função do Lambda como o backend da API:

export const handler = function(event, context, callback) { console.log('Received event:', JSON.stringify(event, null, 2)); var res ={ "statusCode": 200, "headers": { "Content-Type": "*/*" } }; var greeter = 'World'; if (event.greeter && event.greeter!=="") { greeter = event.greeter; } else if (event.body && event.body !== "") { var body = JSON.parse(event.body); if (body.greeter && body.greeter !== "") { greeter = body.greeter; } } else if (event.queryStringParameters && event.queryStringParameters.greeter && event.queryStringParameters.greeter !== "") { greeter = event.queryStringParameters.greeter; } else if (event.multiValueHeaders && event.multiValueHeaders.greeter && event.multiValueHeaders.greeter != "") { greeter = event.multiValueHeaders.greeter.join(" and "); } else if (event.headers && event.headers.greeter && event.headers.greeter != "") { greeter = event.headers.greeter; } res.body = "Hello, " + greeter + "!"; callback(null, res); };

Comparando isso com a configuração de integração personalizada do Lambda, a entrada para essa função do Lambda pode ser expressa nos parâmetros da solicitação e no corpo. Você tem mais latitude para permitir que o cliente transmita os mesmos dados de entrada. Aqui, o cliente pode transmitir o nome do greeter como um parâmetro de string de consulta, um cabeçalho ou uma propriedade de corpo. A função também pode oferecer suporte à integração personalizada do Lambda. A configuração da API é mais simples. Você não configura a resposta de método nem a resposta de integração.

Para configurar uma integração de proxy Lambda usando o AWS CLI
  1. Chame o comando create-rest-api para criar uma API:

    aws apigateway create-rest-api --name 'HelloWorld (AWS CLI)' --region us-west-2

    Observe o valor id da API resultante (te6si5ach7) na resposta:

    { "name": "HelloWorldProxy (AWS CLI)", "id": "te6si5ach7", "createdDate": 1508461860 }

    Você precisará do id da API durante toda esta seção.

  2. Chame o comando get-resources para obter o id do recurso raiz:

    aws apigateway get-resources --rest-api-id te6si5ach7 --region us-west-2

    A resposta bem-sucedida é mostrada da seguinte forma:

    { "items": [ { "path": "/", "id": "krznpq9xpg" } ] }

    Anote o valor id do recurso raiz (krznpq9xpg). Você precisará dele na próxima etapa e mais adiante.

  3. Chame create-resource para criar um recurso do API Gateway de /greeting:

    aws apigateway create-resource --rest-api-id te6si5ach7 \ --region us-west-2 \ --parent-id krznpq9xpg \ --path-part {proxy+}

    A resposta correta é semelhante ao seguinte:

    { "path": "/{proxy+}", "pathPart": "{proxy+}", "id": "2jf6xt", "parentId": "krznpq9xpg" }

    Anote o valor {proxy+} do recurso id (2jf6xt). Você precisará dele para criar um método no recurso /{proxy+} na próxima etapa.

  4. Chame put-method para criar uma solicitação de método ANY de ANY /{proxy+}:

    aws apigateway put-method --rest-api-id te6si5ach7 \ --region us-west-2 \ --resource-id 2jf6xt \ --http-method ANY \ --authorization-type "NONE"

    A resposta correta é semelhante ao seguinte:

    { "apiKeyRequired": false, "httpMethod": "ANY", "authorizationType": "NONE" }

    Esse método de API permite que o cliente receba ou envie saudações da função do Lambda no backend.

  5. Chame put-integration para configurar a integração do método ANY /{proxy+} com uma função do Lambda denominada HelloWorld. Essa função responde à solicitação com uma mensagem de "Hello, {name}!", se o parâmetro greeter for fornecido ou "Hello, World!", se o parâmetro de string de consulta não for definido.

    aws apigateway put-integration \ --region us-west-2 \ --rest-api-id te6si5ach7 \ --resource-id 2jf6xt \ --http-method ANY \ --type AWS_PROXY \ --integration-http-method POST \ --uri arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:HelloWorld/invocations \ --credentials arn:aws:iam::123456789012:role/apigAwsProxyRole
    Importante

    Para integrações do Lambda, você deve usar o método HTTP de POST para a solicitação de integração, de acordo com a especificação da ação do serviço do Lambda para invocações de função. A função do IAM de apigAwsProxyRole deve ter políticas que permitem ao serviço apigateway invocar funções do Lambda. Para obter mais informações sobre as permissões do IAM, consulte Modelo de permissões do API Gateway para invocar uma API.

    A saída bem-sucedida é semelhante seguinte:

    { "passthroughBehavior": "WHEN_NO_MATCH", "cacheKeyParameters": [], "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:1234567890:function:HelloWorld/invocations", "httpMethod": "POST", "cacheNamespace": "vvom7n", "credentials": "arn:aws:iam::1234567890:role/apigAwsProxyRole", "type": "AWS_PROXY" }

    Em vez de fornecer uma função do IAM para credentials, você pode chamar o comando add-permission para adicionar permissões baseadas em recurso. Isso é o que o console do API Gateway faz.

  6. Chame create-deployment para implantar a API em um estágio test:

    aws apigateway create-deployment --rest-api-id te6si5ach7 --stage-name test --region us-west-2
  7. Teste a API usando os seguintes comandos cURL em um terminal.

    Chamando a API com o parâmetro de string de consulta de ?greeter=jane:

    curl -X GET 'https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/greeting?greeter=jane'

    Chamando a API com um parâmetro de cabeçalho de greeter:jane:

    curl -X GET https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/hi \ -H 'content-type: application/json' \ -H 'greeter: jane'

    Chamando a API com um corpo de {"greeter":"jane"}:

    curl -X POST https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/hi \ -H 'content-type: application/json' \ -d '{ "greeter": "jane" }'

    Em todos os casos, a saída é uma resposta 200 com o corpo de resposta a seguir:

    Hello, jane!

Formato de entrada de uma função do Lambda para integração de proxy

Com a integração de proxy do Lambda, o API Gateway mapeia toda a solicitação do cliente para o parâmetro event de entrada da função do Lambda de back-end. O exemplo a seguir mostra a estrutura de um evento que o API Gateway envia para uma integração de proxy do 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

Na entrada:

  • A chave headers só pode conter cabeçalhos de valor único.

  • A chave multiValueHeaders pode conter cabeçalhos de vários valores e cabeçalhos de valor único.

  • Se você especificar valores para headers e multiValueHeaders, o API Gateway os mesclará em uma única lista. Se o mesmo de chave/valor for especificado em ambos, somente os valores de multiValueHeaders aparecerão na lista mesclada.

Na entrada para a função do Lambda do back-end, o objeto requestContext é um mapa de pares de chave/valor. Em cada par, a chave é o nome de uma propriedade de variável $context, e o valor é o valor dessa propriedade. O API Gateway pode adicionar novas chaves ao mapa.

Dependendo dos recursos que estão habilitados, o mapa requestContext pode variar de acordo com a API. Por exemplo, no exemplo anterior, nenhum tipo de autorização é especificado. Portanto, nenhuma propriedade $context.authorizer.* ou $context.identity.* está presente. Quando um tipo de autorização é especificado, isso faz com que o API Gateway repasse informações do usuário autorizado para o endpoint de integração em um objeto requestContext.identity da seguinte forma:

  • Quando o tipo de autorização é AWS_IAM, as informações do usuário autorizado incluem propriedades $context.identity.*.

  • Quando o tipo de autorização é COGNITO_USER_POOLS (autorizador do Amazon Cognito), as informações do usuário autorizado incluem propriedades $context.identity.cognito* e $context.authorizer.claims.*.

  • Quando o tipo de autorização é CUSTOM (autorizador do Lambda), as informações do usuário autorizado incluem propriedades $context.authorizer.principalId e outras $context.authorizer.* aplicáveis.

Formato de saída de uma função do Lambda para integração de proxy

Na integração de proxy do Lambda, o API Gateway requer a função do Lambda do backend para retornar a saída de acordo com o seguinte formato JSON:

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

Na saída:

  • As chaves headers e multiValueHeaders podem ser não especificadas se nenhum cabeçalho de resposta extra precisar ser retornado.

  • A chave headers só pode conter cabeçalhos de valor único.

  • A chave multiValueHeaders pode conter cabeçalhos de vários valores e cabeçalhos de valor único. Você pode usar a chave multiValueHeaders para especificar todos os seus cabeçalhos extras, incluindo os de valor único.

  • Se você especificar valores para headers e multiValueHeaders, o API Gateway os mesclará em uma única lista. Se o mesmo de chave/valor for especificado em ambos, somente os valores de multiValueHeaders aparecerão na lista mesclada.

Para ativar o CORS da integração de proxy do Lambda, você deve adicionar Access-Control-Allow-Origin:domain-name à saída headers. domain-name pode ser * para qualquer nome de domínio. A saída body é organizado para o front-end como a carga de resposta do método. Se body for um blob binário, você poderá codificá-lo como uma string codificada em Base64, definindo isBase64Encoded como true e configurando */* como Binary Media Type (Tipo de mídia binário). Caso contrário, será possível defini-lo como false ou deixá-lo sem especificação.

nota

Para obter mais informações sobre como habilitar o suporte a binários, consulte Ativação do suporte binário usando o console do API Gateway. Para obter um exemplo de função do Lambda, consulte Retornar mídia binária de uma integração de proxy do Lambda.

Se a saída da função for de um formato diferente, o API Gateway retorna uma resposta de erro 502 Bad Gateway.

Para retornar uma resposta em uma função do Lambda em Node.js, você poderá usar comandos como o seguinte:

  • Para retornar um resultado bem-sucedido, chame callback(null, {"statusCode": 200, "body": "results"}).

  • Para lançar uma exceção, chame callback(new Error('internal server error')).

  • Para um erro no lado do cliente, (se, por exemplo, um parâmetro necessário estiver ausente), você poderá chamar callback(null, {"statusCode": 400, "body": "Missing parameters of ..."}) para retornar o erro sem lançar uma exceção.

Em uma função do Lambda async no Node.js, a sintaxe equivalente seria:

  • Para retornar um resultado bem-sucedido, chame return {"statusCode": 200, "body": "results"}.

  • Para lançar uma exceção, chame throw new Error("internal server error").

  • Para um erro no lado do cliente, (se, por exemplo, um parâmetro necessário estiver ausente), você poderá chamar return {"statusCode": 400, "body": "Missing parameters of ..."} para retornar o erro sem lançar uma exceção.