Kludex / mangum

AWS Lambda support for ASGI applications
http://mangum.fastapiexpert.com/
MIT License
1.71k stars 127 forks source link

Cannot pass JSON in request body: 'dict' object has no attribute 'encode' #152

Closed HumanRupert closed 3 years ago

HumanRupert commented 3 years ago

Request:

{
  "body": {
    "data": "Oh my god. They killed Kenny!"
  },
  "resource": "/{proxy+}",
  "path": "/api/v1/price_action/$RUDPA",
  "httpMethod": "POST",
  "queryStringParameters": {
    "foo": "bar"
  },
  "multiValueQueryStringParameters": {
    "foo": [
      "bar"
    ]
  },
  "pathParameters": {
    "proxy": "/path/to/resource"
  },
  "stageVariables": {
    "baz": "qux"
  },
  "headers": {
    "Content-Type": "application/json",
    "Accept": "text/html,application/xhtml+xml,application/json;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate, sdch",
    "Accept-Language": "en-US,en;q=0.8",
    "Cache-Control": "max-age=0",
    "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": "1234567890.execute-api.eu-west-2.amazonaws.com",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Custom User Agent String",
    "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
    "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
    "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
    "X-Forwarded-Port": "443",
    "X-Forwarded-Proto": "https"
  },
  "multiValueHeaders": {
    "Accept": [
      "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
    ],
    "Accept-Encoding": [
      "gzip, deflate, sdch"
    ],
    "Accept-Language": [
      "en-US,en;q=0.8"
    ],
    "Cache-Control": [
      "max-age=0"
    ],
    "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": [
      "0123456789.execute-api.eu-west-2.amazonaws.com"
    ],
    "Upgrade-Insecure-Requests": [
      "1"
    ],
    "User-Agent": [
      "Custom User Agent String"
    ],
    "Via": [
      "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)"
    ],
    "X-Amz-Cf-Id": [
      "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA=="
    ],
    "X-Forwarded-For": [
      "127.0.0.1, 127.0.0.2"
    ],
    "X-Forwarded-Port": [
      "443"
    ],
    "X-Forwarded-Proto": [
      "https"
    ]
  },
  "requestContext": {
    "accountId": "123456789012",
    "resourceId": "123456",
    "stage": "prod",
    "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "requestTime": "09/Apr/2015:12:34:56 +0000",
    "requestTimeEpoch": 1428582896000,
    "identity": {
      "cognitoIdentityPoolId": null,
      "accountId": null,
      "cognitoIdentityId": null,
      "caller": null,
      "accessKey": null,
      "sourceIp": "127.0.0.1",
      "cognitoAuthenticationType": null,
      "cognitoAuthenticationProvider": null,
      "userArn": null,
      "userAgent": "Custom User Agent String",
      "user": null
    },
    "path": "/prod/path/to/resource",
    "resourcePath": "/{proxy+}",
    "httpMethod": "POST",
    "apiId": "1234567890",
    "protocol": "HTTP/1.1"
  }
}

Response:

{
  "errorMessage": "'dict' object has no attribute 'encode'",
  "errorType": "AttributeError",
  "stackTrace": [
    "  File \"/var/task/mangum/adapter.py\", line 173, in __call__\n    body = body.encode()\n"
  ]
}

What causes the error?

mangum/blob/main/mangum/adapter.py line 150

            is_binary = event.get("isBase64Encoded", False)
            initial_body = event.get("body") or b""
            if is_binary:
                initial_body = base64.b64decode(initial_body)
            elif not isinstance(initial_body, bytes):
                initial_body = initial_body.encode()

            http_cycle = HTTPCycle(scope, text_mime_types=self.text_mime_types)
            response = http_cycle(self.app, initial_body)
jordaneremieff commented 3 years ago

@akhtariali can you confirm the version of Mangum you are using?

HumanRupert commented 3 years ago

@jordaneremieff 0.10.0

I updated the API to only receive encoded parameters and then decode them to dictionaries. But I'm not sure if it's a proper solution.

The part of code that appears to be problematic is present since the first commit on adapter.py. See: https://github.com/jordaneremieff/mangum/blob/96bb9a8b359139f77dea7d4ab25e8c980e13f312/mangum/adapter.py#L252

HumanRupert commented 3 years ago

When I make requests from Postman, it works fine. When I use the test function in the AWS Lambda dashboard, it gives me this error. I send the data as raw JSON in Postman.

jordaneremieff commented 3 years ago

@akhtariali this is expected behavior when invoking requests directly using Lambda Proxy integration in the AWS Lambda test console, but when using Postman the API Gateway integration is handling the request so it does not run into this issue.

In the AWS test console, you would have to use an escaped JSON string for the body like this:

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