Доступ к объекту HTTP-запроса (заголовки, строка запроса, файлы cookie, тело) в лямбда-выражении с помощью конечной точки http
Я пытаюсь увидеть, как получить доступ к заголовку запроса и значения тела из с в лямбда-код. Если тело запроса имеет формат JSON, оно автоматически кажется проанализированным и доступным в объекте события.
Как я могу получить доступ к полной строке запроса, телу запроса, заголовкам запроса (cookie) для любого типа входящего запроса "Content-Type" внутри Lambda?
Изменения ниже - это информация, которую я собрал, чтобы помочь решить вопрос, который может быть или не быть актуальным. Пожалуйста, игнорируйте их, если хотите.
РЕДАКТИРОВАТЬ:
Я прошел существующие вопросы по SE здесь и здесь. Согласно этой теме, используя $input.json('$')
должен сделать свое дело. Я думаю, что ответы по этим ссылкам выше уже устарели, так как шлюз API по умолчанию, кажется, распознает JSON в запросе и, если да, делает его доступным в event
объект без каких-либо настраиваемых шаблонов сопоставления.
Настройка отображения, как предложено, не работает для меня. Он не содержит информацию заголовка запроса.
Вот скриншоты о том, как это настроено.
Клавиша "заголовки" возвращает пустое значение. С помощью $input.params('$')
или же "$input.params('$')"
ошибки.
РЕДАКТИРОВАТЬ 2
Попытка определения заголовков в запросе метода. Все еще не получая значение User-Agent внутри лямбды.
РЕДАКТИРОВАТЬ 3
Я использовал следующее сопоставление шаблона в шлюзе API
{
"request": $input.json('$'),
"headers": "$input.params()"
}
и приведенный ниже код в лямбде
context.succeed("event.key32:"+JSON.stringify(event, null, 2) );
И ответ, сгенерированный шлюзом API, показывает это
Глядя на значение "заголовки" в ответе, похоже, что шлюз / облачный интерфейс AWS-SDK/API удаляет все заголовки, полученные от клиента HTTP? Вот полный текст из JSON, возвращенный заголовком $input.params().
header={CloudFront-Forwarded-Proto=https, CloudFront-Is-Desktop-Viewer=true, CloudFront-Is-Mobile-Viewer=false, CloudFront-Is-SmartTV-Viewer=false, CloudFront-Is-Tablet-Viewer=false, Content-Type=application/json, Via=1.1 5d53b9570d94ce920abbd471.cloudfront.net (CloudFront), 1.1 95eea7baa7ec95c9a41eca9e3ab7.cloudfront.net (CloudFront), X-Amz-Cf-Id=GBqmObLRy6Iem9bJbVPrrW1K3YoWRDyAaMpv-UkshfCsHAA==, X-Forwarded-For=172.35.96.199, 51.139.183.101, X-Forwarded-Port=443, X-Forwarded-Proto=https}}
У него нет строки User-Agent в заголовке, хотя, как показано на скриншоте выше, он был отправлен клиентом REST. Интересно, что вся строка запроса сделана доступной. Не уверен, что это намеченный способ получить к нему доступ.
4 ответа
Заголовки запроса могут быть доступны с помощью $input.params('header-name')
Удивительно, но заголовок User-Agent недоступен с помощью приведенного выше кода. Вам нужно прыгнуть через следующий обруч, чтобы получить его:
$context.identity.userAgent
Тело запроса / полезная нагрузка должны быть доступны с использованием следующего кода. Больше ссылок здесь, здесь и здесь:
{
"reqbody": "$input.path('$')"
}
Пока не ясно, ожидается ли, что тело запроса будет в JSON. Следует отметить, что запрос рассматривается как UTF-8 согласно этому посту.
Там в настоящее время, кажется, две ошибки:
- Заголовок "User-Agent" отсутствует / удаляется Amazon API.
Когда значения заголовка содержат двойную кавычку ("), лямбда-функция не выполняется. (Я не вижу записи журнала в журналах cloudwatch для таких запросов). Вместо этого тело ответа http содержит следующее:
{ "Type": "User", "message": "Could not parse request body into json." }
Пример запроса, который не работает в Amazon API
Я считаю, что это необходимо исправить, чтобы иметь возможность реализовать механизм ETag для кэширования.
Рекомендации:
Ожидается, что Etag будет заключен в двойные кавычки. Ожидается, что браузер отправит это точное значение обратно через заголовок If-None-Match, и именно здесь Amazon API ломается.
Вы должны получить необходимую информацию в сопоставлении шаблонов и отправить их обратно в вашу функцию Lambda, это один из шаблонов, который я использовал для отправки информации в функцию Lambda:
{
"params" : "$input.params()",
"content-type-value" : "$input.params().header.get('Content-Type')",
"body" : "$input.json('$')",
"request-id": "$context.requestId",
"method": "$context.httpMethod",
"resource": "$context.resourcePath",
"id": "$input.params('id')" //This is a path parameter in my case
}
Вы можете сделать то же самое, или вы можете получить доступ params.path.id
(опять в моем случае). Вот ссылка на документацию.
Ура,
Похоже, если "Content-Type" не отправлено, AWS API Gateway по умолчанию принимает значение "application / json": https://forums.aws.amazon.com/thread.jspa?threadID=215471
Так что просто определите шаблон сопоставления для "application/json".
Я обновил шаблон сопоставления, который использовал в ответе на один из указанных вопросов, чтобы он содержал свойство userAgent.
{
"method": "$context.httpMethod",
"body": $input.json('$'),
"userAgent": "$context.identity.userAgent",
"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
}
}
Подробное описание шаблона доступно здесь: http://kennbrodhagen.net/2015/12/06/how-to-create-a-request-object-for-your-lambda-event-from-api-gateway/