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

25
demandé sur TommyBs 2017-01-14 12:23:36

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
}
23
répondu Ka Hou Ieong 2018-02-25 20:38:39

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.

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.

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);
3
répondu mon 2018-09-08 23:25:55

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. :)

0
répondu Te ENe Te 2017-10-22 05:25:18