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
gefragt vor 2 Jahren8610 Aufrufe
4 Antworten
0
Akzeptierte Antwort

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
beantwortet vor 2 Jahren
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
beantwortet vor 2 Jahren
  • 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.

beantwortet vor einem Jahr
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
beantwortet vor 8 Monaten

Du bist nicht angemeldet. Anmelden um eine Antwort zu veröffentlichen.

Eine gute Antwort beantwortet die Frage klar, gibt konstruktives Feedback und fördert die berufliche Weiterentwicklung des Fragenstellers.

Richtlinien für die Beantwortung von Fragen