当前位置: 首页 > 知识库问答 >
问题:

通过API网关在aws Lambda中获取json身体

慕皓君
2023-03-14

我目前正在使用NodeJS通过AWS Api网关在AWS lambda上构建机器人,我遇到了POST请求和JSON数据的问题。我的api使用“使用Lambda代理集成”,即使当我测试代理发送内容类型的应用程序/json和正文中的一些json时,例如g{"foo":"bar"}我不能访问对象,除非先解析它

e. g.

  var json = JSON.parse(event.body);
  console.log(json.foo);

现在我知道,仅仅通过JSON.parse运行它似乎没什么大不了的,但是我已经看到了许多其他的例子,其中根本不是这样的。看这里https://github.com/pinzler/fb-messenger-bot-aws-lambda/blob/master/index.js

我是否需要向API网关添加任何内容才能正确处理此问题?“post method request”部分中我的“request body”步骤为请求主体设置了一个内容类型为application/json的设置。

就我所知,上面例子的自述文件似乎没有使用代理集成,所以我不确定我应该在这里做什么

共有3个答案

郭皓
2023-03-14

我将lambda与Zappa一起使用;我正在发送json格式的POST数据:

我的basic_lambda_pure.py代码是:

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

我得到了下一个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
}

我的数据是在body key上的,但是是code64编码的,我怎么知道呢?我看到钥匙是Base64编码的

我复制body key的值,然后用这个工具解码,“eureka”,我得到值。

我希望这对你有帮助。:)

谷梁英毅
2023-03-14

我认为,在使用与Lambda集成的API网关时,需要了解一些事情。

过去只有Lambda集成需要映射模板。我想这就是为什么仍然有很多例子在使用它。

  • 如何从亚马逊API网关向AWS Lambda传递查询字符串或路由参数

从2017年9月起,您不再需要配置映射来访问请求主体。

  • AWS上的无服务器架构

Lambda代理集成,如果您启用它,API网关将把每个请求映射到JSON,并将其作为事件对象传递给Lambda。在Lambda函数中,您将能够从中检索查询字符串参数、标头、阶段变量、路径参数、请求上下文和主体。如果不启用Lambda代理集成,您必须在应用编程接口的集成请求部分创建映射模板然后决定如何将HTTP请求映射到JSON。如果要将信息传递回客户端,您可能必须创建一个集成响应映射。在添加Lambda代理集成之前,用户被迫手动映射请求和响应,这是一个令人惊愕的来源,尤其是在更多的情况下复杂映射。

语言需要引导思维。把术语弄清楚。

>

  • Lambda Proxy Integration=Pass-through
    只需将HTTP请求传递给Lambda即可。

    Lambda Integration=Template transformation
    使用Apache Velocity模板完成转换过程,您需要自己编写模板。

    使用Lambda代理集成,Lambda事件中的主体是使用反斜杠转义的字符串,而不是JSON。

    "body": "{\"foo\":\"bar\"}" 
    

    如果在JSON格式化程序中测试。

    Parse error on line 1:
    {\"foo\":\"bar\"}
    -^
    Expecting 'STRING', '}', got 'undefined'
    

    下面的文档是关于响应的,但应适用于请求。

    • 我收到了一个格式错误的Lambda代理响应错误或亚马逊应用编程接口网关的502状态代码。我该如何解决这个问题?

    如果返回JSON,则必须将body字段转换为字符串,否则将导致响应出现进一步的问题。您可以在Node.js函数中使用JSON.stringify来处理此问题;其他运行时将需要不同的解决方案,但概念是相同的。

    为了让JavaScript将其作为JSON对象访问,需要使用JapaScript中的JSON.parse和Python中的JSON.dumps将其转换回JSON对象。

    • 如何在JavaScript中使用JSON

    字符串对于传输非常有用,但您希望能够在客户端和/或服务器端将其转换回JSON对象。

    AWS文档说明了如何操作。

    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);
    

  • 严项明
    2023-03-14

    您可以在API网关中配置两种不同的Lambda集成,例如Lambda集成和Lambda代理集成。对于Lambda集成,您可以在不需要解析主体的有效载荷中自定义要传递给Lambda的内容,但是当您在API网关中使用Lambda代理集成时,API网关将像这样在有效载荷中代理Lambda的所有内容,

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

    对于您正在引用的示例,它不是从原始请求获取主体。它正在构造返回API网关的响应体。应该是这个格式,,

    {
        "statusCode": httpStatusCode,
        "headers": { "headerName": "headerValue", ... },
        "body": "...",
        "isBase64Encoded": false
    }
    
     类似资料:
    • 我在Azure(Web App)中托管了一个API。每个客户端都无法访问此API目录(IP限制),我愿意使用APIM来保护它。 用户将调用APIM网关,网关应做出适当响应。 一个大问题是身份验证:我正在用AAD保护这个API(后端API而不是APIM网关endpoint)。因此,用户应该根据AAD对自己进行身份验证,并在不直接访问后端的情况下访问资源。 有没有可能实现这样的场景?

    • 问题内容: 这是我的带有json响应的模型: 在这里,我通过http.request得到它。为什么我接收(数据)字符串而不是json? 如何获取json? 问题答案: http以字符串形式发送/接收数据…这就是事实。您正在寻找将该字符串解析为json。

    • 首先,我对AWS很陌生。以下是我想要达到的目标: null 因此,现在我有了一个专用子网,其endpoint允许HTTP(S)流量。该endpoint具有某些(专用)DNS名称,(可能)也具有专用IP(找不到) 现在我想要添加一个API网关来前面的一些AWS lambda。我创建所述API,并将其作为endpoint类型->Private 下面是:正式文档将API网关“链接”到VPCendpoin

    • 是否可以通过CloudFront对API网关endpoint使用IAM角色身份验证? 下面是一个基本用例: null 选项:200 岗位:403 {“消息”:“我们计算的请求签名与您提供的签名不匹配。请检查您的AWS秘密访问密钥和签名方法。有关详细信息,请参阅服务文档。\n\n此请求的规范字符串应为\n'POST\n/test/create\naccept:application/json\nco

    • 如何获取json请求正文?