从JavaScript向Google Apps Script POST JSON时遇CORS跨域问题求助
解决Google Apps Script跨域请求(CORS)被拦截的问题
你遇到的核心问题是浏览器的预检OPTIONS请求没有被Google Apps Script正确处理,导致CORS策略拦截了你的POST请求。我来帮你拆解原因和解决方案:
为什么Postman能成功,浏览器却不行?
当浏览器发送带Content-Type: application/json的POST请求时,会先自动发送一个OPTIONS预检请求,用来确认目标服务器是否允许跨域操作。如果服务器没有处理这个OPTIONS请求,或者返回的响应头不符合要求,浏览器就会直接拦截后续的POST请求,抛出你看到的CORS错误。
而Postman这类工具不会触发预检请求,它会直接发送POST请求,所以能成功拿到响应——这也是为什么你在Postman里能看到Access-Control-Allow-Origin: *头,但浏览器根本没机会走到这一步。
你的GAS代码哪里出了问题?
你的doPost函数只处理了POST方法的请求,但完全没处理OPTIONS预检请求。另外,即使POST请求能走到返回步骤,你也没有明确设置CORS相关的响应头,这也会导致浏览器拒绝接收响应。
修改后的服务端代码
首先添加一个专门处理OPTIONS请求的函数,返回浏览器需要的CORS头:
function doOptions(e) { return ContentService.createTextOutput('') .setMimeType(ContentService.MimeType.TEXT) .setHeaders({ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type' }); }
然后修改你的doPost函数,确保返回的响应也带上CORS头,同时把MIME类型调整为更合适的JSON:
function doPost(e){ var postData = JSON.parse(e.postData.contents); let responseContent = "It Works!"; switch (postData.task) { case 'addRecord': const res = addRecord(postData.request); // 建议返回结构化的JSON响应,方便客户端处理 responseContent = JSON.stringify({status: 'success', data: res}); break; default: responseContent = JSON.stringify({status: 'error', message: 'Unknown task type'}); } return ContentService.createTextOutput(responseContent) .setMimeType(ContentService.MimeType.JSON) .setHeaders({ 'Access-Control-Allow-Origin': '*' }); }
为什么这些修改能解决问题?
doOptions函数会响应浏览器的预检请求,明确告诉浏览器:允许所有来源(*)访问,允许POST和OPTIONS方法,允许携带Content-Type头——这样预检就能顺利通过。- 修改后的
doPost返回了Access-Control-Allow-Origin头,确保浏览器接收POST响应时不会因为跨域被拦截;同时把MIME类型设为JSON,和返回的内容格式匹配,避免解析问题。
可选:客户端代码优化(用Fetch API更简洁)
你的原始XMLHttpRequest代码没问题,但用现代的Fetch API会更易读:
const data = JSON.stringify({"task": 'addRecord', "request": {"first_name": "Oliver"}}); fetch("https://script.google.com/macros/s/AKfycbwnOTv_-kFISLa-3S-vkEqZscgrmptlf9nAP6o7O8vQm6exnvg/exec", { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: data }) .then(response => response.json()) .then(result => console.log('请求成功:', result)) .catch(error => console.error('请求失败:', error));
内容的提问来源于stack exchange,提问作者 GhostKU




