I have a simple HTML form that needs to submit to a Google script (which is attached to a Google Sheet)
In the past, I was able to submit the form as an "action" on the HTML element with no issues whatsoever.
<form class="gform"
method="POST"
action="https://script.google.com/a/...OxsinJpM.../exec"
autocomplete="off"
>
However, now I am trying to post the data to the same script using a JavaScript function - as we need to do some additional data verification & error handling:
function submitButtonHandler() {
console.log("Submit Handler")
axios({
method: 'post',
url: 'https://script.google.com/a/...NdEccO.../exec',
data: $('form').serialize(),
headers: {
'Content-Type': 'text/plain',
},
}).then((response) => {
console.log("Submitted", response);
})
}
However, trying to do it this way produces a CORS error in the console:
Examining the request in the network tab looks like this:
I already know about the "simple request" provision (this) which will avoid preflight checks - so I've tried setting the Content-Type
header to application/x-www-form-urlencoded
and text/plain
I've tried both Axios and AJAX to make the request - no difference.
I've dealt with CORS issues before, however I usually have control over the server so I can just set the Access-Control-Allow-Origin: *
server-side. Since this is a Google script, I don't have the ability to do this.
I know it's possible to POST this data to the script, as I can do it with the form action. It must also be possible in JavaScript.. but how?
I've even tried re-deploying Google script with a new version, to rule out any kind of temporary bug, but this didn't work.
EDIT: Not a duplicate of How do I authorize an app script in a web interface?. My apps script is wrapped in a try/catch block, but it's as if the request doesn't even leave the browser - no error is caught anywhere:
function doPost(e) {
try {
Logger.log(e);
record_data(e);
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(e.parameters) }))
.setMimeType(ContentService.MimeType.JSON);
} catch(error) { // if error return this
Logger.log(error);
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": error}))
.setMimeType(ContentService.MimeType.JSON);
}
}
Note: After much testing, I WAS able to get this work by deploying my Google Script as a API Executable instead, and using the gapi.client.request
function to make the request.
HOWEVER, this introduced another problem, as deploying as an API Executable does not permit you to "Execute the app as", like when deployed as a Web App. This is no good for our use case, as we can't grant all users access to the associated Google Sheet, yet we still need the ability for them to POST to the app.
Currently, I am attempting to form the request using XMLHttpRequest
, as per this documentation
Thus, the code that makes my query is as follows:
const serializedData = $('form').serialize();
const user = gapi.auth2.getAuthInstance().currentUser.get();
const oauthToken = user.getAuthResponse(true).access_token;
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://script.google.com/a/t....com/macros/s/AK...Ki/exec');
xhr.setRequestHeader('Authorization',
'Bearer ' + oauthToken);
xhr.send(serializedData);
However, it still does not work with the exact same CORS error.
Has this even been done before using Google Scripts?
Is it impossible to POST to a Google script (deployed as Web App) as an authenticated user? If so, why does a form submit action work?