Cómo pasar una cadena de consulta o un parámetro de ruta a AWS Lambda desde Amazon API Gateway

348

por ejemplo si queremos usar

GET /user?name=bob

o

GET /user/bob

¿Cómo pasaría estos dos ejemplos como parámetro a la función Lambda?

Vi algo sobre la configuración de un "mapeado de" en la documentación, pero no puedo encontrar esa configuración en la consola API Gateway.

  • method.request.path.parameter-namepara un parámetro de ruta denominado parameter-namecomo se define en la página Solicitud de método.
  • method.request.querystring.parameter-namepara un parámetro de cadena de consulta denominado parameter-namecomo se define en la página Solicitud de método.

No veo ninguna de estas opciones a pesar de que definí una cadena de consulta.

MonoBono
fuente

Respuestas:

299

A partir de septiembre de 2017, ya no tiene que configurar asignaciones para acceder al cuerpo de la solicitud.

Todo lo que necesita hacer es marcar, "Usar integración de proxy Lambda", en Solicitud de integración, en el recurso.

ingrese la descripción de la imagen aquí

Entonces podrá acceder a los parámetros de consulta, parámetros de ruta y encabezados de esta manera

event['pathParameters']['param1']
event["queryStringParameters"]['queryparam1']
event['requestContext']['identity']['userAgent']
event['requestContext']['identity']['sourceIP']
Jonathan
fuente
23
Este es un gran consejo. Pero, tenga en cuenta que activar Lambda Proxy Integration podría causar un error de "Respuesta de proxy Lambda mal formada". Aquí se explica cómo solucionarlo: stackoverflow.com/questions/43708017/…
AaronBaker
55
¿Hay alguna manera de hacer esto en Java, mientras se mantiene la deserialización transparente que RequestHandlerproporciona la implementación ?
zapato
2
¿Dónde está esta configuración?
red888
2
@MattWestlake Cree un recurso llamado usuario y debajo de él un recurso llamado {nombre} en API Gateway.
Jonathan
3
Solo quiero mencionar que después de este cambio también tuve que ir a Amazon API Gateway -> Acciones -> Implementar API y volver a implementar en el entorno en vivo.
victorvartan
221

Los pasos para que esto funcione son:

Dentro de la API Gateway Console ...

  1. ir Resources -> Integration Request
  2. haga clic en el ícono más o editar junto al menú desplegable de plantillas (extraño, ya que el campo de la plantilla ya está abierto y el botón aquí aparece atenuado)
  3. Escriba explícitamente application/jsonen el campo de tipo de contenido aunque muestre un valor predeterminado (si no lo hace, no se guardará y no le dará un mensaje de error)
  4. poner esto en la asignación de entrada { "name": "$input.params('name')" }

  5. haga clic en la casilla de verificación junto al menú desplegable de plantillas (supongo que esto es lo que finalmente lo guarda)

MonoBono
fuente
99
¿Alguna vez recibió esto para enviar parámetros de URL en URL como / user / bob donde estaba la ruta / user / {username}? He intentado todo tipo de permutaciones, pero no he podido resolverlo.
Lucas
55
¿Alguien sabe si hay alguna documentación oficial? sería bueno pasar por todos los parámetros de consulta o manejar valores opcionales con más gracia que las cadenas vacías
AxelTheGerman
66
Un consejo para los desarrolladores de iOS: API Gateway no pasará los datos de la consulta hasta que defina cada variable como cadena de consulta (en 'Solicitud de método') Y despliegue la API. Hasta la implementación, funciona desde la prueba de la consola, pero elimina las consultas de la aplicación.
AlexeyVMP
66
Lucas, lo hice funcionar usando el patrón / user / {username}. Solo recuerde si su ruta de recurso GET es / user / {username}, en el paso 4 la asignación de entrada se ve así {"name": "$ input.params ('username')"}
Gerard
134

He usado esta plantilla de mapeo para proporcionar el cuerpo, los encabezados, el método, la ruta y los parámetros de cadena de consulta de URL para el evento Lambda. Escribí una publicación de blog explicando la plantilla con más detalle: http://kennbrodhagen.net/2015/12/06/how-to-create-a-request-object-for-your-lambda-event-from-api- puerta/

Aquí está la plantilla de mapeo que puede usar:

