I have a very light application that I am putting up on AWS. An API with PUT and OPTIONS methods that uploads files to S3. The API works correctly when run via POSTMAN, Python requests, and CURL on the cli. However, the moment I try to hit the API via a simple s3 hosted webpage I hit a CORS error. In my console the error is:
Access to XMLHttpRequest at 'https://{endpoint}/v1/test.pdf' from origin 'http://{s3-bucket}.s3-website-us-east-1.amazonaws.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
In cloudwatch, the API key authenticates, and we make it to the method body transformation and get this error:
Execution failed due to configuration error: Unable to transform request
My current attempt to solve CORS is the following…my s3 bucket that hosts the webpage has the following policy:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"PUT",
"POST",
"DELETE"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]
My API has an OPTIONS method with 3 method response headers:
Access-Control-Allow-Headers
Access-Control-Allow-Methods
Access-Control-Allow-Origin
The following 3 integration response header mappings for a 200 response:
method.response.header.Access-Control-Allow-Headers = ‘Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token’
method.response.header.Access-Control-Allow-Methods = ‘DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT’
method.response.header.Access-Control-Allow-Origin = ‘*’
I have the same setup for my PUT method.
Once again, the API is running outside of CORS. The following CURL works:
curl -X PUT "https://{endpoint}.amazonaws.com/v1/test.pdf" -H "Content-Type: application/pdf" -H "x-api-key: {api-key}" --data-binary "@{file-location}test.pdf" -v
In case it happens to be .js related…here is the .js for the s3 hosted webpage:
document.getElementById('uploadForm').addEventListener('submit', function(event) {
event.preventDefault();
const apiKey = document.getElementById('apiKey').value;
const fileInput = document.getElementById('file');
const file = fileInput.files[0];
if (!file) {
alert('Please select a file.');
return;
}
const fileName = encodeURIComponent(file.name);
const endpoint = `https://{endpoint}.execute-api.us-east-1.amazonaws.com/v1/${fileName}`;
const contentType = file.type;
// Perform a preflight request
const preflightXhr = new XMLHttpRequest();
preflightXhr.open('OPTIONS', endpoint, true);
preflightXhr.onload = function() {
if (preflightXhr.status === 200) {
// Proceed with the PUT request after successful preflight
const xhr = new XMLHttpRequest();
xhr.open('PUT', endpoint, true);
xhr.setRequestHeader('Content-Type', contentType);
xhr.setRequestHeader('x-api-key', apiKey);
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
alert('File uploaded successfully!');
} else {
alert('Error uploading file: ' + xhr.responseText);
}
}
};
xhr.onerror = function() {
alert('An error occurred while sending the request.');
};
xhr.send(file);
} else {
alert('CORS preflight request failed: ' + preflightXhr.responseText);
}
};
preflightXhr.onerror = function() {
alert('An error occurred during the CORS preflight request.');
};
preflightXhr.send();
});
Looking for any advice or recommendations. I have tried a good many things and am sure I am missing something.
I have tried changing a lot of the CORS settings in API Gateway and with S3.
Stephen Strosko is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.