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

348

например, если мы хотим использовать

GET /user?name=bob

или

GET /user/bob

Как бы вы передали оба этих примера в качестве параметра в функцию Lambda?

Я видел кое-что об установке «сопоставленного» в документации, но не могу найти этот параметр в консоли API Gateway.

  • method.request.path.parameter-nameдля параметра пути с именем, parameter-nameопределенным на странице запроса метода.
  • method.request.querystring.parameter-nameдля параметра строки запроса, названного так, parameter-nameкак определено на странице запроса метода.

Я не вижу ни одного из этих вариантов, хотя я определил строку запроса.

MonkeyBonkey
источник

Ответы:

299

С сентября 2017 года вам больше не нужно настраивать сопоставления для доступа к телу запроса.

Все, что вам нужно сделать, это проверить «Использовать интеграцию Lambda Proxy» в разделе «Запрос на интеграцию» в разделе ресурса.

введите описание изображения здесь

После этого вы сможете получить доступ к параметрам запроса, параметрам пути и заголовкам, как

event['pathParameters']['param1']
event["queryStringParameters"]['queryparam1']
event['requestContext']['identity']['userAgent']
event['requestContext']['identity']['sourceIP']
Джонатан
источник
23
Это отличный совет. Но имейте в виду, что включение интеграции Lambda Proxy может привести к ошибке «Malformed Lambda Proxy Response». Вот как это исправить: stackoverflow.com/questions/43708017/…
AaronBaker
6
Есть ли способ сделать это в Java, сохраняя прозрачную десериализацию, которую RequestHandlerобеспечивает реализация ?
обувь
2
где эта настройка?
red888
2
@MattWestlake Вы создаете ресурс с именем пользователя и под ним ресурс с именем {имя} в API Gateway.
Джонатан
3
Я просто хочу упомянуть, что после этого изменения мне также пришлось перейти на Amazon API Gateway -> Actions -> Deploy API и повторно развернуть его в реальной среде.
victorvartan
221

Шаги, чтобы заставить это работать:

В консоли API Gateway ...

  1. перейти к Resources -> Integration Request
  2. щелкните значок «плюс» или «Изменить» рядом с раскрывающимся списком шаблонов (странно, я знаю, так как поле шаблона уже открыто, а кнопка здесь выглядит серой)
  3. Явно введите application/jsonполе типа контента, даже если оно показывает значение по умолчанию (если вы не сделаете этого, оно не сохранится и не выдаст сообщение об ошибке)
  4. положить это в отображении ввода { "name": "$input.params('name')" }

  5. установите флажок рядом с раскрывающимся списком шаблонов (я полагаю, что это, наконец, сохраняет его)

MonkeyBonkey
источник
9
Вы когда-нибудь получали это для отправки через параметры URL в URL, таких как / user / bob, где маршрут был / user / {username}? Я попробовал все виды перестановок, но не смог решить это.
Лукас
5
Кто-нибудь знает, есть ли официальная документация? было бы неплохо просто пройти через все параметры запроса или обработать необязательные значения более изящно, чем пустые строки
AxelTheGerman
6
Один совет для разработчиков iOS: API Gateway не будет передавать данные запроса, пока вы не определите каждую переменную как строку запроса (в разделе «Запрос метода») И не развернете API. До развертывания он работает из консольного теста, но вырезает из запросов приложения.
AlexeyVMP
3
@axel задокументировано здесь: docs.aws.amazon.com/apigateway/latest/developerguide/…
russau
6
Лукас, я заставил его работать, используя шаблон / user / {username}. Просто запомните, если ваш путь к ресурсам GET равен / user / {username}, на шаге 4 отображение ввода выглядит следующим образом: {"name": "$ input.params ('username')"}
Gerard
134

Я использовал этот шаблон сопоставления для предоставления параметров строки, заголовка, метода, пути и URL-запроса в событие Lambda. Я написал сообщение в блоге, объясняющее шаблон более подробно: http://kennbrodhagen.net/2015/12/06/how-to-create-a-request-object-for-your-lambda-event-from-api- шлюз /