{
  "method": "$context.httpMethod",
  "body" : $input.json('$'),
  "headers": {
    #foreach($param in $input.params().header.keySet())
    "$param": "$util.escapeJavaScript($input.params().header.get($param))" #if($foreach.hasNext),#end

    #end
  },
  "queryParams": {
    #foreach($param in $input.params().querystring.keySet())
    "$param": "$util.escapeJavaScript($input.params().querystring.get($param))" #if($foreach.hasNext),#end

    #end
  },
  "pathParams": {
    #foreach($param in $input.params().path.keySet())
    "$param": "$util.escapeJavaScript($input.params().path.get($param))" #if($foreach.hasNext),#end

    #end
  }  
}
kennbrodhagen
fuente
¡Asombroso! Estaba luchando con pasarle cosas genéricamente a mi manejador. La mejor respuesta aquí.
Venkat D.
Hice esto, pero todavía no obtengo nada. Está mostrando Indefinido. ¿Cómo se supone que debemos enviar los parámetros en la URL? ¿y necesitamos especificar el nombre de la variable en la URL como en un escenario normal de URL GET? Por favor, me ayudas con ésto.
Parthapratim Neog
8
No importa, obtuve el resultado. El problema era que agregué el mapeo y simplemente lo guardé, y no volví a deployusar la API. Una vez que implementé la API con la nueva asignación, funcionó bien. Gracias una tonelada.
Parthapratim Neog
@ shashu10 Ver mi respuesta
matsev
1
No puedo comenzar a decirte lo útil que es tu blog. Primero encontré la publicación "eturn-html-from-aws-api-gateway" y la seguí, porque es exactamente lo que necesitaba. Ahora necesito pasar algunos parámetros a la función y modificar el html en función de eso, ¡y nuevamente eres el único con una guía real! Todas las otras guías que he encontrado parecen perder el punto.
user3685427
41

Actualmente, se incluye una plantilla desplegable en la API Gateway Console en AWS.

Para su API, haga clic en el nombre del recurso ... luego OBTENGA

Expanda "Plantillas de mapeo corporal"

Escribir

aplicación / json

para Content-Type (debe escribirse explícitamente) y haga clic en la marca

Se abrirá una nueva ventana con las palabras "Generar plantilla" y un menú desplegable (ver imagen).

Seleccione

Método Passthrough de solicitud

ingrese la descripción de la imagen aquí

Luego haga clic en guardar

Para acceder a cualquier variable, simplemente use la siguiente sintaxis (esto es Python), por ejemplo, URL:

https://yourURL.execute-api.us-west-2.amazonaws.com/prod/confirmReg?token=12345&uid=5

Puede obtener variables de la siguiente manera:

from __future__ import print_function

import boto3
import json

print('Loading function')


def lambda_handler(event, context):
    print(event['params']['querystring']['token'])
    print(event['params']['querystring']['uid'])

Por lo tanto, no es necesario nombrar o asignar explícitamente cada variable que desee.

Dirk Conrad Coetsee
fuente
¡excelente! ¡la funcionalidad está ahí mismo en el servicio pero se la había perdido!
hnvasa
25

Para pasar parámetros a su función lambda, debe crear una asignación entre la solicitud de API Gateway y su función lambda. La asignación se realiza en la sección Integration Request-> Mapping templatesdel recurso API Gateway seleccionado.

Cree una asignación de tipo application/json, luego a la derecha editará (haga clic en el lápiz) la plantilla.

Una plantilla de mapeo es en realidad una plantilla de Velocity donde puedes usar ifs, loops y, por supuesto, imprimir variables en ella. La plantilla tiene estas variables inyectadas donde puede acceder a los parámetros de cadena de consulta, encabezados de solicitud, etc. individualmente. Con el siguiente código, puede volver a crear toda la cadena de consulta:

{
    "querystring" : "#foreach($key in $input.params().querystring.keySet())#if($foreach.index > 0)&#end$util.urlEncode($key)=$util.urlEncode($input.params().querystring.get($key))#end",
    "body" : $input.json('$')
}

Nota: haga clic en el símbolo de verificación para guardar la plantilla. Puede probar sus cambios con el botón "prueba" en su recurso. Pero para probar los parámetros de la cadena de consulta en la consola de AWS, deberá definir los nombres de los parámetros en la Method Requestsección de su recurso.

Nota: consulte la Guía del usuario de Velocity para obtener más información sobre el lenguaje de plantillas Velocity.

Luego, en su plantilla lambda, puede hacer lo siguiente para analizar la cadena de consulta:

