I have a very simple webpage, that only has a button which should submit the POST below to my google app scripts code. When testing, I click the button to run the SendTest() function and get the following error in the console:
Access to fetch at 'https://script.google.com/macros/s/[redacted]/exec' from origin 'http://127.0.0.1:5500' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
On the Network tab, I see the OPTIONS request, but it returns a 405 Method Not Allowed error. I have tried manually adding the header with no luck.
Any point in the right direction would be greatly appreciated.
Simplified HTML / JS Code:
<!DOCTYPE html>
<button onclick="sendTest()">Send Test POST</button>
<script>
async function sendTest() {
try {
const payload = {
responses: [
{ category: 'Test', question: 'Q?', recommendation: 'Do X' }
]
};
console.log('Sending:', JSON.stringify(payload));
const response = await fetch('https://script.google.com/macros/s/[redacted]/exec', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload),
mode: 'cors',
credentials: 'omit'
});
console.log('Response status:', response.status);
console.log('Response headers:', [...response.headers.entries()]);
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP error! Status: ${response.status}, Details: ${errorText}`);
}
const result = await response.json();
console.log('Response:', result);
} catch (error) {
console.error('Fetch error:', error);
}
}
Google App Script Code:
function doGet(e) {
var output = JSON.stringify({
status: 'success',
message: 'It worked',
});
return ContentService.createTextOutput(output)
.setMimeType(ContentService.MimeType.JSON);
}
function doPost(e) {
return ContentService.createTextOutput(JSON.stringify({status: "success", "data": "my-data"})).setMimeType(ContentService.MimeType.JSON);
}
function doOptions(e) {
const output = ContentService.createTextOutput('');
output.setMimeType(ContentService.MimeType.TEXT);
output.addHeader('Access-Control-Allow-Origin', '*');
output.addHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
output.addHeader('Access-Control-Allow-Headers', 'Content-Type');
return output;
}
In your script, please modify Javascript as follows.
const response = await fetch('https://script.google.com/macros/s/[redacted]/exec', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload),
mode: 'cors',
credentials: 'omit'
});
const response = await fetch('https://script.google.com/macros/s/[redacted]/exec', {
method: 'POST',
body: JSON.stringify(payload),
});
or
const response = await fetch('https://script.google.com/macros/s/[redacted]/exec', {
method: 'POST',
body: JSON.stringify(payload),
headers: { "Content-Type": "text/plain" }
});
In your showing script, it seems that Web Apps is used. When you modify the Google Apps Script of Web Apps, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful about this.
You can see the details of this in my report "Redeploying Web Apps without Changing URL of Web Apps (Author: me)".