33

I'm trying to create a new service using AWS API Gateway, but I found out the browser automatically calls OPTIONS method in order to obtain CORS information.

The problem is that AWS API Gateway does not offer a native way to configure CORS headers.

Is it possible to create a Lambda Script in order to respond to OPTIONS method?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Alessandro Oliveira
  • 2,126
  • 2
  • 17
  • 24
  • Did you take a look at [Enable CORS for a Method in API Gateway](http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html)? Did that not work? – James Aug 10 '15 at 15:29

5 Answers5

54

If you have lambda-proxy enabled, you need to set the CORS headers manually:

module.exports.hello = function(event, context, callback) {

    const response = {
      statusCode: 200,
      headers: {
        "Access-Control-Allow-Origin" : "*", // Required for CORS support to work
        "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS
      },
      body: JSON.stringify({ "message": "Hello World!" })
    };

    callback(null, response);
};

https://serverless.com/framework/docs/providers/aws/events/apigateway#enabling-cors

sqren
  • 22,833
  • 7
  • 52
  • 36
10

If you're using {proxy+} endpoint, you must handle CORS HTTP requests in the Lambda function. The implementation depends on the framework you're using. For Express, the easiest solution is to simply use Express CORS middleware.

If you don't want to handle CORS requests by Lambda, try changing the settings of your Lambda Method to handle CORS on the API Gateway level.

Here's a detailed official tutorial for CORS setup on AWS API Gateway.

It's also critical that you allow header X-Api-Key in Access-Control-Allow-Headers otherwise auth won't work and you'll get errors.

EDIT: In November 2015 the API Gateway team added a new feature to simplify CORS setup.

adamkonrad
  • 6,794
  • 1
  • 34
  • 41
  • 21
    enabling CORS setup in api gateway in the not enough if your api gateway is configured as lambdaproxy – Chandru Oct 26 '16 at 03:25
  • @Chandru I agree, the aws docs says that for proxy setups, the response has to come from the http backend, what should this look for like for node/express? – chrismarx May 07 '18 at 21:06
  • Try creating one `{proxy+}` endpoint and have all the requests forwarded to the Lambda function. – adamkonrad May 07 '18 at 21:14
  • 1
    This answer is not correct as stated above. The one below should be marked. – drogon Nov 28 '18 at 04:55
  • This answer is correct. However Lambda-level configuration is needed for {proxy+} endpoints because all requests are just passed through from API Gateway. – adamkonrad Nov 28 '18 at 05:03
  • @Alisson You should see `{proxy+}` in your API Gateway resource. – adamkonrad May 20 '19 at 13:12
4

Here is a sample, I hope this helps you:

...
    return {
        statusCode: 200,
        headers: {
            "Access-Control-Allow-Headers" : "Content-Type",
            "Access-Control-Allow-Origin": "*", // Allow from anywhere 
            "Access-Control-Allow-Methods": "GET" // Allow only GET request 
        },
        body: JSON.stringify(response)
    }
}

For more information please check this link: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html

Thiago
  • 12,778
  • 14
  • 93
  • 110
2

If you're using JQuery $.ajax, it will send the X-Requested-With with the POST following the OPTIONS request, so you need to make sure when setting up your OPTIONS access-control-accept-headers on AWS API to include that header: X-Requested-With along with the others.

jomamaxx
  • 111
  • 5
  • 1
    where did you discover this? is it documented? how were you able to add the header in the API Gateway resources "Enable CORS" form? – nelsonic Jan 30 '16 at 21:56
0

I have a solution for HTTP API Gateway with ANY method. If you use authorizer on ANY method, your authorizer will reject the OPTIONS request as it doesn't contain an Authorization/Bearer token. Solution is simple: Next to the ANY route, create OPTIONS route with the very same path and no authorizer, pointing to lambda function. Then in lambda, add

const headers = {
    "Content-Type": "application/json",
    "Access-Control-Allow-Origin": "*",
    "Cache-Control": "max-age=0, no-store, must-revalidate",
    Pragma: "no-cache",
    Expires: 0
};
data = {
        multiValueHeaders: {},
        isBase64Encoded: false,
        statusCode: 200,
        headers: headers,
        body: ""
    }
if (event.httpMethod == "OPTIONS") {
    return context.done(undefined, data)
}

This worked for me.

jacoor
  • 760
  • 5
  • 9