Comment passer une chaîne de requête ou un paramètre de route à AWS Lambda à partir d'Amazon API Gateway

348

par exemple, si nous voulons utiliser

GET /user?name=bob

ou

GET /user/bob

Comment transmettriez-vous ces deux exemples en tant que paramètre à la fonction Lambda?

J'ai vu quelque chose sur la définition d'un "mappé depuis" dans la documentation, mais je ne trouve pas ce paramètre dans la console API Gateway.

  • method.request.path.parameter-namepour un paramètre de chemin nommé parameter-namecomme défini dans la page de demande de méthode.
  • method.request.querystring.parameter-namepour un paramètre de chaîne de requête nommé parameter-namecomme défini dans la page Demande de méthode.

Je ne vois aucune de ces options même si j'ai défini une chaîne de requête.

MonkeyBonkey
la source

Réponses:

299

Depuis septembre 2017, vous n'avez plus à configurer les mappages pour accéder au corps de la demande.

Tout ce que vous devez faire est de vérifier, "Utiliser l'intégration du proxy Lambda", sous Demande d'intégration, sous la ressource.

entrez la description de l'image ici

Vous pourrez ensuite accéder aux paramètres de requête, aux paramètres de chemin et aux en-têtes comme ceci

event['pathParameters']['param1']
event["queryStringParameters"]['queryparam1']
event['requestContext']['identity']['userAgent']
event['requestContext']['identity']['sourceIP']
Jonathan
la source
23
Ceci est un excellent conseil. Mais gardez à l'esprit que l'activation de l'intégration du proxy Lambda peut provoquer une erreur «Réponse du proxy Lambda mal formée». Voici comment y remédier: stackoverflow.com/questions/43708017/…
AaronBaker
5
existe-t-il un moyen de le faire en java, tout en conservant la désérialisation transparente RequestHandlerfournie par l' implémentation ?
chaussure
2
où est ce paramètre?
red888
2
@MattWestlake Vous créez une ressource appelée utilisateur et en dessous une ressource appelée {nom} dans API Gateway.
Jonathan
3
Je veux juste mentionner qu'après ce changement, j'ai également dû aller sur Amazon API Gateway -> Actions -> Déployer l'API et redéployer dans l'environnement en direct.
victorvartan
221

Les étapes pour obtenir ce fonctionnement sont les suivantes:

Dans la console API Gateway ...

  1. aller à Resources -> Integration Request
  2. cliquez sur l'icône plus ou modifier à côté de la liste déroulante des modèles (bizarre, je sais que le champ du modèle est déjà ouvert et que le bouton ici est grisé)
  3. Tapez explicitement application/jsondans le champ de type de contenu même s'il affiche une valeur par défaut (si vous ne le faites pas, il ne sera pas enregistré et ne vous donnera pas de message d'erreur)
  4. mettre cela dans le mappage d'entrée { "name": "$input.params('name')" }

  5. cliquez sur la case à cocher à côté de la liste déroulante des modèles (je suppose que c'est ce qui l'enregistre finalement)

MonkeyBonkey
la source
9
Avez-vous déjà obtenu ceci pour envoyer des paramètres d'URL dans des URL comme / user / bob où l'itinéraire était / user / {username}? J'ai essayé toutes sortes de permutations, mais je n'ai pas pu résoudre cela.
Lucas
5
quelqu'un sait-il s'il existe une documentation officielle? serait bien de passer à travers tous les paramètres de requête ou de gérer les valeurs optionnelles plus gracieusement que les chaînes vides
AxelTheGerman
6
Un conseil pour les développeurs iOS: API Gateway ne transmettra pas les données de requête tant que vous n'aurez pas défini chaque variable comme chaîne de requête (sous 'Method Request') ET déployé l'API. Jusqu'au déploiement, il fonctionne à partir du test de la console, mais coupe les requêtes de l'application.
AlexeyVMP
6
Lucas, je l'ai fait fonctionner en utilisant le modèle / user / {username}. N'oubliez pas que si votre chemin d'accès aux ressources GET est / user / {username}, à l'étape 4, le mappage d'entrée ressemble à ceci {"name": "$ input.params ('username')"}
Gerard
134