Вот шаблон отображения, который вы можете использовать:

{
  "method": "$context.httpMethod",
  "body" : $input.json('$'),
  "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
  }  
}
kennbrodhagen
источник
Удивительный! Я изо всех сил пытался передать вещи своему обработчику. Лучший ответ здесь.
Венкат Д.
Я сделал это, но пока ничего не получаю. Его показ Не определено. Как мы должны отправить параметры в URL? и нужно ли нам указывать имя переменной в URL, как в обычном сценарии GET url? Пожалуйста, помогите мне с этим.
Партхапратим Неог
8
Неважно, я получил результат. Проблема была в том, что я добавил отображение и просто сохранил его, а deployAPI снова не сделал . Как только я развернул API с новым отображением, все заработало. Благодаря тонну.
Партхапратим Неог
@ shashu10 Посмотри мой ответ
мацев
1
Я не могу начать рассказывать, насколько полезен твой блог. Сначала я нашел пост «eturn-html-from-aws-api-gateway» и последовал за ним, потому что это именно то, что мне было нужно. Теперь мне нужно передать некоторые параметры в функцию и изменить HTML на основе этого - и снова вы единственный, у кого есть настоящее руководство! Все остальные гиды, которые я нашел, похоже, упускают суть.
user3685427
41

В наши дни раскрывающийся шаблон включен в консоль API Gateway на AWS.

Для вашего API, нажмите на название ресурса ... затем GET

Разверните "Шаблоны картографии тела"

Введите

Применение / JSON

для Content-Type (должен быть явно напечатан) и нажмите галочку

Откроется новое окно со словами «Создать шаблон» и раскрывающийся список (см. Изображение).

Выбрать

Метод запроса прохождения

введите описание изображения здесь

Затем нажмите Сохранить

Чтобы получить доступ к любым переменным, просто используйте следующий синтаксис (это Python), например, URL:

https://yourURL.execute-api.us-west-2.amazonaws.com/prod/confirmReg?token=12345&uid=5

Вы можете получить переменные следующим образом:

from __future__ import print_function

import boto3
import json

print('Loading function')


def lambda_handler(event, context):
    print(event['params']['querystring']['token'])
    print(event['params']['querystring']['uid'])

Таким образом, нет необходимости явно называть или отображать каждую переменную, которую вы хотите.

Дирк Конрад Коэтзее
источник
превосходно! функциональность прямо там в сервисе, но пропустил это!
hnvasa
25

Чтобы передать параметры в вашу лямбда-функцию, вам необходимо создать отображение между запросом API-шлюза и вашей лямбда-функцией. Сопоставление выполняется в разделе Integration Request-> Mapping templatesвыбранного ресурса шлюза API.

Создайте отображение типа application/json, затем справа вы отредактируете (щелкните карандашом) шаблон.

Шаблон отображения на самом деле является шаблоном Velocity, где вы можете использовать ifs, циклы и, конечно, печатать переменные на нем. В шаблон вводятся эти переменные, где вы можете получить доступ к параметрам строки запроса, заголовкам запроса и т. Д. По отдельности. С помощью следующего кода вы можете заново создать всю строку запроса:

{
    "querystring" : "#foreach($key in $input.params().querystring.keySet())#if($foreach.index > 0)&#end$util.urlEncode($key)=$util.urlEncode($input.params().querystring.get($key))#end",
    "body" : $input.json('$')
}

Примечание: нажмите на значок галочки, чтобы сохранить шаблон. Вы можете проверить свои изменения с помощью кнопки «Тест» на вашем ресурсе. Но чтобы протестировать параметры строки запроса в консоли AWS, вам нужно определить имена параметров в Method Requestразделе вашего ресурса.

Примечание: обратитесь к Руководству пользователя Velocity для получения дополнительной информации о языке шаблонов Velocity.

Затем в своем лямбда-шаблоне вы можете сделать следующее, чтобы проанализировать строку запроса:

