Jak przekazać kwerendę lub parametr trasy do AWS Lambda z Amazon API Gateway


348

na przykład, jeśli chcemy użyć

GET /user?name=bob

lub

GET /user/bob

Jak przekazałbyś oba te przykłady jako parametr do funkcji Lambda?

Widziałem coś o ustawianiu „mapowanego z” w dokumentacji, ale nie mogę znaleźć tego ustawienia w konsoli API Gateway.

  • method.request.path.parameter-namedla parametru ścieżki o nazwie parameter-namezdefiniowanej na stronie Żądanie metody.
  • method.request.querystring.parameter-namedla parametru ciągu zapytania o nazwie parameter-namezdefiniowanej na stronie Żądanie metody.

Nie widzę żadnej z tych opcji, mimo że zdefiniowałem ciąg zapytania.

Odpowiedzi:


299

Od września 2017 r. Nie trzeba już konfigurować odwzorowań, aby uzyskać dostęp do treści żądania.

Wszystko, co musisz zrobić, to zaznaczyć „Użyj integracji Lambda Proxy” w części Żądanie integracji w zasobie.

enter image description here

Będziesz wtedy mieć dostęp do parametrów zapytania, parametrów ścieżki i podobnych nagłówków

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

23
To świetna wskazówka. Pamiętaj jednak, że włączenie integracji Lambda Proxy może spowodować błąd „Źle sformułowana odpowiedź Lambda Proxy”. Oto jak to naprawić: stackoverflow.com/questions/43708017/…
AaronBaker

6
czy istnieje sposób na zrobienie tego w java przy jednoczesnym zachowaniu przejrzystej deserializacji RequestHandlerzapewnianej przez implementację ?
but

2
gdzie jest to ustawienie?
red888

2
@MattWestlake Tworzysz zasób o nazwie user, a pod nim zasób o nazwie {name} w API Gateway.
Jonathan

3
Chcę tylko wspomnieć, że po tej zmianie musiałem także przejść do Amazon API Gateway -> Działania -> Wdróż interfejs API i ponownie wdrożyć w środowisku na żywo.
victorvartan

221

Kroki, aby uruchomić to są:

W konsoli API Gateway Console ...

  1. iść do Resources -> Integration Request
  2. kliknij ikonę plusa lub edytuj obok menu szablonów (dziwne, wiem, ponieważ pole szablonu jest już otwarte, a przycisk tutaj jest wyszarzony)
  3. Jawnie wpisz application/jsonw polu typu zawartości, nawet jeśli pokazuje wartość domyślną (jeśli tego nie zrobisz, nie zostanie zapisany i nie wyświetli się komunikat o błędzie)
  4. umieść to w mapowaniu wejściowym { "name": "$input.params('name')" }

  5. kliknij pole wyboru obok menu rozwijanego szablonów (zakładam, że to ostatecznie je zapisuje)


9
Czy zdarzyło Ci się kiedyś, że przesyłasz to przez parametry URL w adresach URL takich jak / user / bob, gdzie była droga / user / {nazwa użytkownika}? Próbowałem wszystkich rodzajów permutacji, ale nie byłem w stanie tego rozwiązać.
Lucas

5
czy ktoś wie, czy istnieje jakaś oficjalna dokumentacja? miło byłoby po prostu przejść przez wszystkie parametry zapytania lub obsłużyć opcjonalne wartości z większym wdziękiem niż puste ciągi
AxelTheGerman

6
Jedna wskazówka dla programistów iOS: API Gateway nie przekaże danych zapytania, dopóki nie zdefiniujesz każdej zmiennej jako ciągu zapytania (w sekcji „Request Method”) ORAZ nie wdrożysz interfejsu API. Do czasu wdrożenia działa z testu konsoli, ale wycina zapytania aplikacji.
AlexeyVMP,


