TL;DR: I am getting a CORS error when Unity WebRequest reaches out to a google sheets script through WebGL
I am currently working on a project that involves several moving pieces: Unity (WebGL), ExpressJs, and Google Sheets Script. The purpose of the project is to create an online museum that displays artworks that are managed through a google sheet.
The google sheet has google script attached to it that coverts the sheet into an online JSON for Unity to access. Then, Unity is added to a Heroku site through WebGL.
The Unity project works perfectly in the editor. My problem is that I get a CORS error when attempting to access it through WebGL. Originally, I got a CORS Access-Control-Allow-Headers error, but after attaching some headers to it (see below), the error changed to "Access to fetch at '[google sheet script url]' from origin '[website url]' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
With apologies, I'm including more code than I'd like to, but I'm not sure where the problem lies so I'm not sure what to exclude. The code in relation to the error is the following:
code from Unity (C#):
IEnumerator ObtainSheetData()
{
//access the online JSON
UnityWebRequest www = UnityWebRequest.Get("[google sheet script]");
www.SetRequestHeader("Access-Control-Allow-Credentials", "true");
www.SetRequestHeader("Access-Control-Allow-Headers", "Accept, X-Access-Token, X-Application-Name, X-Request-Sent-Time");
www.SetRequestHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
www.SetRequestHeader("Access-Control-Allow-Origin", "[domain]");
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError) {
Debug.Log("ERROR: " + www.error);
}
else {
// handle the JSON
string json = www.downloadHandler.text;
o = JSON.Parse(json);
foreach (var item in o) {
var itemo = JSON.Parse(item.ToString());
maxID = itemo[0]["ID"];
}
}
}
code from NodeJS side code from app.js script:
var app = express();
var originsWhitelist = [
'http://localhost:3101',
'https://langenheim-a07134ab155c.herokuapp.com' // website origin
];
var corsOptions = {
origin: function(origin, callback){
console.log(origin);
var isWhitelisted = originsWhitelist.indexOf(origin) !== -1;
console.log(isWhitelisted);
callback(null, isWhitelisted);
},
credentials:true
}
app.use(cors(corsOptions))
code from LoadUnity.js (router to the hbs portion):
router.get('/', async function(req, res, next) {
await doc.useServiceAccountAuth({
client_email: CREDENTIALS.client_email,
private_key: CREDENTIALS.private_key
});
res.header("Access-Control-Allow-Origin", "[domain]");
res.header("Access-Control-Allow-Headers", "*");
res.render('loadUnity', { title: 'The Langenheim',
layout: 'layout'});
});
code from LoadUnity.hbs:
<!DOCTYPE html>
<html lang="en-us">
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="[domain]" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
... (rest of default WebGL index.html)
I am not sure whether or not the google script code is relevant, but here it is regardless:
function doGet(e) {
var sheet = SpreadsheetApp.getActive();
var form = sheet.getSheetByName("Form responses 2");
var data=[];
var rlen=form.getLastRow();
var clen=form.getLastColumn();
var rows=form.getRange(1,1,rlen,clen).getValues();
for(var i=1; i<rows.length; i++) {
var datarow=rows[i];
var record={};
for(var j = 0; j<clen; j++) {
record[rows[0][j]] = datarow[j];
}
data.push(record);
}
console.log(data);
var result=JSON.stringify(data);
return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);
}
I tried adding headers, and it didn't remove the CORS errors. I also specified the domain and it has not worked.