var query = require('querystring').parse(event.querystring)
// access parameters with query['foo'] or query.foo
gimenete
fuente
99
Esta es la mejor solución. Por favor recuerde hacerlo Actions>Deploy APIentonces (perdí mi tiempo olvidando esto ...). El lambda arn asociado tomará el cambio inmediatamente después de la implementación. Puedes consultarlo Stages > #stage (like: prod) > Deployment History.
loretoparisi
24

La respuesta aceptada funcionó bien para mí, pero al ampliar la respuesta de gimenete, quería una plantilla genérica que pudiera usar para pasar por todos los parámetros de consulta / ruta / encabezado (solo como cadenas por ahora), y encontré la siguiente plantilla. Lo estoy publicando aquí en caso de que alguien lo encuentre útil:

#set($keys = [])
#foreach($key in $input.params().querystring.keySet())
  #set($success = $keys.add($key))
#end

#foreach($key in $input.params().headers.keySet())
  #if(!$keys.contains($key))
    #set($success = $keys.add($key))
  #end
#end

#foreach($key in $input.params().path.keySet())
  #if(!$keys.contains($key))
    #set($success = $keys.add($key))
  #end
#end

{
#foreach($key in $keys)
  "$key": "$util.escapeJavaScript($input.params($key))"#if($foreach.hasNext),#end
#end
}
BenV
fuente
1
Fabuloso, quería poder usar la misma función para las solicitudes POST (con cuerpo JSON) y GET con cadenas de consulta. Funciona un sueño. ¡Gracias!
Matt Fletcher el
@benv ¿es esta la plantilla completa?
nxmohamad
17

Como parte de tratar de responder una de mis propias preguntas aquí , me encontré con este truco.

En la plantilla de mapeo de API Gateway, use lo siguiente para darle la cadena de consulta completa tal como la envió el cliente HTTP:

{
    "querystring": "$input.params().querystring"
}

La ventaja es que no tiene que limitarse a un conjunto de claves asignadas predefinidas en su cadena de consulta. Ahora puede aceptar cualquier par clave-valor en la cadena de consulta, si así es como desea manejar.

Nota: De acuerdo con esto , solo $input.params(x)aparece como una variable disponible para la plantilla VTL. Es posible que las partes internas cambien y querystringya no estén disponibles.

usuario3526
fuente
1
Esto todavía funciona a partir de mayo de 2017, pero devuelve el objeto JS que API Gateway crea para usted en lugar de la cadena de consulta real. Esto es molesto para mí porque estoy tratando de analizar la cadena de consulta para convertir los parámetros repetidos en una matriz.
Tom Saleeba
11

Ahora debería poder usar el nuevo tipo de integración de proxy para Lambda para obtener automáticamente la solicitud completa en forma estándar, en lugar de configurar asignaciones.

ver: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-set-up-lambda-proxy-integration-on- recurso proxy

jackko
fuente
1
No estoy seguro de por qué, pero la integración de proxy generalmente no funciona para mí. Tuve que eliminarlo de las últimas API que he creado.
Gustavo Straube
mismo ^ además, he tenido problemas CORS con API Gateway. Siguiendo con los documentos de AWS, no pude hacer que CORS funcionara. Sin embargo, encontré un viejo artículo de Medium a mediados de finales de 2015 que tenía una forma manual de configurar CORS y funcionó.
Stephen Tetreault el
7

GET / user? Name = bob

{
    "name": "$input.params().querystring.get('name')"
}

OBTENER / usuario / bob

{
    "name": "$input.params('name')"
}
Dmitry Grinko
fuente
5

Muchas de las respuestas aquí son geniales. Pero quería algo un poco más simple. Quería algo que funcione con la muestra "Hello World" de forma gratuita. Esto significa que quería que un simple produzca un cuerpo de solicitud que coincida con la cadena de consulta:

{
#foreach($param in $input.params().querystring.keySet())
  "$param": "$util.escapeJavaScript($input.params().querystring.get($param))" #if($foreach.hasNext),#end
#end
}

Creo que la respuesta principal produce algo más útil cuando se construye algo real, pero para que se ejecute un mundo de saludo rápido usando la plantilla de AWS, esto funciona muy bien.

KrisTC
fuente
4

El siguiente ejemplo de asignación de parámetros pasa todos los parámetros, incluidos la ruta, la cadena de consulta y el encabezado, al punto final de integración a través de una carga útil JSON

#set($allParams = $input.params())
{
  "params" : {
    #foreach($type in $allParams.keySet())
    #set($params = $allParams.get($type))
    "$type" : {
      #foreach($paramName in $params.keySet())
      "$paramName" : "$util.escapeJavaScript($params.get($paramName))"
      #if($foreach.hasNext),#end
      #end
    }
    #if($foreach.hasNext),#end
    #end
  }
}