6
Lucas, mam to do pracy przy użyciu wzorca / user / {nazwa użytkownika}. Pamiętaj tylko, że twoja ścieżka do zasobu GET to / user / {nazwa użytkownika}, w kroku 4 odwzorowanie danych wejściowych wygląda następująco {"name": "$ input.params ('nazwa użytkownika')"}
Gerard

134

Użyłem tego szablonu odwzorowania, aby podać parametry ciągu treści, nagłówków, metody, ścieżki i adresu URL zapytania do zdarzenia Lambda. Napisałem post na blogu wyjaśniający bardziej szczegółowo szablon: http://kennbrodhagen.net/2015/12/06/how-to-create-a-request-object-for-your-lambda-event-from-api- przejście/

Oto szablon odwzorowania, którego możesz użyć:

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

Niesamowity! Walczyłem z przekazywaniem rzeczy ogólnie mojemu przewodnikowi. Najlepsza odpowiedź tutaj.
Venkat D.

Zrobiłem to, ale jeszcze nic nie dostaję. Pokazuje niezdefiniowane. Jak mamy wysłać parametry w adresie URL? i czy musimy podać nazwę zmiennej w adresie URL, tak jak w normalnym scenariuszu GET? Proszę, pomóż mi się z tym uporać.
Parthapratim Neog,

8
Nieważne, mam wynik. Problem polegał na tym, że dodałem mapowanie i właśnie je zapisałem, i nie zrobiłem deployponownie interfejsu API. Gdy wdrożyłem interfejs API z nowym mapowaniem, zadziałało dobrze. Wielkie dzięki.
Parthapratim Neog,

@ shashu10 Zobacz moją odpowiedź
matsev

1
Nie mogę ci powiedzieć, jak użyteczny jest twój blog. Najpierw znalazłem post „eturn-html-from-aws-api-gateway” i podążyłem za nim, ponieważ właśnie tego potrzebowałem. Teraz muszę przekazać kilka parametrów do funkcji i na tej podstawie zmodyfikować HTML - i znowu jesteś jedynym z prawdziwym przewodnikiem! Wszystkie inne przewodniki, które znalazłem, wydają się nie mieć sensu.
user3685427,

41

Obecnie rozwijany szablon znajduje się w konsoli API Gateway w AWS.

W przypadku interfejsu API kliknij nazwę zasobu ... a następnie GET

Rozwiń „Szablony mapowania ciała”

Wpisz

application / json

dla Content-Type (musi być wyraźnie wpisany) i kliknij znacznik

Otworzy się nowe okno ze słowami „Generuj szablon” i menu rozwijane (patrz zdjęcie).

Wybierz

Przekazanie żądania metody

wprowadź opis zdjęcia tutaj

Następnie kliknij Zapisz

Aby uzyskać dostęp do dowolnych zmiennych, użyj następującej składni (jest to Python), np. URL:

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

Zmienne można uzyskać w następujący sposób:

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'])

Dlatego nie ma potrzeby jawnego nadawania nazw ani mapowania każdej pożądanej zmiennej.


świetny! funkcjonalność jest dostępna w serwisie, ale jej brakowało!
hnvasa

25

Aby przekazać parametry do funkcji lambda, musisz utworzyć mapowanie między żądaniem interfejsu API Gateway a funkcją lambda. Mapowanie odbywa się w Integration Request->Mapping templates wybranego zasobu API Gateway.

Utwórz odwzorowanie typu application/json , a następnie po prawej stronie edytujesz (kliknij ołówkiem) szablon.

Szablon mapowania to tak naprawdę szablon Velocity, w którym można używać ifs, pętli i oczywiście drukować na nim zmienne. W szablonie wprowadzono te zmienne, w których można uzyskać dostęp do parametrów zapytania, nagłówków żądań itp. Indywidualnie. Za pomocą następującego kodu możesz ponownie utworzyć cały kwerenda:

{
    "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('$')
}

Uwaga: kliknij symbol zaznaczenia, aby zapisać szablon. Możesz przetestować swoje zmiany za pomocą przycisku „test” w swoim zasobie. Ale aby przetestować parametry zapytania w konsoli AWS, musisz zdefiniować nazwy parametrów wMethod Request sekcji swojego zasobu.

