Cómo pasar un params de POST a AWS Lambda desde Amazon API Gateway


En esta pregunta Cómo pasar un parámetro querystring o route a AWS Lambda desde Amazon API Gateway

Muestra cómo asignar parámetros de cadena de consulta a AWS lambda mediante API gateway. Me gustaría hacer lo mismo pero mapeando valores POST en lugar de query-string. Lo intenté:

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

Pero no funcionó, no veo los datos reales del formulario. Por cierto estoy publicando usando:

application/x-www-form-urlencoded

Obtengo mi respuesta de mi función lambda, así que sé que está invocando lambda fine, pero mi el problema es que no veo los POST params en ninguna parte. No puedo averiguar cómo mapearlos. Me deshago de todo lo que consigo en el lado Lambda y aquí está:

 {"values":"{path={}, querystring={}, header={Accept=*/*, Accept-Encoding=gzip, deflate, Accept-Language=en-US,en;q=0.8, Cache-Control=no-cache, CloudFront-Forwarded-Proto=https, CloudFront-Is-Desktop-Viewer=true, CloudFront-Is-Mobile-Viewer=false, CloudFront-Is-SmartTV-Viewer=false, CloudFront-Is-Tablet-Viewer=false, CloudFront-Viewer-Country=US, Content-Type=application/x-www-form-urlencoded, Origin=chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop, Postman-Token=7ba28698-8753-fcb1-1f48-66750ce12ade, Via=1.1 6ba5553fa41dafcdc0e74d152f3a7a75.cloudfront.net (CloudFront), X-Amz-Cf-Id=sc8C7dLcW0BHYopztNYrnddC0hXyFdBzHv0O9aWU1gKhd1D_J2HF3w==, X-Forwarded-For=50.196.93.57, 54.239.140.62, X-Forwarded-Port=443, X-Forwarded-Proto=https}}"}
Author: Community, 2015-08-17

8 answers

Buena respuesta de r7kamura. Además, aquí hay un ejemplo de una plantilla de mapeo comprensible y robusta para application/x-www-form-urlencoded que funciona para todos los casos (suponiendo POST):

{
    "data": {
        #foreach( $token in $input.path('$').split('&') )
            #set( $keyVal = $token.split('=') )
            #set( $keyValSize = $keyVal.size() )
            #if( $keyValSize >= 1 )
                #set( $key = $util.urlDecode($keyVal[0]) )
                #if( $keyValSize >= 2 )
                    #set( $val = $util.urlDecode($keyVal[1]) )
                #else
                    #set( $val = '' )
                #end
                "$key": "$val"#if($foreach.hasNext),#end
            #end
        #end
    }
}

Transformaría una entrada de

name=Marcus&email=email%40example.com&message=

Hacia

{
    "data": {
                "name": "Marcus",
                "email": "[email protected]",
                "message": ""
    }
}

Un manejador Lambda podría usarlo así (este devuelve todos los datos de entrada):

module.exports.handler = function(event, context, cb) {
  return cb(null, {
    data: event.data
  });
};
 42
Author: Marcus Whybrow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-21 23:51:22

Puede convertir los datos del cuerpo de la solicitud en un formato JSON válido configurando las plantillas de asignación en la configuración de integración para que AWS Lambda pueda recibirlos.

Actualmente parece que Amazon API Gateway aún no admite application/x-www-form-urlencoded oficialmente, pero avilewin publicó una solución para hacerlo en los foros de AWS. En las plantillas de asignación puede usar Velocity Template Language (VTL), por lo que lo que debe hacer es configurar las plantillas de asignación que convierta el formato application / x-www-form-urlencoded en un formato JSON válido. Por supuesto que esta es una solución sucia, pero creo que es la única manera de hacerlo por ahora.

 20
Author: r7kamura,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-24 10:15:36

Puede convertir los parámetros en JSON con una plantilla de puerta de enlace de API: https://forums.aws.amazon.com/thread.jspa?messageID=673012&tstart=0#673012

O puede hacer esto en la propia función lambda usando QueryString parser pacakge: https://www.npmjs.com/package/qs

var qs = require('qs');
var obj = qs.parse('a=c');  // { a: 'c' } 

Si Amazon agrega soporte incorporado para dicha característica, lo usaré, pero hasta entonces personalmente prefiero la segunda forma porque es más limpio y más fácil de depurar si algo falla Equivocada.

Actualización de Julio 2017:

Puede utilizar la integración proxy que lo soporta de forma predeterminada: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html

 10
Author: advncd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-02 01:30:25

Si habilita la integración del proxy Lambda introduzca la descripción de la imagen aquí

El cuerpo del MENSAJE estará disponible en:

event['body']['param']

OBTENER parámetros y encabezados también estarán disponibles a través de

event['pathParameters']['param1']
event["queryStringParameters"]['queryparam1']
event['requestContext']['identity']['userAgent']
event['requestContext']['identity']['sourceIP']
 8
Author: Jonathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-05 16:29:30

Implementé una API con POST requests donde Content-Type era application/x-www-form-urlencoded. Si solo está interesado en obtener una cadena de consultas larga de valores similares a las solicitudes GET, utilice esta sintaxis de asignación.

{
    "body": "$input.body"
}

Tenga en cuenta que también puede agregar otras asignaciones... Lo dejé fuera para abordar el problema original.

Aquí hay un tutorial de blog que utilicé cuando implementé originalmente mi API. Mi función lambda entonces analiza el querystring pasa los datos a otros procesos.

 1
Author: openwonk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-21 03:37:04

Encontré una solución muy simple que creo que vale la pena compartir, ya que me llevó un poco de tiempo encontrar este código de trabajo mínimo.

Si tiene un formulario común, que envíe datos con el tipo de contenido application/x-www-form-urlencoded, simplemente marque "Lambda proxy integration", entonces encontrará datos de formulario codificados en event.cuerpo que puede ser analizado con Node.módulo nativo js querystring.

const querystring = require('querystring')

function handler (event, context, callback) {
  // Read form data.
  const { user, pass } = querystring.parse(event.body)

  // Follows your code to handle request.
}
 1
Author: Gianluca Casati,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-26 21:34:50

Esto funciona con la integración lambda. Suponiendo que el cuerpo de su solicitud POST es, por ejemplo,

{
   "name" : "Hello",
   "address" : "Cool place" 
}

Puedes acceder así:

if (event.body !== null && event.body !== undefined) {
   let body = JSON.parse(event.body)
   let name = body.name;
   let address = body.address;
}

Más información aquí : http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html

 0
Author: Dodi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-02 17:37:56

Función simple que devuelve el diccionario ordenado de los valores publicados:

import urllib
from collections import OrderedDict
postdata = ''

def GetPostData(body):
    #postdata = OrderedDict()
    postdata = {}
    for items in body.split('&'):
        vals = items.split('=')
        postdata[vals[0]] = urllib.parse.unquote(vals[1])
    return postdata

#Testing it out:
#Assume you get body from event['body'] or body = event.get['body']
body = 'text=This%20works%20really%20well%21%245123%21%403%2146t5%40%2341&anotherkey=isawesome23412%201%21%403%21%40312'

postdata = GetPostData(body)
print(postdata['text'])
#returns 'This works really well!$5123!@3!46t5@#41'
print(postdata['anotherkey'])
#returns 'isawesome23412 1!@3!@312'

Para evitar un error de clave cuando faltan elementos publicados, debe usar value = postdata.get ( " ) en su lugar, como valor será None si la clave no está presente.

 0
Author: Arvin Amir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-18 23:37:10