Obtenir le corps json dans aws Lambda via API gateway
j'utilise actuellement NodeJS pour construire un bot sur AWS lambda via la passerelle de L'Api AWS et je suis en train de rencontrer un problème avec les requêtes POST et les données JSON. Mon api utilise 'use Lambda Proxy integration' et même lorsque je teste le proxy qui envoie un contenu-type D'Application / json et quelques json dans le corps E. g {"foo":"bar"}
I can't access the object without parsing it first
E. g
var json = JSON.parse(event.body);
console.log(json.foo);
maintenant je sais que cela ne semble pas une grosse affaire par JSON.analyser, mais j'ai vu un certain nombre d'autres exemples où ce n'est pas du tout le cas. voir ici https://github.com/pinzler/fb-messenger-bot-aws-lambda/blob/master/index.js
dois-je ajouter quelque chose à ma passerelle API pour gérer cela correctement? mon étape ' request body 'dans la section' post method request ' a un type de contenu de la configuration application/json pour le corps de la requête.
le readme pour l'exemple ci-dessus ne semble pas utiliser l'intégration par procuration autant que je peux le dire, donc je ne suis pas sûr de ce que je devrais faire ici
3 réponses
il existe deux intégrations Lambda différentes que vous pouvez configurer dans API Gateway, telles que Lambda integration et Lambda proxy integration. Pour Lambda integration , vous pouvez personnaliser ce que vous allez passer à Lambda dans la charge utile que vous n'avez pas besoin de parser le corps, mais lorsque vous utilisez Lambda Proxy integration dans API Gateway, API Gateway va proxy tout à Lambda dans la charge utile comme ceci,
{
"message": "Hello me!",
"input": {
"path": "/test/hello",
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, lzma, sdch, br",
"Accept-Language": "en-US,en;q=0.8",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "US",
"Host": "wt6mne2s9k.execute-api.us-west-2.amazonaws.com",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48",
"Via": "1.1 fb7cca60f0ecd82ce07790c9c5eef16c.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "nBsWBOrSHMgnaROZJK1wGCZ9PcRcSpq_oSXZNQwQ10OTZL4cimZo3g==",
"X-Forwarded-For": "192.168.100.1, 192.168.1.1",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"pathParameters": {"proxy": "hello"},
"requestContext": {
"accountId": "123456789012",
"resourceId": "us4z18",
"stage": "test",
"requestId": "41b45ea3-70b5-11e6-b7bd-69b5aaebc7d9",
"identity": {
"cognitoIdentityPoolId": "",
"accountId": "",
"cognitoIdentityId": "",
"caller": "",
"apiKey": "",
"sourceIp": "192.168.100.1",
"cognitoAuthenticationType": "",
"cognitoAuthenticationProvider": "",
"userArn": "",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48",
"user": ""
},
"resourcePath": "/{proxy+}",
"httpMethod": "GET",
"apiId": "wt6mne2s9k"
},
"resource": "/{proxy+}",
"httpMethod": "GET",
"queryStringParameters": {"name": "me"},
"stageVariables": {"stageVarName": "stageVarValue"},
"body": "{\"foo\":\"bar\"}",
"isBase64Encoded": false
}
}
Pour l'exemple que vous faites référence, il n'est pas le corps de la demande originale. Il construit le corps de réponse vers la passerelle API. Il devrait être dans ce format,
{
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "...",
"isBase64Encoded": false
}
je pense qu'il y a quelques choses à comprendre quand on travaille avec L'intégration de passerelle API avec Lambda.
Lambda Intégration vs Lambda Proxy Intégration
il n'y avait que Lambda Integration qui nécessite des modèles de mappage. Je suppose que c'est la raison pour laquelle beaucoup d'exemples l'utilisent encore.
-
Comment passer un paramètre querystring ou route à AWS Lambda de L'API Amazon Passerelle
depuis septembre 2017, vous n'avez plus besoin de configurer mappings pour accéder au corps de la requête.
-
architecture sans serveur sur AWS
Lambda Proxy Integration, si vous l'activez, API Gateway mappera toutes les requêtes vers JSON et les transmettra à Lambda comme objet event. Dans la fonction Lambda vous pourrez pour récupérer les paramètres de la chaîne de requête, les en-têtes, les variables d'étape, les paramètres de chemin, le contexte de la requête, et le corps de celle-ci.
Sans permettre L'intégration de Lambda Proxy, vous devrez créer un modèle de mapping dans la section Demande D'intégration de la passerelle API et décider vous-même comment mapper la demande HTTP à JSON. Et vous auriez probablement à créer un mappage de réponse D'intégration si vous deviez transmettre l'information au client.
Avant que L'intégration par procuration Lambda ne soit ajoutée ,les utilisateurs de ont été forcés de cartographier les requêtes et les réponses manuellement, ce qui a été une source de consternation , surtout avec des correspondances plus complexes.
le corps est une corde échappée, pas JSON
utilisant Lambda Proxy Integration, le corps dans le cas de lambda est une corde échappée avec backslash, pas un JSON.
"body": "{\"foo\":\"bar\"}"
si testé dans un formatteur JSON.
Parse error on line 1:
{\"foo\":\"bar\"}
-^
Expecting 'STRING', '}', got 'undefined'
le document ci-dessous concerne la réponse, mais il doit s'appliquer à la demande.
- j'ai reçu une erreur de "malformed Lambda proxy response" ou un code de statut 502 avec Amazon API Gateway. Comment puis-je résoudre ce problème?
le champ body, si vous retournez JSON, doit être converti en chaîne ou il causera d'autres problèmes avec la réponse. Vous pouvez utiliser JSON.stringify pour gérer ce Nœud.js fonctions; d'autres runtimes exigera des solutions différentes, mais le concept est le même.
pour que JavaScript y accède en tant qu'objet JSON, il faut le reconvertir en objet JSON avec json.analyser dans JapaScript, json.les décharges en Python.
- comment travailler avec JSON en JavaScript
chaînes sont utiles pour le transport, mais vous voudrez être en mesure de les convertir en un objet JSON du côté du client et/ou du serveur.
la documentation AWS montre ce qu'il faut faire.
if (event.body !== null && event.body !== undefined) {
let body = JSON.parse(event.body)
if (body.time)
time = body.time;
}
...
var response = {
statusCode: responseCode,
headers: {
"x-custom-header" : "my custom header value"
},
body: JSON.stringify(responseBody)
};
console.log("response: " + JSON.stringify(response))
callback(null, response);
j'utilise lambda avec Zappa; J'envoie des données avec le POST dans le format json:
mon code pour basic_lambda_pure.py est:
import time
import requests
import json
def my_handler(event, context):
print("Received event: " + json.dumps(event, indent=2))
print("Log stream name:", context.log_stream_name)
print("Log group name:", context.log_group_name)
print("Request ID:", context.aws_request_id)
print("Mem. limits(MB):", context.memory_limit_in_mb)
# Code will execute quickly, so we add a 1 second intentional delay so you can see that in time remaining value.
print("Time remaining (MS):", context.get_remaining_time_in_millis())
if event["httpMethod"] == "GET":
hub_mode = event["queryStringParameters"]["hub.mode"]
hub_challenge = event["queryStringParameters"]["hub.challenge"]
hub_verify_token = event["queryStringParameters"]["hub.verify_token"]
return {'statusCode': '200', 'body': hub_challenge, 'headers': 'Content-Type': 'application/json'}}
if event["httpMethod"] == "post":
token = "xxxx"
params = {
"access_token": token
}
headers = {
"Content-Type": "application/json"
}
_data = {"recipient": {"id": 1459299024159359}}
_data.update({"message": {"text": "text"}})
data = json.dumps(_data)
r = requests.post("https://graph.facebook.com/v2.9/me/messages",params=params, headers=headers, data=data, timeout=2)
return {'statusCode': '200', 'body': "ok", 'headers': {'Content-Type': 'application/json'}}
j'ai eu la réponse suivante de json:
{
"resource": "/",
"path": "/",
"httpMethod": "POST",
"headers": {
"Accept": "*/*",
"Accept-Encoding": "deflate, gzip",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "US",
"Content-Type": "application/json",
"Host": "ox53v9d8ug.execute-api.us-east-1.amazonaws.com",
"Via": "1.1 f1836a6a7245cc3f6e190d259a0d9273.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "LVcBZU-YqklHty7Ii3NRFOqVXJJEr7xXQdxAtFP46tMewFpJsQlD2Q==",
"X-Amzn-Trace-Id": "Root=1-59ec25c6-1018575e4483a16666d6f5c5",
"X-Forwarded-For": "69.171.225.87, 52.46.17.84",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https",
"X-Hub-Signature": "sha1=10504e2878e56ea6776dfbeae807de263772e9f2"
},
"queryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"requestContext": {
"path": "/dev",
"accountId": "001513791584",
"resourceId": "i6d2tyihx7",
"stage": "dev",
"requestId": "d58c5804-b6e5-11e7-8761-a9efcf8a8121",
"identity": {
"cognitoIdentityPoolId": null,
"accountId": null,
"cognitoIdentityId": null,
"caller": null,
"apiKey": "",
"sourceIp": "69.171.225.87",
"accessKey": null,
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": null,
"userAgent": null,
"user": null
},
"resourcePath": "/",
"httpMethod": "POST",
"apiId": "ox53v9d8ug"
},
"body": "eyJvYmplY3QiOiJwYWdlIiwiZW50cnkiOlt7ImlkIjoiMTA3OTk2NDk2NTUxMDM1IiwidGltZSI6MTUwODY0ODM5MDE5NCwibWVzc2FnaW5nIjpbeyJzZW5kZXIiOnsiaWQiOiIxNDAzMDY4MDI5ODExODY1In0sInJlY2lwaWVudCI6eyJpZCI6IjEwNzk5NjQ5NjU1MTAzNSJ9LCJ0aW1lc3RhbXAiOjE1MDg2NDgzODk1NTUsIm1lc3NhZ2UiOnsibWlkIjoibWlkLiRjQUFBNHo5RmFDckJsYzdqVHMxZlFuT1daNXFaQyIsInNlcSI6MTY0MDAsInRleHQiOiJob2xhIn19XX1dfQ==",
"isBase64Encoded": true
}
mes données étaient sur corps clé, mais est codé code64, Comment puis-je savoir cela? J'ai vu la clé isBase64Encoded
"je copie la valeur pour corps clé et décoder avec Cet outil et "eureka", j'obtiens les valeurs.
j'espère que cela vous aidera. :)