Доступ к объекту 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 согласно этому посту.


Там в настоящее время, кажется, две ошибки:

  1. Заголовок "User-Agent" отсутствует / удаляется Amazon API.
  2. Когда значения заголовка содержат двойную кавычку ("), лямбда-функция не выполняется. (Я не вижу записи журнала в журналах cloudwatch для таких запросов). Вместо этого тело ответа http содержит следующее:

    {
       "Type": "User",
       "message": "Could not parse request body into json."
    }
    

Пример запроса, который не работает в Amazon API

Я считаю, что это необходимо исправить, чтобы иметь возможность реализовать механизм ETag для кэширования.

Рекомендации:

Ожидается, что Etag будет заключен в двойные кавычки. Ожидается, что браузер отправит это точное значение обратно через заголовок If-None-Match, и именно здесь Amazon API ломается.

Синтаксис для ETag?

HTTP: максимальная длина etag

http://gsnedders.com/http-entity-tags-confusion

Вы должны получить необходимую информацию в сопоставлении шаблонов и отправить их обратно в вашу функцию 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/

Другие вопросы по тегам