it-swarm.com.ru

Как передать параметры из POST в AWS Lambda из Amazon API Gateway

В этом вопросе Как передать строку запроса или параметр маршрута в AWS Lambda из Amazon API Gateway

показано, как сопоставить параметры строки запроса с AWS-лямбдой с помощью API-шлюза. Я хотел бы сделать то же самое, но отображать значения POST вместо строки запроса. Я старался:

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

но не работает, я не вижу фактических данных формы. Кстати, я публикую с помощью: 

application/x-www-form-urlencoded

Я получаю ответ от своей лямбда-функции, поэтому я знаю, что она нормально запускает лямбда-функцию, но моя проблема в том, что я нигде не вижу параметров POST. Я не могу понять, как их отобразить. Я сбрасываю все, что попадаю на лямбда-сторону, и вот оно:

 {"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}}"}
34
ecorvo

Хороший ответ от r7kamura. Дополнительно Вот пример понятного и надежного шаблона отображения для application/x-www-form-urlencoded, который работает для всех случаев (при условии 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
    }
}

Это преобразовало бы вход

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

в

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

Лямбда-обработчик может использовать его следующим образом (этот возвращает все входные данные):

module.exports.handler = function(event, context, cb) {
  return cb(null, {
    data: event.data
  });
};
54
Marcus Whybrow

Вы можете преобразовать любые данные тела запроса в допустимый формат JSON, настроив шаблоны сопоставления в настройках интеграции, чтобы AWS Lambda могла их получить.

В настоящее время кажется, что Amazon API Gateway официально не поддерживает application/x-www-form-urlencoded, но avilewin опубликовал решение для этого на форумах AWS. В шаблонах сопоставления вы можете использовать Velocity Template Language (VTL) , поэтому вам нужно настроить шаблоны сопоставления, которые преобразуют формат application/x-www-form-urlencoded в допустимый формат JSON. Конечно, это грязное решение, но я думаю, что пока это единственный способ сделать это.

20
r7kamura

Если вы включите Lambda Proxy Integration  enter image description here

Тело POST будет доступно из:

event['body']['param']

GET параметры и заголовки также будут доступны через

event['pathParameters']['param1']
event["queryStringParameters"]['queryparam1']
event['requestContext']['identity']['userAgent']
event['requestContext']['identity']['sourceIP']
12
Jonathan

Вы можете преобразовать параметры в JSON с помощью шаблона шлюза API: https://forums.aws.Amazon.com/thread.jspa?messageID=673012&tstart=0#673012

Или вы можете сделать это в самой лямбда-функции, используя QueryString parser pacakge: https://www.npmjs.com/package/qs

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

Если Amazon добавит встроенную поддержку для такой функции, я буду ее использовать, но до тех пор я лично предпочитаю второй способ, потому что он чище и легче отлаживается, если что-то пойдет не так.

Обновление июль 2017 года:

Вы можете использовать прокси-интеграцию, которая поддерживает ее по умолчанию: http://docs.aws.Amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for- lambda.html

11
advncd

Расширяя @ markus-whybrow ответ:

{
        #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": "$util.escapeJavaScript($val)"#if($foreach.hasNext),#end
            #end
        #end
    }

Это избавляет от «данных», а также исправляет случай, если у вас есть двойная кавычка в одном из ваших значений.

3
Mark Sergienko

Я реализовал API с запросами POST, где Content-Type был application/x-www-form-urlencoded. Если вы просто заинтересованы в получении длинной строки значений, аналогичных GET-запросам, используйте этот синтаксис сопоставления.

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

Обратите внимание, вы можете добавить и другие сопоставления ... Я оставил это для решения исходной проблемы.

Вот учебник блога, который я использовал при первоначальной реализации моего API. Моя лямбда-функция затем анализирует строку запроса и передает данные другим процессам. 

2
openwonk

Я нашел действительно простое решение, которым, я думаю, стоит поделиться, поскольку мне понадобилось несколько времени, чтобы найти этот минимально работающий код.

Если у вас есть общая форма, которая отправляет данные с типом контента application/x-www-form-urlencoded, просто отметьте «Интеграция с прокси-сервером Lambda», тогда вы найдете данные закодированной формы в файле event.body, который можно проанализировать с помощью Node.js. собственный модуль строки запроса.

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
Gianluca Casati

Простая функция, которая возвращает упорядоченный словарь опубликованных значений:

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 [email protected][email protected]#41'
print(postdata['anotherkey'])
#returns 'isawesome23412 [email protected][email protected]'

Чтобы избежать ошибки ключа, если опубликованные элементы отсутствуют, Вместо этого следует использовать значение = postdata.get (''), так как значение будет Нет, если ключа нет.

0
Arvin Amir

Это работает с лямбда-интеграцией . Предполагается, что тело вашего POST запроса, например, 

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

Вы можете получить к нему доступ так: 

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

Более подробная информация здесь: http://docs.aws.Amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html

0
Dodi