If you don't know what is CORS - in short, by default, if you are on the http://website.com this website can only make requests to that website. In order to make a request to http://otherwebsite.com, first website has to set CORS headers in the response. More theory can be found here.
If you are using Serverless the enabling CORS on your endpoints is a straightforward process.
When editing the yaml file just set cors: true
on an http events.
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
cors: true
You could do it manually but Serverless will save you some time and do it automatically during the deployment.
There is one more thing that has to be done for CORS to work. In every λ function you have to specify headers. Just set Access-Control-Allow-Origin
to '*'
to accept requests coming from all domains or 'your-domain-name.com'
for requests coming from one domain.
module.exports.hello = (event, context, c) => {
const response = {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*', // Required for CORS support to work
// try swapping '*' for an environment based variable
},
body: 'hello'
};
c(null, response)
}
Settings cors to true sets the default configuration of Serverless to be:
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
cors:
origin: '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
allowCredentials: false
This lets our lambda serverless function to know that we can safely accept requests from any website ('*'
- means any). If being precise, the browsers regulate this behaviour for security reasons. If you include an AJAX call from youdomain.com
to our lambda function which will reside at domain looking something like this: https://q3o4tjwe0dgj.execute-api.us-east-1.amazonaws.com/dev/hello
then before doing GET
request to this endpoint, the browser will do so called Preflight request
. This is a request of HTTP method OPTIONS
with three HTTP headers: Origin
, Access-Control-Request-Method
and Access-Control-Request-Headers
.
As it is usually handled by the browsers automatically, the developers don't need to handle the logic around it. However, if you are curious, you can do the request to your newly generated lambda endpoint:
OPTIONS https://q3o4tjwe0dgj.execute-api.us-east-1.amazonaws.com/dev/hello
The header results should look like this:
access-control-allow-credentials: false
access-control-allow-headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent
access-control-allow-methods: OPTIONS,GET
access-control-allow-origin: *
which means that two methods are allowed on this endpoint - OPTIONS and GET
The best practice would be to have the same domain for your lambdas and the website you are querying them with. You don't have to set CORS headers in this case.
If your lambdas and the domain you are calling lambdas from are on the different domains, the recommended approach is to set Access-Control-Allow-Origin
header to that domain name. This header supports either one single domain name (can be pattern) or '*'
If you are just using one CloudFormation stack for lambdas (one lambda functions group) and you use one domain name there is another approach.
You can set custom domain name for your API Gateway. Details instruction on how to do it can be found here
Further reading: