Reputation: 13910
Whenever I try to access serverless lambda function via POST through the browser I get the error
Response to preflight request doesn't pass access control check: No >'Access-Control-Allow-Origin' header is present on the requested resource.
When it is a /GET
it works fine I have read it is because it is not sending pre flight request. When I change it to POST
this is when it fails.
The command I am running:
sam local start-api
And my template.yaml is:
...
Resources:
PropertiesFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: target/service-0.0.1-SNAPSHOT.jar
Handler: com.aws.PropertiesHandler::handleRequest
Runtime: java8
Events:
PropertiesApi:
Type: Api
Properties:
Path: /properties
Method: post
...
How can I enable CORS on these endpoints?
Upvotes: 10
Views: 10835
Reputation: 2834
Bit late to the party, but I've been struggling with this and found a solution. Hopefully will help someone else as well. I didn't want to polute my lambda code with additional, unsafe headers so looked into doing it within SAM.
I only use SAM for local development, not for deployment so this solution might not be for everyone as it requires changes to the template.
The solution to this is to use HttpApi
in the SAM template instead of 'Api
. I've added the following to the Globals
section:
Globals:
HttpApi:
CorsConfiguration:
AllowHeaders:
- Content-Type
- Authorization
- Access-Control-Allow-Origin
AllowMethods:
- '*'
AllowOrigins:
- '*'
And then changed the Function
resource to the HttpApi
type:
MyFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: api/
Handler: management.createHandler
Runtime: nodejs20.x
Architectures:
- x86_64
Events:
HelloWorld:
Type: HttpApi <-- Change here
Properties:
Path: /announcement
Method: post
And now all responses when local start-api
return the CORS headers.
One odd thing, I have many Functions defined in the template but I only had to change the Type
on one of them to make the headers work for all.
Upvotes: 0
Reputation: 11
Try this on your serverless template file if you are using SAM
"Globals": {
"Api": {
"Cors": {
"AllowMethods": "'POST, GET, PUT, DELETE'",
"AllowHeaders": "'content-type'",
"AllowOrigin": "'*'"
}
}
}
Upvotes: 0
Reputation: 141
I had the same error and I have already fixed it in 3 steps. (AWS Lambda in Java8, SAM CLI v0.37.0)
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("X-Custom-Header", "application/json");
headers.put("Access-Control-Allow-Origin", "*");
headers.put("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
headers.put("Access-Control-Allow-Headers", "X-Requested-With,content-type");
Globals:
Function:
Timeout: 20
Api:
Cors:
AllowMethods: "'GET,POST,OPTIONS'"
AllowHeaders: "'content-type'"
AllowOrigin: "'*'"
AllowCredentials: "'*'"
Events:
HelloWorld:
Type: Api
Properties:
# Path: /hello
# Method: get
Path: "/{proxy+}"
Method: ANY
Upvotes: 13
Reputation: 886
First, you will need to add the following section in the template.yml to enable cors in the API gateway:
Globals:
Api:
Cors:
AllowMethods: "'GET,POST,OPTIONS'"
AllowHeaders: "'content-type'"
AllowOrigin: "'*'"
AllowCredentials: "'*'"
Then in your lambda function response
MultivaluedMap<String, Object> headers = responseContext.getHeaders();
headers.add("Access-Control-Allow-Origin", "*");
headers.add("Access-Control-Allow-Headers", requestContext.getHeaderString("Access-Control-Request-Headers"));
headers.add("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,HEAD,OPTIONS");
Upvotes: 6
Reputation: 41
You should be able to get around this for local testing by explicitly adding the following headers to your response, in your handler function:
"Access-Control-Allow-Origin": "*"
You can use an environment variable that only adds the headers if you're running locally.
Here's a simple Python example from a handler function I have:
if not all(field in values for field in required_fields):
response = {
'statusCode': 400,
'body': json.dumps(
{
'message': 'Required data missing from request body'
}
)
}
# explicitly add CORs headers for local testing
response['headers'] = {"Access-Control-Allow-Origin": "*"}
return response
This is only suitable for local testing, when you deploy to an API Gateway CORs is handled by configuration on the API Gateway.
This solution worked for me until I also added authorization to the API, with a Cognito user pool, which I'm currently trying to work through.
Here's a similar post on the issue: How to Enable CORS for an AWS API Gateway Resource
Here's reference to it in the official AWS documentation.
Upvotes: 4