var query = require('querystring').parse(event.querystring)
// access parameters with query['foo'] or query.foo
gimenete
источник
9
Это лучшее решение. Пожалуйста, не забудьте сделать это Actions>Deploy API(я потерял время, забывая об этом ...). Связанный лямбда-арн примет изменение сразу после развертывания. Вы можете проверить это Stages > #stage (like: prod) > Deployment History.
Лоретопариси
24

Принятый ответ работал хорошо для меня, но, расширив ответ Джименете, я хотел универсальный шаблон, который мог бы использовать для прохождения всех параметров запроса / пути / заголовка (так же, как строки на данный момент), и я пришел к следующему шаблону. Я публикую это здесь на случай, если кто-то посчитает это полезным:

#set($keys = [])
#foreach($key in $input.params().querystring.keySet())
  #set($success = $keys.add($key))
#end

#foreach($key in $input.params().headers.keySet())
  #if(!$keys.contains($key))
    #set($success = $keys.add($key))
  #end
#end

#foreach($key in $input.params().path.keySet())
  #if(!$keys.contains($key))
    #set($success = $keys.add($key))
  #end
#end

{
#foreach($key in $keys)
  "$key": "$util.escapeJavaScript($input.params($key))"#if($foreach.hasNext),#end
#end
}
BENV
источник
1
Потрясающе, я хотел иметь возможность использовать одну и ту же функцию как для запросов POST (с телом JSON), так и для GET со строками запросов. Работает мечта. Спасибо!
Мэтт Флетчер
@benv это полный шаблон?
nxmohamad
17

Как часть попытки ответить на один из моих собственных вопросов здесь , я столкнулся с этой уловкой.

В шаблоне сопоставления шлюза API используйте следующую команду, чтобы получить полную строку запроса, отправленную клиентом HTTP:

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

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

Примечание: В соответствии с этим , только $input.params(x)перечислен как переменная доступна для шаблона VTL. Возможно, что внутреннее устройство может измениться и querystringможет больше не быть доступным.

user3526
источник
1
Это все еще работает с мая 2017 года, но возвращает объект JS, который API-шлюз создает для вас, а не фактическую строку запроса. Это раздражает меня, потому что я пытаюсь разобрать строку запроса, чтобы превратить повторяющиеся параметры в массив.
Том Салеба,
11

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

см .: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-set-up-lambda-proxy-integration-on- прокси-ресурс

jackko
источник
1
Я не уверен почему, но интеграция с прокси обычно не работает для меня. Мне пришлось удалить его из последних API, которые я создал.
Густаво Штраубе
то же самое, кроме того, у меня были проблемы с CORS с API Gateway. Следуя документам AWS, я не смог заставить работать CORS. Однако я нашел старую статью Medium середины конца 2015 года, в которой был ручной способ настройки CORS, и это сработало.
Стивен Тетро
7

GET / user? Name = bob

{
    "name": "$input.params().querystring.get('name')"
}

GET / пользователь / bob

{
    "name": "$input.params('name')"
}
Дмитрий Гринько
источник
5

Здесь очень много ответов. Но я хотел что-то немного проще. Я хотел что-то, что будет работать с образцом "Hello World" бесплатно. Это означает, что я хотел, чтобы простое производило тело запроса, которое соответствует строке запроса:

{
#foreach($param in $input.params().querystring.keySet())
  "$param": "$util.escapeJavaScript($input.params().querystring.get($param))" #if($foreach.hasNext),#end
#end
}

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

KrisTC
источник
4

В следующем примере сопоставления параметров все параметры, включая путь, строку запроса и заголовок, передаются в конечную точку интеграции через полезную нагрузку JSON.

#set($allParams = $input.params())
{
  "params" : {
    #foreach($type in $allParams.keySet())
    #set($params = $allParams.get($type))
    "$type" : {
      #foreach($paramName in $params.keySet())
      "$paramName" : "$util.escapeJavaScript($params.get($paramName))"
      #if($foreach.hasNext),#end
      #end
    }
    #if($foreach.hasNext),#end
    #end
  }
}

По сути, этот шаблон отображения выводит все параметры запроса в полезной нагрузке, как указано ниже:

