Why does Lambda URL convert the request body from JSON to string?

1

Hi there,

We are making use of the new Lambda URL feature. When we invoke the URL of our function to send a POST request with a simple body, what we see in the event that the function receives is that the body is shown as a string, and not as a JSON.

For a simple request body that looks like:

{
    "accountId": "123456789012",
    "duration": 5
}

this is what we see in the event object that is passed to the function upon invocation:

{
    "version": "2.0",
    "routeKey": "$default",
    "rawPath": "/",
    "rawQueryString": "",
    "headers": {
        "content-length": "55",
        "x-amz-date": "20220509T192924Z",
        "x-forwarded-proto": "https",
        "x-forwarded-port": "443",
        "x-forwarded-for": "OBFUSCATED",
        "x-amz-security-token": "OBFUSCATED",
        "accept": "*/*",
        "x-amzn-trace-id": "OBFUSCATED",
        "host": "OBFUSCATED",
        "content-type": "application/json",
        "accept-encoding": "gzip, deflate, br",
        "user-agent": "Thunder Client (https://www.thunderclient.com)"
    },
    "requestContext": {
        "accountId": "123456789012",
        "apiId": "OBFUSCATED",
        "authorizer": {
            "iam": {
                "accessKey": "OBFUSCATED",
                "accountId": "123456789012",
                "callerId": "OBFUSCATED",
                "cognitoIdentity": "None",
                "principalOrgId": "OBFUSCATED",
                "userArn": "arn:aws:sts::123456789012:assumed-role/ExampleRole",
                "userId": "OBFUSCATED"
            }
        },
        "domainName": "OBFUSCATED",
        "domainPrefix": "OBFUSCATED",
        "http": {
            "method": "POST",
            "path": "/",
            "protocol": "HTTP/1.1",
            "sourceIp": "OBFUSCATED",
            "userAgent": "Thunder Client (https://www.thunderclient.com)"
        },
        "requestId": "b76a957b-2f63-4fd8-8944-65hy79b62711",
        "routeKey": "$default",
        "stage": "$default",
        "time": "09/May/2022:19:29:28 +0000",
        "timeEpoch": 1652124568118
    },
    "body": "{\\n    \"accountId\": \"123456789012\",\\n    \"duration\": 5\\n}",
    "isBase64Encoded": "False"
}

As you can see the value of the body node is wrapped in " and AWS has added also the new line characters together with escape characters.

Because of this, we can't simply parse the body, and therefore we always have to deserialize it and remove the newline characters.

Any idea why this happens? Am I missing something when I send the request?

Thank you in advance!

Pier
質問済み 2年前8610ビュー
4回答
0
承認された回答

Hey Pier, you are right. My answer was wrong in your context, sorry about that. But the body being string is by design as noted by Uri.

profile pictureAWS
Eduardo
回答済み 2年前
0

This is by design.

I think you are only able to change it using API Gateway. Lambda functions with PROXY integration accelerates your integration process as you don't need to create the request and response templates. And, as the Lambda can receive binary payload in BASE64, the body should have a type for this case also, as, the payload is not JSON.

You can still receive the payload as JSON if you setup the request and response templates by yourself.

profile pictureAWS
Eduardo
回答済み 2年前
  • Thank you for your answer, Eduardo.

    How can set up a request template for a Lambda URL? I haven't seen that being supported for Lambda URLs. The link you posted is for API Gateway.

  • The reason provided by Eduardo is correct, although the details relate to API Gateway with Lambda and not Lambda Function URLs.

    I think that depending on the programming language, you should be able to parse it easily, e.g., in Python use something like body = json.loads(event.body)

0

When calling the function from outside, you'll get an event composed by the system, and in it, the body will be a string. If you want to use it as an object, you need to convert it back. For example, in node.js, you need to use something like this:

exports.handler = async (event) => {
  const body = JSON.parse(event.body)
...

ps. You may also want to prepare for errors in the body, as it may be invalid, so, you can put the parse in a try..catch block, and check if the required parameter is defined etc.

回答済み 1年前
0

I haven't found any documentation of this in the AWS Lambda documentation. It seems like a basic fundamental concern that should be addressed in AWS Lambda 101. Did I miss the documentation or do you have to trawl through user questions to get this information?

p.s. I've found some related documentation under AWS API Gateway, but I still don't see Lambda documentation of fundamental concerns such as parsing of the JSON body, HTTP status header control for responses, additional content that Lambda seems to generate in the response, etc.: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-integrations.html

Neil
回答済み 8ヶ月前

ログインしていません。 ログイン 回答を投稿する。

優れた回答とは、質問に明確に答え、建設的なフィードバックを提供し、質問者の専門分野におけるスキルの向上を促すものです。

質問に答えるためのガイドライン

関連するコンテンツ