3

我在 Google Apps Script 中创建了函数,当我在 Google Apps Script 中运行它时效果很好。输出数据返回到 Google 表格。

function testFunction11() {
  var rng = SpreadsheetApp.getActiveRange();
  var encodedAuthInformation = Utilities.base64Encode("username:key");
  var headers = {"Authorization" : "Basic " + encodedAuthInformation};
  var params = {
    'method': 'GET',
    'muteHttpExceptions': true,
    'headers': headers
  };
  var res = UrlFetchApp.fetch("https://api.apiservice.com/api/v1/xxx?fields=somefields", params);
  Logger.log(res.getContentText());
  rng.setValue(res);
}

单元格中的输出:

[
  {
    "id": xxx,
    "createdDate": "2019-02-01T04:54:00Z",
    "reference": "XXX"
  },
etc

然后我将脚本分配给按钮“testFunction11”。当我单击按钮时,它会返回

{
  "message": "An error has occurred."
}

它看起来像来自 API 服务器的响应。

我唯一的假设是谷歌工作表的按钮添加了一些标题、用户代理或内容类型来请求,这在 API 服务器中是不允许的。经过一番搜索,我想我无法在请求中重新分配用户代理。这是对的还是我做错了?

编辑1:

每个案例的标题console.log(UrlFetchApp.getRequest(url, params)):单击电子表格中的按钮时:

{headers={Authorization=Basic XXXXXXXXQVU6MWVhODlmZmFkN2U3NGNjOGJkOTc1YTE1ZjVhNTE3MzE=, X-Forwarded-For=178.xx.my.ip}, method=get, payload=, followRedirects=true, validateHttpsCertificates=true, useIntranet=false, contentType=null, url=https://api.apisite.com/api/v1/SalesOrders?fields=Id,Createddate,Reference&where=Createddate%3E2019-02-01T00:00:00Z}

对于脚本:

{headers={Authorization=Basic XXXXXXXXQVU6MWVhODlmZmFkN2U3NGNjOGJkOTc1YTE1ZjVhNTE3MzE=}, method=get, payload=, followRedirects=true, validateHttpsCertificates=true, useIntranet=false, contentType=null, url=https://api.apisite.com/api/v1/SalesOrders?fields=Id,Createddate,Reference&where=Createddate%3E2019-02-01T00:00:00Z}

所以按钮只添加X-Forwarded-For.

当我尝试手动添加X-Forwarded-For: 'unknown'时出现这样的错误

There are attribute with impossible value: Header:X-Forwarded-For

俄语中的错误文本,很抱歉可能翻译不准确。这很有趣,因为当我Test: unknown以同样的方式添加时,没有错误,但显然不起作用。看起来谷歌不允许更改此值。

将在邮递员中尝试不同的标头,并可能确认此标头是错误的原因。谢谢@TheMaster

编辑2:

我通过邮递员尝试了不同的标题。因此,结果是当我添加任何值的标题X-Forwarded-For键时,它会返回"message": "An error has occurred." 当我不添加此键时,它运行良好。

因此,问题是通过 Google Apps 脚本禁用添加此标头的任何方法。好像没有。

4

2 回答 2

5
  • 在您的情况下,当UrlFetchApp.fetch()从电子表格上的按钮运行时,X-Forwarded-For会自动添加到标题中。
  • 通过添加X-Forwarded-For到标题中,An error has occurred.会发生错误。
  • 另一方面,X-Forwarded-For不使用在标头中,不会发生错误。

如果我的理解是正确的,这个解决方法怎么样?我认为可能有几种解决方法。所以请认为这只是其中之一。在此解决方法中,Web 应用程序用作包装函数。

示例脚本:

首先,请复制并粘贴以下脚本。请设置testFunction11()为按钮。testFunction11()运行时,向testFunction11()Web 应用程序 ( doGet()) 发出请求,而 Web 应用程序向https://api.apiservice.com/api/v1/xxx?fields=somefields. 这样,X-Forwarded-For不用于请求的标头。然后,返回 Web Apps 的结果并将值放入电子表格。请在运行脚本之前部署 Web 应用程序。

function testFunction11() {
  var rng = SpreadsheetApp.getActiveRange();
  var url = ScriptApp.getService().getUrl();
  var params = {method: "get", headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()}};
  var res = UrlFetchApp.fetch(url, params);
  Logger.log(res.getContentText());
  rng.setValue(res);
}

function doGet() {
  var url = "https://api.apiservice.com/api/v1/xxx?fields=somefields";
  var encodedAuthInformation = Utilities.base64Encode("username:key");
  var headers = {"Authorization" : "Basic " + encodedAuthInformation};
  var params = {
    'method': 'GET',
    'muteHttpExceptions': true,
    'headers': headers
  };
  var res = UrlFetchApp.fetch(url, params);
  return ContentService.createTextOutput(res.getContentText());
}

部署 Web 应用程序:

在运行此脚本之前,请部署 Web 应用程序。

  • 在脚本编辑器上
  • 发布 -> 部署为 Web 应用程序
    1. 创建新的项目版本
    2. 在“执行应用程序”中,选择“我”
    3. 在“谁有权访问该应用程序”中,
      • 如果该功能仅由您使用,请选择“仅我自己”。
      • 如果该功能被多个用户使用,请选择“任何人”。
    4. 点击“部署”
    5. 复制“当前网络应用 URL”
    6. 点击“确定”

笔记:

  • 当您修改脚本时,请将 Web 应用程序重新部署为新版本。这样,最新的脚本就会反映到 Web 应用程序中。这是很重要的一点。
  • 这是一个简单的示例脚本。所以请根据您的情况进行修改。

参考:

于 2019-02-10T23:55:29.647 回答
1

对于此主题的未来搜索:我遇到了完全相同的错误消息的问题,我将UrlFetchApp#getRequest其用作实用程序来生成请求对象,然后使用UrlFetchApp#fetchAll.

解决方案是避免使用getRequest,而是在不使用任何X-Forwarded-Forheader的情况下自行构建请求,从而使请求成功完成。

我找不到任何文档来支持这一点,但我推测发生了以下问题:当 GoogleX-Forwarded-For在发出请求之前注入标头时,它注入的 IP 取决于脚本在其中执行的上下文。我认为 Google 验证了这一点如果该标头是手动设置的,那么 IP 地址需要匹配他们的 GAS 代理的 IP 或用户的浏览器 IP;使用哪一个似乎会根据脚本执行的上下文而改变。

于 2020-06-17T20:41:34.487 回答