javascriptpostgoogle-apps-script

Google App Script Web App GET and POST request blocked by CORS policy


I created a Google Web script app that adds a user's name and email to a spreadsheet. This works fine when accessing the web page from directly in the browser, but both GET and POST requests from a website returns the error "Access to fetch at 'https://script.google.com/macros/s/AKfycbxkG5hM6MMswwHdzWSJKwutMYsOZRT3zjC7jFti0sDvJ47bWB4BTsHPhvbyEVGSsSc5/exec' from origin '' has been blocked by CORS policy: 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."

I don't necessarily need a response from the POST request, but using 'no-cors' doesn't actually update the spreadsheet (I tested to make sure it worked outside of website)

I've used both XMLHttpRequest and the fetch method, with both GET and POST requests and a variety of the settings changed to try to get this to work but no luck so far.

I've tried to modify settings in the Google Apps Script Project (Set to execute as me, anyone can access even anonymous) and the manifest (not much here, documentation reference).

I've looked at these stack overflow posts to try to help, but their solution didn't work for me (any didn't exactly apply to my situation)

App Script sends 405 response when trying to send a POST request

Google Apps Script cross-domain requests stopped working

Here's my fetch method (most recent attempt)

fetch("https://script.google.com/macros/s/AKfycbxkG5hM6MMswwHdzWSJKwutMYsOZRT3zjC7jFti0sDvJ47bWB4BTsHPhvbyEVGSsSc5/exec", {
    method: 'POST',
    data: data,
    mode: 'cors',
    credentials: 'include', // include, *same-origin, omit
    redirect: 'follow',
    headers: {
        'Content-Type': 'text/plain;charset=utf-8',
    }
}).then(response => {
    console.log("success:", response);
});

Right now the server should return a string that says "Success" but instead I get the error I mentioned before.

Edit I forgot to include the doGet and doPost methods on the Google App Script:


var emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

function doPost (e){
  if(!e) return ContentService.createTextOutput("No e");
  if(!e.parameters) return ContentService.createTextOutput("No params");
  if(!e.parameters.email) return ContentService.createTextOutput("No email");
  if(!e.parameters.name) return ContentService.createTextOutput("No name");
  if(!emailRegex.test(e.parameters.email)) return ContentService.createTextOutput("Wrong email format"); // if the email is not in proper format, return

  return addToDoc(e.parameters);
}

function doGet (e){

  if(!e) return ContentService.createTextOutput("No e");
  if(!e.parameters) return ContentService.createTextOutput("No params");
  if(!e.parameters.email) return ContentService.createTextOutput("No email");
  if(!e.parameters.name) return ContentService.createTextOutput("No name");
  if(!emailRegex.test(e.parameters.email)) return ContentService.createTextOutput("Wrong email format"); // if the email is not in proper format, return

  return addToDoc(e.parameters);
}

function addToDoc (params){
  var email = params.email;
  var name = params.name;

  var sheet = SpreadsheetApp.openById("1X0sUNSFcv-phGbGy7jeo9K5WLEX5cxyh_1_X6kSPjPs").getSheets()[0];

  var dataRange = sheet.getDataRange();
  var values = dataRange.getValues();

  // If we already have the email in the system, return
  for(var x = 0; x < values.length; x++){
    for(var y = 0; y < values[x].length; y++){
      if(values[x][y].indexOf(email) > -1) return ContentService.createTextOutput("Already have email");
    }
  }

  // Gets current row index and updates
  var scriptProps = PropertiesService.getScriptProperties();
  var nextDataIndex = parseInt(scriptProps.getProperty("NEXT_DATA_INDEX"));
  scriptProps.setProperty("NEXT_DATA_INDEX", ""+(nextDataIndex+1));

  var insertRange = sheet.getRange(nextDataIndex, 1, 1, 2);
  insertRange.setValues([[name, email]]);

  return ContentService.createTextOutput("Success");
}

Solution

So it turns out my doPost request was failing (doGet was working) because I was using e.parameters and not e.postData. When I got the error message I assumed it was a problem with my website, not the web app.

Thank you Tanaike! I would've spent forever trying to fix the website


Solution

  • Although I'm not sure about your Google Apps Script of Web Apps from your question, how about this modification?

    Modification points:

    1. I think that your Web Apps might return no values. You can put return ContentService.createTextOutput() in the functions of doPost() and doGet(). By this, at Google Apps Script, the status 200 is returned.

      function doPost(e) { // or doGet(e)
      
        // do something
      
        return ContentService.createTextOutput(); // Please add this.
      }
      
    2. You can modify the client-side script as follows:

      fetch("https://script.google.com/macros/s/AKfycbxkG5hM6MMswwHdzWSJKwutMYsOZRT3zjC7jFti0sDvJ47bWB4BTsHPhvbyEVGSsSc5/exec", {
          method: 'POST',
          body: data,
          headers: {
              'Content-Type': 'text/plain;charset=utf-8',
          }
      }).then(response => {
          console.log("success:", response);
      }).catch(err => {
          console.log("Error:" + err);
      });
      

    Note:

    References:

    If I misunderstood your question and this was not the result you want, I apologize.