Resolve CORS with AWS Lambda Proxy

  • Post author:
  • Post category:AWS
A meme depicting the emotions of a front-end developer when they first encounter a CORS error from the API.
CORS is the pain that every developer will feel at some point. Image by KCGD_r.

Introduction

CORS is a policy handled by the front-end web browser that prevents a browser from making cross-origin requests. This helps protect the user (and server) from requests outside of the origin. Whenever we make an API call to an origin outside of our own, for example calling api.mytestwebsite.com from mytestwebsite2.com with the default server configuration would return an error because of the cross-origin request.

When setting up a Lambda through an API gateway, we can receive CORS errors as well. This can occur when our API gateway is routing through a Lambda Proxy to a different domain. If you are reading this, then you’ve already experienced the following scenario:

  1. You built your endpoint using a Lambda and deployed it.
  2. If you used the Serverless Application Model (SAM), then an API gateway will have already been created for you.
  3. You add a domain to the endpoint, and you tested it in Postman.
  4. As soon as you call the API from a different domain, you see the dreaded error
CORS Error as seen in dev console.

The Solution

If you are a front-end developer who was just hoping to spin up an API endpoint quickly, this is not exactly what you wanted to see. In order to resolve this, we need to do two things for our deployed API gateway – Add an OPTIONS resource and update our Lambda proxy to return response headers.

The OPTIONS Resource

If you are using a default hello word template, your OPTIONS resource may not have been automatically setup in your API gateway. Without one, all requests coming from an origin outside of the API’s domain will be blocked by default. The easiest way to resolve this problem is to use the Enable CORS on the / method in your API gateway.

You can access this by going to API Gateway in your AWS Console, choosing your API, clicking on Resources, then clicking on Actions -> Enable CORS. You should be presented with the following screen:

Because the Lambda created by SAM is a Lambda Proxy, we can uncheck the box for POST. Clicking on Enable CORS and replace existing CORS headers should generate us an OPTIONS. Note: In the screenshot above, I have already generated an OPTIONS previously. Don’t forget to Deploy API after you have enabled CORS. Once this has been generated and deployed without errors, the next step is to enable CORS on our Lambda.

Add CORS to Lambda Proxy

With the OPTIONS generated, we are halfway there. At this point, you may see some very odd behavior where you Lambda can be called, but you receive an error because the response is missing the correct CORS headers. This is occurring because our Lambda must also return the correct headers for our API response. Fortunately, this is the easy part.

If you are using the Hello World template, a response variable will have already been created for you at the top of your Lambda. It would look something like:

let response;

We need to update this to declare it as an object and then assign our headers to it. Note: the following code will assign our headers to ALL responses using this response object.

let response = {};
response.headers = {
    "X-Requested-With": '*',
    "Access-Control-Allow-Headers": 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with',
    "Access-Control-Allow-Origin": '*',
    "Access-Control-Allow-Methods": 'POST,GET,OPTIONS'
};

We declare response as an object and add a headers key. At this point, feel free to configure your headers to match the endpoints in your lambda proxy. The most important here being the Access-Control-Allow-Origin header. Currently, this is set to ‘*’ which allows any origin.

The final step that we need to fix this is to include our headers within our response before we send it. We can use the spread operator to append our headers to our response object:

response = {
  ...response, 
  'statusCode': 200,
  'body': JSON.stringify({
    message: "Success",
   })
};

return response;

By using the spread operator above, it will append the headers key to this response, and your CORS errors should be resolved once you build/deploy the Lambda.

Conclusion

Enabling OPTIONS and updating your Lambda proxy might seem common sense for a back-end developer, but I personally had trouble figuring out that I needed to make the changes in two different areas as well. Hopefully, after making it this far, you have resolved the CORS error with your API endpoint and can get back to developing an awesome front-end application!