Доступ к HTTP-запросу (заголовки, строка запроса, куки, тело) в лямбда с конечной точкой http
Я пытаюсь увидеть, как получить доступ к заголовкам запроса и значениям тела из с помощью лямбда-кода. Если тело запроса находится в формате JSON, оно автоматически, по-видимому, анализируется и становится доступным в объекте события.
Как я могу получить доступ к полной строке запроса, телу запроса, заголовкам запроса (куки) для любого типа входящего запроса "Content-Type" внутри Lambda?
Ниже перечислены данные, которые я собрал, чтобы помочь решить вопрос, который может быть или не быть релевантным. Пожалуйста, проигнорируйте их, если хотите.
EDIT:
Я рассмотрел существующие вопросы по SE здесь и здесь.
В соответствии с этим thread использование $input.json('$')
должно сделать трюк. Я полагаю, что ответы на эти выше ссылки уже устарели, поскольку шлюз API по умолчанию, по-видимому, распознает JSON в запросе, и если это делает его доступным в объекте event
без настройки шаблонов сопоставления.
Настройка отображения, как было предложено, не работает для меня. Он не содержит информацию заголовка запроса.
Вот скриншоты о том, как он настроен.
![введите описание изображения здесь]()
![введите описание изображения здесь]()
Ключ "заголовки" возвращает пустое значение. Использование ошибок $input.params('$')
или "$input.params('$')"
.
ИЗМЕНИТЬ 2
Пробовал определять заголовки в запросе метода. Все еще не получает значение User-Agent внутри lambda.
![введите описание изображения здесь]()
ИЗМЕНИТЬ 3
Я использовал следующее сопоставление шаблонов в шлюзе API
{
"request": $input.json('$'),
"headers": "$input.params()"
}
и ниже код в lambda
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.
Интересно, что вся строка запроса доступна. Не уверен, что это предназначен для доступа к нему.
Ответы
Ответ 1
Доступ к заголовкам запросов можно получить с помощью $input.params('header-name')
Удивительно, что к заголовку User-Agent не удается получить доступ с помощью вышеуказанного кода. Вам нужно перепрыгнуть через следующее обруч, чтобы получить его:
$context.identity.userAgent
Тело запроса/полезная нагрузка должны быть доступны с использованием следующего кода. Больше ссылок здесь, здесь и здесь:
{
"reqbody": "$input.path('$')"
}
Пока неясно, будет ли тело запроса находиться в JSON. Следует отметить, что запрос обрабатывается как UTF-8 в соответствии с этот пост.
В настоящее время существует два ошибки:
- Заголовок "User-Agent" отсутствует/удаляется API-интерфейсом Amazon.
-
Когда значения заголовка содержат двойную кавычку ("), функция лямбда не выполняется. (я не вижу записи журнала в журналах облачного просмотра для таких запросов)., тело ответа http содержит следующее:
{
"Type": "User",
"message": "Could not parse request body into json."
}
Пример запроса, который не работает в API Amazon
![введите описание изображения здесь]()
Я считаю, что это должно быть исправлено, чтобы иметь возможность реализовать механизм ETag для кэширования.
Литература:
Предполагается, что Etag будет заключен в двойные кавычки. Ожидается, что браузер отправит это точное значение через заголовок If-None-Match, и здесь разрывается API Amazon.
Синтаксис для ETag?
HTTP: максимальная длина etag
http://gsnedders.com/http-entity-tags-confusion
Ответ 2
Кажется, что если "Content-Type" не отправлен, AWS API Gateway по умолчанию использует его "application/json":
https://forums.aws.amazon.com/thread.jspa?threadID=215471
Итак, просто определите шаблон сопоставления для "application/json".
Ответ 3
Вы должны получить необходимую информацию в сопоставлении шаблонов и отправить их обратно своей функции 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
(опять же в моем случае). Вот ссылка в документацию.
Приветствия,
Ответ 4
Я обновил шаблон сопоставления, который я использовал в ответе на один из ссылочных вопросов, чтобы содержать свойство 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/