En efecto, esta plantilla de mapeo genera todos los parámetros de solicitud en la carga útil como se describe a continuación:

{
  "parameters" : {
     "path" : {    
       "path_name" : "path_value", 
       ...
     }
     "header" : {  
       "header_name" : "header_value",
       ...
     }
     'querystring" : {
       "querystring_name" : "querystring_value",
       ...
     }
   }
}

Copiado de la Guía del desarrollador de Amazon API Gateway

matsev
fuente
2

La cadena de consulta es fácil de analizar en javascript en lambda

para GET / user? name = bob

 var name = event.params.querystring.name;

Sin embargo, esto no resuelve la pregunta GET user / bob.

Michael Riecken
fuente
its event.queryStringParameters.name
Neo
Tenía que hacerevent.queryStringParameters.name
Anders Kitson
2

Como respuesta de @ Jonathan, después de marcar Usar integración de proxy Lambda en Solicitud de integración , en su código fuente debe implementar el siguiente formato para evitar el error 502 Bad Gateway .

NodoJS 8.10:

exports.handler = async (event, context, callback) => {
  // TODO: You could get path, parameter, headers, body value from this
  const { path, queryStringParameters, headers, body } = event;

  const response = {
    "statusCode": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "body": JSON.stringify({
      path, 
      query: queryStringParameters,
      headers,
      body: JSON.parse(body)
    }),
    "isBase64Encoded": false
  };

  return response;
};

No olvide implementar su recurso en API Gateway antes de volver a ejecutar su API. La respuesta JSON solo devuelve qué conjunto en el cuerpo es correcto. Entonces, podría obtener la ruta, el parámetro, los encabezados y el valor del cuerpo del evento

const {ruta, queryStringParameters, encabezados, cuerpo} = evento;

Long Nguyen
fuente
1

La función Lambda espera una entrada JSON, por lo tanto, es necesario analizar la cadena de consulta. La solución es cambiar la cadena de consulta a JSON utilizando la plantilla de mapeo.
Lo usé para C # .NET Core, por lo que la entrada esperada debería ser un JSON con el parámetro "queryStringParameters".
Siga estos 4 pasos a continuación para lograr eso:

  1. Abra la plantilla de mapeo de su recurso API Gateway y agregue nuevo application/jsoncontent-tyap:

Plantilla de mapeo de API Gateway

  1. Copie la plantilla a continuación, que analiza la cadena de consulta en JSON, y péguela en la plantilla de mapeo:

    {
    "queryStringParameters": {#foreach($key in $input.params().querystring.keySet())#if($foreach.index > 0),#end"$key":"$input.params().querystring.get($key)"#end}
    }
    
  2. En API Gateway, llame a su función Lambda y agregue la siguiente cadena de consulta (por ejemplo): param1=111&param2=222&param3=333

  3. La plantilla de mapeo debe crear la salida JSON a continuación, que es la entrada para su función Lambda.

    {
    "queryStringParameters": {"param3":"333","param1":"111","param2":"222"}
    }
    
  4. Ya terminaste Desde este punto, la lógica de su función Lambda puede usar los parámetros de la cadena de consulta.
    ¡Buena suerte!

Lior Kirshner
fuente
0

Puede usar Lambda como "Integración de proxy Lambda" , refiérase a esto [ https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda. html # api-gateway-proxy-Integration-lambda-function-python] , las opciones disponibles para este lambda son

Para Nodejs Lambda 'event.headers', 'event.pathParameters', 'event.body', 'event.stageVariables' y 'event.requestContext'

Para el evento Python Lambda ['encabezados'] ['nombre de parámetro'] y así sucesivamente

RajDev
fuente
-1

Después de leer varias de estas respuestas, utilicé una combinación de varias en agosto de 2018 para recuperar los parámetros de cadena de consulta a través de lambda para Python 3.6.

Primero, fui a API Gateway -> Mi API -> recursos (a la izquierda) -> Solicitud de integración. Abajo en la parte inferior, seleccione Plantillas de mapeo y luego, para el tipo de contenido, ingrese application/json.

A continuación, seleccione la plantilla Método de transferencia de solicitud que proporciona Amazon y seleccione guardar e implementar su API.

Luego, en lambda event['params']se accede a todos sus parámetros. Para la cadena de consulta:event['params']['querystring']

Jghorton14
fuente