Uwaga: sprawdź Podręcznik użytkownika Velocity aby uzyskać więcej informacji na temat języka szablonów Velocity.

Następnie w szablonie lambda możesz wykonać następujące czynności, aby przeanalizować kwerendę:

var query = require('querystring').parse(event.querystring)
// access parameters with query['foo'] or query.foo

9
To najlepsze rozwiązanie. Proszę pamiętać, aby to zrobić Actions>Deploy API(traciłem czas, zapominając o tym ...). Skojarzona lambda arn przyjmie zmianę natychmiast po wdrożeniu. Możesz to sprawdzić Stages > #stage (like: prod) > Deployment History.
loretoparisi

24

Przyjęta odpowiedź działała dla mnie dobrze, ale rozwijając odpowiedź gimenete, chciałem ogólnego szablonu, którego mógłbym użyć do przekazania wszystkich parametrów zapytania / ścieżki / nagłówka (jak na razie ciągów znaków), i wymyśliłem następujący szablon. Zamieszczam go tutaj, na wypadek, gdyby ktoś uznał to za przydatne:

#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
}

1
Fab, chciałem móc używać tej samej funkcji zarówno dla żądań POST (z treścią JSON), jak i GET z ciągami zapytań. Działa marzenie. Dzięki!
Matt Fletcher

@benv to pełny szablon?
nxmohamad

17

W ramach odpowiedzi na jedno z moich pytań tutaj , natknąłem się na ten podstęp.

W szablonie odwzorowania bramy API użyj następujących poleceń, aby podać pełny ciąg zapytania wysłany przez klienta HTTP:

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

Zaletą jest to, że nie musisz ograniczać się do zestawu predefiniowanych kluczy odwzorowanych w ciągu zapytania. Teraz możesz zaakceptować dowolne pary klucz-wartość w ciągu zapytania, jeśli tak chcesz sobie radzić.

Uwaga: Zgodnie z tym , tylko $input.params(x)wymieniona jest jako zmienna udostępniona dla szablonu VTL. Możliwe, że elementy wewnętrzne mogą ulec zmianie i querystringmogą nie być już dostępne.


1
Wciąż działa to od maja 2017 r., Ale zwraca obiekt JS, który API Gateway tworzy dla Ciebie, zamiast rzeczywistego ciągu zapytania. Jest to dla mnie denerwujące, ponieważ próbuję przeanalizować ciąg zapytania, aby zamienić powtarzane parametry w tablicę.
Tom Saleeba

11

Teraz powinieneś być w stanie użyć nowego typu integracji proxy dla Lambda, aby automatycznie uzyskać pełne żądanie w standardowym kształcie, zamiast konfigurować mapowania.

patrz: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-set-up-lambda-proxy-integration-on- zasób proxy


1
Nie jestem pewien dlaczego, ale integracja proxy zwykle nie działa dla mnie. Musiałem usunąć go z najnowszych interfejsów API, które utworzyłem.
Gustavo Straube,

to samo ^ ponadto miałem problemy CORS z API Gateway. Postępując zgodnie z dokumentami AWS, nie byłem w stanie uruchomić CORS. Znalazłem jednak stary artykuł Medium z połowy 2015 roku, który miał ręczny sposób konfigurowania CORS i działał.
Stephen Tetreault

7

GET / user? Name = bob

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

GET / user / bob

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

5

Wiele odpowiedzi tutaj jest świetnych. Ale chciałem czegoś nieco prostszego. Chciałem czegoś, co zadziała z próbką „Hello World” za darmo. Oznacza to, że chciałem, aby prosty tworzył treść żądania pasującą do ciągu zapytania:

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

Myślę, że najlepsza odpowiedź daje coś bardziej przydatnego podczas budowania czegoś prawdziwego, ale dla szybkiego przywrócenia świata za pomocą szablonu z AWS działa to świetnie.


