You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Google Apps Script Web App POST请求桌面正常,移动端Chrome遇CORS拦截

解决Google Apps Script Web App移动端POST请求CORS拦截问题

问题背景

我通过Google Apps Script Web App接收外部自定义HTML表单的数据,桌面端Chrome和Safari请求正常,但移动端Chrome会被CORS错误拦截。已尝试:

  • Content-Type设为text/plain;charset=utf-8避免预检请求
  • Web App部署为「任何人」可访问
  • 设置mode: "no-cors"但无法读取响应

相关代码如下:

Code.gs 代码

function doGet() {
  return HtmlService.createHtmlOutput("Web App Ready");
}

function doPost(e) {
  try {
    const payload = JSON.parse(e.postData.contents);

    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("FormData");
    if (!sheet) throw new Error("Sheet 'FormData' not found");

    const timestamp = new Date();
    payload.entries.forEach(entry => {
      sheet.appendRow([
        payload.entity,
        payload.section,
        payload.month,
        payload.week,
        entry.event,
        entry.cow,
        entry.quantity,
        timestamp
      ]);
    });

    return ContentService
      .createTextOutput(JSON.stringify({ success: true }))
      .setMimeType(ContentService.MimeType.JSON);

  } catch (err) {
    return ContentService
      .createTextOutput(JSON.stringify({ success: false, error: err.message }))
      .setMimeType(ContentService.MimeType.JSON);
  }
}

前端fetch请求代码

fetch("https://script.google.com/macros/s/AKfycbzF3vn9IR4J6ZznIwgP_oTfIyhN44u9PNVYFOWXW1jJeEDvkO03VZboGO0uHbRsEfBYgQ/exec", {
  method: "POST",
  headers: {
    "Content-Type": "text/plain;charset=utf-8"
  },
  body: JSON.stringify(meta),
  redirect: "follow"
})
.then(() => {
  alert("✅ Data submitted to Google Sheet!");
})
.catch(err => {
  console.error("❌ Network error:", err);
  alert("❌ Submission failed: " + err.message);
});

可行解决方案

1. 手动添加CORS响应头到Web App

Google Apps Script Web App默认的CORS头配置在移动端可能存在兼容问题,需要手动指定Access-Control-Allow-Origin头。修改doPost的返回逻辑:

// 成功响应
return ContentService
  .createTextOutput(JSON.stringify({ success: true }))
  .setMimeType(ContentService.MimeType.JSON)
  .setHeaders({
    "Access-Control-Allow-Origin": "*", // 允许所有域,也可以指定你的前端域名
    "Access-Control-Allow-Methods": "POST",
    "Access-Control-Allow-Headers": "Content-Type"
  });

// 错误响应同理
return ContentService
  .createTextOutput(JSON.stringify({ success: false, error: err.message }))
  .setMimeType(ContentService.MimeType.JSON)
  .setHeaders({
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "POST",
    "Access-Control-Allow-Headers": "Content-Type"
  });

注意:部署Web App时要重新发布新版本,否则修改不会生效。

2. 优化前端fetch请求配置

移动端Chrome对请求凭证和重定向的处理更严格,调整fetch参数:

fetch("https://script.google.com/macros/s/AKfycbzF3vn9IR4J6ZznIwgP_oTfIyhN44u9PNVYFOWXW1jJeEDvkO03VZboGO0uHbRsEfBYgQ/exec", {
  method: "POST",
  headers: {
    "Content-Type": "text/plain;charset=utf-8"
  },
  body: JSON.stringify(meta),
  redirect: "manual", // 避免移动端自动重定向触发CORS问题
  credentials: "omit", // 明确不发送凭证,减少预检触发概率
  mode: "cors" // 显式指定cors模式
})
.then(response => {
  if (!response.ok) throw new Error("Server responded with error");
  return response.json();
})
.then(data => {
  if (data.success) {
    alert("✅ Data submitted to Google Sheet!");
  } else {
    alert("❌ Submission failed: " + data.error);
  }
})
.catch(err => {
  console.error("❌ Network error:", err);
  alert("❌ Submission failed: " + err.message);
});

3. 备选方案:改用Google Forms作为数据中转

如果Web App的CORS问题始终无法解决,可以创建一个隐藏的Google Form,将表单的提交端点作为前端请求目标,数据会自动同步到关联的Google Sheet。这种方式完全避开CORS问题,因为Google Forms的端点支持跨域请求。

关键注意事项

  • 修改Web App代码后,必须重新发布新版本(部署时选择「新版本」,不要选择「测试部署」)
  • 尽量指定具体的Access-Control-Allow-Origin值(比如你的前端域名),而非通配符*,提升安全性
  • 移动端测试时,确保浏览器没有缓存旧的请求配置,可以开启无痕模式测试

内容的提问来源于stack exchange,提问作者Linus Lüdecke

火山引擎 最新活动