{
  "parameters" : {
     "path" : {    
       "path_name" : "path_value", 
       ...
     }
     "header" : {  
       "header_name" : "header_value",
       ...
     }
     'querystring" : {
       "querystring_name" : "querystring_value",
       ...
     }
   }
}

Скопировано из Руководства разработчика по API Amazon Gateway

matsev
источник
2

Строка запроса проста для разбора в javascript в lambda

для GET / пользователя? name = bob

 var name = event.params.querystring.name;

Это не решает вопрос GET user / bob.

Майкл Риккен
источник
его event.queryStringParameters.name
Neo
Я должен был сделатьevent.queryStringParameters.name
Андерс Китсон
2

Как ответ @ Jonathan, после отметки « Использовать интеграцию Lambda Proxy в запросе на интеграцию» в исходном коде необходимо реализовать следующий формат, чтобы пропустить ошибку 502 Bad Gateway .

NodeJS 8.10:

exports.handler = async (event, context, callback) => {
  // TODO: You could get path, parameter, headers, body value from this
  const { path, queryStringParameters, headers, body } = event;

  const response = {
    "statusCode": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "body": JSON.stringify({
      path, 
      query: queryStringParameters,
      headers,
      body: JSON.parse(body)
    }),
    "isBase64Encoded": false
  };

  return response;
};

Не забудьте развернуть свой ресурс в API Gateway, прежде чем перезапускать свой API. Ответ JSON просто вернет, какой набор в теле корректен. Таким образом, вы можете получить путь, параметр, заголовки, значение тела из события

const {path, queryStringParameters, headers, body} = событие;

Лонг Нгуен
источник
1

Функция Lambda ожидает ввод данных в формате JSON, поэтому необходимо выполнить синтаксический анализ строки запроса. Решение состоит в том, чтобы изменить строку запроса на JSON с помощью шаблона отображения.
Я использовал его для C # .NET Core, поэтому ожидаемым вводом должен быть JSON с параметром «queryStringParameters».
Для этого выполните следующие 4 шага:

  1. Откройте шаблон сопоставления вашего ресурса API Gateway и добавьте новый application/jsonконтент-tyap:

Шаблон сопоставления шлюза API

  1. Скопируйте шаблон ниже, который анализирует строку запроса в JSON, и вставьте ее в шаблон отображения:

    {
    "queryStringParameters": {#foreach($key in $input.params().querystring.keySet())#if($foreach.index > 0),#end"$key":"$input.params().querystring.get($key)"#end}
    }
    
  2. В API Gateway вызовите функцию Lambda и добавьте следующую строку запроса (для примера): param1=111&param2=222&param3=333

  3. Шаблон отображения должен создать вывод JSON ниже, который является вводом для вашей лямбда-функции.

    {
    "queryStringParameters": {"param3":"333","param1":"111","param2":"222"}
    }
    
  4. Вы сделали С этого момента логика вашей лямбда-функции может использовать параметры строки запроса.
    Удачи!

Лиор Киршнер
источник
0

Вы можете использовать Lambda в качестве «Lambda Proxy Integration» , см. Этот [ https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda. html # api-gateway-proxy -gration -lambda-function-python] , варианты, доступные для этой лямбды:

Для Nodejs Lambda «event.headers», «event.pathParameters», «event.body», «event.stageVariables» и «event.requestContext»

Для события Python Lambda ['headers'] ['имя_параметра'] и т. Д.

RajDev
источник
-1

Прочитав несколько из этих ответов, я использовал комбинацию из нескольких в августе 2018 года для получения параметров строки запроса через лямбду для python 3.6.

Сначала я зашёл в API Gateway -> Мой API -> ресурсы (слева) -> Запрос на интеграцию. Внизу внизу выберите Mapping Templates, а затем введите тип контента application/json.

Затем выберите шаблон «Метод запроса», который предоставляет Amazon, и выберите «Сохранить и развернуть API».

Тогда лямбда event['params']- это то, как вы получаете доступ ко всем вашим параметрам. Для строки запроса:event['params']['querystring']

Jghorton14
источник