J'ai utilisé ce modèle de mappage pour fournir des paramètres de chaîne de requête Body, Headers, Method, Path et URL à l'événement Lambda. J'ai écrit un article de blog expliquant le modèle plus en détail: http://kennbrodhagen.net/2015/12/06/how-to-create-a-request-object-for-your-lambda-event-from-api- passerelle/

Voici le modèle de mappage que vous pouvez utiliser:

{
  "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
la source
Incroyable! J'avais du mal à transmettre les choses de manière générique à mon gestionnaire. Meilleure réponse ici.
Venkat D.
Je l'ai fait, mais je ne reçois rien encore. Son affichage indéfini. Comment sommes-nous censés envoyer les paramètres dans l'URL? et devons-nous spécifier le nom de la variable dans l'URL comme dans un scénario d'URL GET normal? S'il vous plaît, aidez-moi avec ça.
Parthapratim Neog
8
Peu importe, j'ai obtenu le résultat. Le problème était, j'ai ajouté le mappage et je l'ai simplement enregistré, et je n'ai pas fait de deploynouveau l'api. Une fois que j'ai déployé l'API avec la nouvelle cartographie, cela a très bien fonctionné. Merci beaucoup.
Parthapratim Neog
@ shashu10 Voir ma réponse
matsev
1
Je ne peux pas commencer à vous dire à quel point votre blog est utile. J'ai trouvé le post "eturn-html-from-aws-api-gateway" en premier et l'ai suivi, car c'est exactement ce dont j'avais besoin. Maintenant, je dois passer quelques paramètres à la fonction et modifier le html en fonction de cela - et encore une fois, vous êtes le seul à avoir un vrai guide! Tous les autres guides que j'ai trouvés semblent manquer le propos.
user3685427
41

Ces jours-ci, un modèle de liste déroulante est inclus dans la console API Gateway sur AWS.

Pour votre API, cliquez sur le nom de la ressource ... puis OBTENEZ

Développez "Modèles de cartographie du corps"

Tapez

application / json

pour Content-Type (doit être explicitement tapé) et cliquez sur la coche

Une nouvelle fenêtre s'ouvrira avec les mots "Générer le modèle" et une liste déroulante (voir image).

Sélectionner

Passthrough de demande de méthode

entrez la description de l'image ici

Cliquez ensuite sur enregistrer

Pour accéder à toutes les variables, utilisez simplement la syntaxe suivante (c'est Python) par exemple URL:

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

Vous pouvez obtenir des variables comme suit:

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

Il n'est donc pas nécessaire de nommer ou de mapper explicitement chaque variable souhaitée.

Dirk Conrad Coetsee
la source
excellent! la fonctionnalité est là dans le service mais elle l'avait manqué!
hnvasa
25

Pour transmettre des paramètres à votre fonction lambda, vous devez créer un mappage entre la demande API Gateway et votre fonction lambda. Le mappage est effectué dans la section Integration Request-> Mapping templatesde la ressource API Gateway sélectionnée.

Créez un mappage de type application/json, puis à droite vous éditez (cliquez sur le crayon) le modèle.

Un modèle de mappage est en fait un modèle Velocity où vous pouvez utiliser des ifs, des boucles et bien sûr imprimer des variables dessus. Le modèle a ces variables injectées où vous pouvez accéder individuellement aux paramètres de la chaîne de requête, demander les en-têtes, etc. Avec le code suivant, vous pouvez recréer la chaîne de requête entière:

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

Remarque: cliquez sur le symbole de contrôle pour enregistrer le modèle. Vous pouvez tester vos modifications avec le bouton "test" de votre ressource. Mais pour tester les paramètres de la chaîne de requête dans la console AWS, vous devrez définir les noms des paramètres dans la Method Requestsection de votre ressource.

Remarque: consultez le Guide de l'utilisateur Velocity pour plus d'informations sur le langage de modélisation Velocity.

Ensuite, dans votre modèle lambda, vous pouvez effectuer les opérations suivantes pour analyser la chaîne de requête:

var query = require('querystring').parse(event.querystring)
// access parameters with query['foo'] or query.foo
gimenete
la source
9
C'est la meilleure solution. N'oubliez pas de faire Actions>Deploy APIalors (j'ai perdu mon temps à oublier cela ...). L'arn lambda associé prendra la modification immédiatement après le déploiement. Vous pouvez le vérifier Stages > #stage (like: prod) > Deployment History.
loretoparisi
24

La réponse acceptée a bien fonctionné pour moi, mais en développant la réponse de gimenete, je voulais un modèle générique que je pourrais utiliser pour passer à travers tous les paramètres de requête / chemin / en-tête (tout comme les chaînes pour l'instant), et j'ai créé le modèle suivant. Je le poste ici au cas où quelqu'un le trouverait utile:

#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
la source
1
Fab, je voulais pouvoir utiliser la même fonction pour les requêtes POST (avec corps JSON) et GET avec les chaînes de requête. Fonctionne un rêve. Merci!
Matt Fletcher
@benv est-ce le modèle complet?
nxmohamad
17

Dans le cadre d'essayer de répondre à l'une de mes propres questions ici , je suis tombé sur cette astuce.

Dans le modèle de mappage API Gateway, utilisez ce qui suit pour vous donner la chaîne de requête complète envoyée par le client HTTP:

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

L'avantage est que vous n'avez pas à vous limiter à un ensemble de clés mappées prédéfinies dans votre chaîne de requête. Vous pouvez maintenant accepter toutes les paires clé-valeur dans la chaîne de requête, si c'est ainsi que vous souhaitez gérer.

Remarque: selon cela , seule $input.params(x)est répertoriée en tant que variable mise à disposition pour le modèle VTL. Il est possible que les internes changent et querystringne soient plus disponibles.

user3526
la source
1
Cela fonctionne toujours depuis mai 2017, mais il renvoie l'objet JS que API Gateway crée pour vous plutôt que la chaîne de requête réelle. C'est ennuyeux pour moi car j'essaie d'analyser la chaîne de requête pour transformer des paramètres répétés en un tableau.
Tom Saleeba
11

Vous devriez maintenant pouvoir utiliser le nouveau type d'intégration de proxy pour Lambda pour obtenir automatiquement la demande complète sous forme standard, plutôt que de configurer des mappages.

voir: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-set-up-lambda-proxy-integration-on- ressource-proxy

jackko
la source
1
Je ne sais pas pourquoi, mais l'intégration du proxy ne fonctionne généralement pas pour moi. J'ai dû le supprimer des dernières API que j'ai créées.
Gustavo Straube
même ^ en outre, j'ai eu des problèmes CORS avec API Gateway. Suite aux documents AWS, je n'ai pas réussi à faire fonctionner CORS. Cependant, j'ai trouvé un ancien article Medium de la mi-fin 2015 qui avait une manière manuelle de configurer CORS et qui fonctionnait.
Stephen Tetreault
7

GET / utilisateur? Name = bob

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

GET / utilisateur / bob

{
    "name": "$input.params('name')"
}
Dmitry Grinko
la source
5

Beaucoup de réponses ici sont excellentes. Mais je voulais quelque chose d'un peu plus simple. Je voulais quelque chose qui fonctionnera avec l'échantillon "Hello World" gratuitement. Cela signifie que je voulais un simple produit un corps de demande qui correspond à la chaîne de requête:

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

Je pense que la première réponse produit quelque chose de plus utile lors de la construction de quelque chose de réel, mais pour obtenir un bonjour rapide en utilisant le modèle d'AWS, cela fonctionne très bien.

KrisTC
la source
4

L'exemple de mappage de paramètres suivant transmet tous les paramètres, y compris le chemin d'accès, la chaîne de requête et l'en-tête, au point de terminaison d'intégration via une charge utile 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
  }
}

En effet, ce modèle de mappage génère tous les paramètres de demande dans la charge utile, comme indiqué ci-dessous:

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

Copié à partir du guide du développeur Amazon API Gateway

matsev
la source
2

La chaîne de requête est simple à analyser en javascript dans le lambda

pour GET / utilisateur? name = bob

 var name = event.params.querystring.name;

Cela ne résout cependant pas la question de l'utilisateur / bob GET.

Michael Riecken
la source
its event.queryStringParameters.name
Neo
Je devais faireevent.queryStringParameters.name
Anders Kitson
2

Comme réponse de @ Jonathan, après avoir marqué Utiliser l'intégration du proxy Lambda dans la demande d'intégration , dans votre code source, vous devez implémenter le format ci-dessous pour contourner l' erreur 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;
};

N'oubliez pas de déployer votre ressource sur API Gateway avant de réexécuter votre API. La réponse JSON renvoie simplement quel ensemble dans le corps est correct. Ainsi, vous pouvez obtenir le chemin, le paramètre, les en-têtes et la valeur corporelle de l'événement

const {path, queryStringParameters, headers, body} = événement;

Long Nguyen
la source
1

La fonction Lambda attend une entrée JSON, donc l'analyse de la chaîne de requête est nécessaire. La solution consiste à remplacer la chaîne de requête par JSON à l'aide du modèle de mappage.
Je l'ai utilisé pour C # .NET Core, donc l'entrée attendue devrait être un JSON avec le paramètre "queryStringParameters".
Suivez ces 4 étapes ci-dessous pour y parvenir:

  1. Ouvrez le modèle de mappage de votre ressource API Gateway et ajoutez un nouveau application/jsoncontenu-tyap:

Modèle de mappage API Gateway

  1. Copiez le modèle ci-dessous, qui analyse la chaîne de requête dans JSON, et collez-le dans le modèle de mappage:

    {
    "queryStringParameters": {#foreach($key in $input.params().querystring.keySet())#if($foreach.index > 0),#end"$key":"$input.params().querystring.get($key)"#end}
    }
    
  2. Dans l'API Gateway, appelez votre fonction Lambda et ajoutez la chaîne de requête suivante (pour l'exemple): param1=111&param2=222&param3=333

  3. Le modèle de mappage doit créer la sortie JSON ci-dessous, qui est l' entrée pour votre fonction Lambda.

    {
    "queryStringParameters": {"param3":"333","param1":"111","param2":"222"}
    }
    
  4. Vous avez terminé. À partir de ce moment, la logique de votre fonction Lambda peut utiliser les paramètres de chaîne de requête.
    Bonne chance!

Lior Kirshner
la source
0

Vous pouvez utiliser Lambda comme «intégration de proxy Lambda» , référez-vous à cette [ https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda. html # api-gateway-proxy-integration-lambda-function-python] , les options disponibles pour ce lambda sont

Pour Nodejs Lambda 'event.headers', 'event.pathParameters', 'event.body', 'event.stageVariables' et 'event.requestContext'

Pour l'événement Python Lambda ['headers'] ['parametername'] et ainsi de suite

RajDev
la source
-1

Après avoir lu plusieurs de ces réponses, j'ai utilisé une combinaison de plusieurs en août 2018 pour récupérer les paramètres de chaîne de requête via lambda pour python 3.6.

Tout d'abord, je suis allé à API Gateway -> Mon API -> ressources (à gauche) -> Demande d'intégration. En bas en bas, sélectionnez Modèles de mappage puis entrez le type de contenu application/json.

Ensuite, sélectionnez le modèle Passthrough de demande de méthode fourni par Amazon et sélectionnez enregistrer et déployer votre API.

Ensuite, lambda event['params']est la façon dont vous accédez à tous vos paramètres. Pour la chaîne de requête:event['params']['querystring']

Jghorton14
la source