javascriptgoogle-apps-scriptweb-applicationscors

Google apps script, web app invokes CORS policy


I've been working on a Website, and wanted to use Google Sheets as my database for some god-aweful reason. In the Google Apps Script, I have a switch statement within the doGet method to get the path info. Like so:

function doGet(e)
{
   let output = "";
   path = e.pathInfo.split("/");
   switch(path[0])
   {
      case "Employees":
         if(path.length > 1)
         {
            output = getEmployeeByName(path[1]);
         }
         else
         {
            output = getAllEmployees();
         }
      break;
      case "Tasks":
         output = getAllTasks();
      break;
   }
   return ContentService.createTextOutput(JSON.stringify(output)).setMimeType(ContentService.MimeType.JSON);
}

Then, in my front end, using React.js, I try to fetch the URL link taken from the deployment.

 try
 {
  fetch(this.url +"/Employees", {
    redirect: "follow",
    method: "GET",
    headers: {
      "Content-Type": "text/plain;charset=utf-8",
    },
  })
 }
 catch (err)
 {
  console.log(err);
  return "Something messed up: ";
 }

And my appsscript.json:

{   "timeZone": "America/Chicago",   "dependencies": {},   "exceptionLogging": "STACKDRIVER",   "runtimeVersion": "V8",   "webapp": {     "executeAs": "USER_DEPLOYING",     "access": "ANYONE_ANONYMOUS"   } }

The problem is that this above call gets blocked by CORS policy, but removing the extra path (And just calling fetch(this.url)) doesn't. The error thrown is

Access to ' (link) ' from origin 'localhost:3000' 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.

I'm not entirely sure how to fix CORS errors, but I can confirm everything else works (Using the url and path in a web browser returns the right data).


Solution

  • I'm guessing for path parameters, you need to be able to login. if trailing path is included, the page redirects to a Google login page, which is the page that requires CORS. Since you're not using the return value of fetch, you can just use mode:'no-cors' to send a one way request.

    Alternatively, if you're logged in the browser, you can also send third party cookies, if the browser allows it by setting credentials to include. If this works, you can get a return value as well.

    https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

     fetch(this.url +"/Employees", {
        redirect: "follow",
        method: "GET",
        mode: "no-cors",
        //or if user is logged in the browser and browser is willing to send third party cookies
        //credentials: "include",
        headers: {
          "Content-Type": "text/plain",
        },
      })
    

    Related: Possible to update one google appscript that affects other google appscript?

    A better way however is to ditch the path parameters and use query parameters instead:

     fetch(this.url +"?p=Employees", {
        redirect: "follow",
        method: "GET",
        headers: {
          "Content-Type": "text/plain",
        },
      })
    

    And on server side,

    function doGet(e)
    {
       let output = "";
       const path = e.parameters.p;
       switch(path[0])
       {
        //the rest of the code...