4

Poniższy przykład mapowania parametrów przekazuje wszystkie parametry, w tym ścieżkę, kwerendę i nagłówek, do punktu końcowego integracji za pośrednictwem ładunku 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
  }
}

W efekcie ten szablon odwzorowania wyświetla wszystkie parametry żądania w ładunku zgodnie z poniższym opisem:

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

Skopiowano z Amazon API Gateway Developer Guide


2

Ciąg zapytania jest prosty do przetworzenia w javascript w lambda

dla GET / user? name = bob

 var name = event.params.querystring.name;

Nie rozwiązuje to jednak pytania GET user / bob.


its event.queryStringParameters.name
Neo

Musiałem zrobićevent.queryStringParameters.name
Anders Kitson

2

Jako odpowiedź @ Jonathana, po znaku Użyj integracji Lambda Proxy w żądaniu integracji , w kodzie źródłowym powinieneś zaimplementować poniższy format, aby przekazać błąd 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;
};

Nie zapomnij wdrożyć swojego zasobu w API Gateway przed ponownym uruchomieniem API. Odpowiedź JSON po prostu zwraca, który zestaw w treści jest poprawny. Możesz więc uzyskać ścieżkę, parametr, nagłówki, wartość treści ze zdarzenia

const {path, queryStringParameters, headers, body} = event;


1

Funkcja Lambda oczekuje danych wejściowych JSON, dlatego konieczne jest parsowanie ciągu zapytania. Rozwiązaniem jest zmiana ciągu zapytania na JSON przy użyciu szablonu odwzorowania.
Użyłem go dla C # .NET Core, więc oczekiwanym wejściem powinien być JSON z parametrem „queryStringParameters”.
Aby to osiągnąć, wykonaj 4 poniższe kroki:

  1. Otwórz szablon mapowania zasobu API Gateway i dodaj nowy application/jsontyp zawartości:

Szablon mapowania bramy API

  1. Skopiuj poniższy szablon, który analizuje ciąg zapytania do JSON, i wklej go do szablonu odwzorowania:

    {
    "queryStringParameters": {#foreach($key in $input.params().querystring.keySet())#if($foreach.index > 0),#end"$key":"$input.params().querystring.get($key)"#end}
    }
    
  2. W bramie API wywołaj funkcję Lambda i dodaj następujący ciąg zapytania (na przykład): param1=111&param2=222&param3=333

  3. Szablon odwzorowania powinien utworzyć wynik JSON poniżej, który jest danymi wejściowymi dla funkcji Lambda.

    {
    "queryStringParameters": {"param3":"333","param1":"111","param2":"222"}
    }
    
  4. Jesteś skończony. Od tego momentu logika funkcji Lambda może wykorzystywać parametry ciągu zapytania.
    Powodzenia!


0

Możesz użyć Lambda jako „Lambda Proxy Integration” , patrz [ https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda. html # api-gateway-proxy -integracja-lambda-funkcja-python] , dostępne opcje to

W przypadku Nodejs Lambda „event.headers”, „event.pathParameters”, „event.body”, „event.stageVariables” i „event.requestContext”

Dla zdarzenia Python Lambda [„nagłówki”] [„nazwa parametru”] i tak dalej



-1

Po przeczytaniu kilku z tych odpowiedzi użyłem kombinacji kilku w sierpniu 2018 r., Aby pobrać parametry ciągu zapytania przez lambda dla Pythona 3.6.

Najpierw poszedłem do API Gateway -> Mój API -> zasoby (po lewej) -> Żądanie integracji. Na dole u dołu wybierz Szablony odwzorowania, a następnie wpisz typ zawartości application/json.

Następnie wybierz dostarczony przez Amazon szablon metody żądania przejścia, a następnie wybierz opcję zapisz i wdróż interfejs API.

Następnie w lambda event['params']uzyskasz dostęp do wszystkich swoich parametrów. Dla ciągu zapytania:event['params']['querystring']

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.