简体   繁体   中英

AWS API Gateway Lambda failed with status 200

I'm writing a MicroService and my lambda handler takes JSON in the body of the request and builds a Jinja2 template. My Lambda function is working properly and returns a status code of 200, but when I call the function through my API Gateway I get a 502 response.

def lambda_handler(event, context):
    try:
        file_object = s3.get_object(Bucket= 'bucket_name', Key='object_name')
        file_content = file_object["Body"].read().decode('utf-8')
        template = Template(file_content)
        rendered_template = template.render(resume = request_body)
        # Do some logic to place render in s3 and get path
        response = {
            'statusCode': 200,
            'header': {'Content-Type': 'application/json'},
            'body': 'path to file'
        }
        return response
    except Exception as e:
        print(e)
        raise e

The request body I am using is similar to:

{
  "username": "john-doe",
  "location": "US",
  .
  .
  .
}

The error I am receiving in response is:

{
  "errorMessage": "'str object' has no attribute 'lastName'",
  "errorType": "UndefinedError",
  "stackTrace": [
    "  File \"/var/task/resume_service.py\", line 39, in lambda_handler\n    raise e\n",
    "  File \"/var/task/resume_service.py\", line 25, in lambda_handler\n    generate = template.render(resume=request_body)\n",
    "  File \"/var/task/jinja2/asyncsupport.py\", line 76, in render\n    return original_render(self, *args, **kwargs)\n",
    "  File \"/var/task/jinja2/environment.py\", line 1008, in render\n    return self.environment.handle_exception(exc_info, True)\n",
    "  File \"/var/task/jinja2/environment.py\", line 780, in handle_exception\n    reraise(exc_type, exc_value, tb)\n",
    "  File \"/var/task/jinja2/_compat.py\", line 37, in reraise\n    raise value.with_traceback(tb)\n",
    "  File \"<template>\", line 28, in top-level template code\n",
    "  File \"/var/task/jinja2/environment.py\", line 411, in getitem\n    return obj[argument]\n"
  ]
}

How come the Lambda function succeeds when I call it by itself, but fails when I call it through the API Gateway?

When using API Gateway with Lambda proxy integration, API Gateway expects the data returned from Lambda in a specific format as listed here . You would also need to add the isBase64Encoded flag in the returned response.

{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
    "body": "..."
}

Skimming through the code, it looks like this will only be applicable when the function returns successfully, but in case of any errors, it will raise an exception - which API Gateway doesn't expect; and hence the 502 Malformed proxy.

To get more clarify over this, check what's the difference between both the requests - from the console and from API Gateway. Since we have to set a specific JSON payload to invoke the function from the console (or any invoking service), I would print out the event after the handler to check what's the event structure of API Gateway request, and use that while testing this from the console to see if that still works. I am guessing doing this way, it won't work as the error claims 'str object' has no attribute 'lastName' .

If this works with API Gateway payload from the console, I would check the full request/response logs from API Gateway and Lambda function logs (with event printed) to get more clarity between the two requests.

The problem happened to be with Jinja2. Jinja2 has several creation functions for rendering a template with given parameters.

render([context]): "This method accepts the same arguments as the dict constructor"

generate([context]): "For very large templates it will not render the whole template at once but evaluate each statement after another.

Due to the size of my templates it was unable to render() the entire template, by changing

rendered_template = Template.render(resume = request_body) to: rendered_template = Template.generate(resume = request_body)

the issue is resolved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM