如何将具有基本权限的 UrlFetchApp 分配给按钮?

How to assign UrlFetchApp with basic authorization to button?

我在 Google Apps 脚本中创建了函数,当我在 Google Apps 脚本中 运行 它时效果很好。输出数据 returns 到 Google Sheets.

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'。 当我点击按钮时,它 returns

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

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

我唯一的假设是 google sheet 的按钮添加了一些 header , User-Agent 或 content-type 来请求,这是不允许的API 服务器。经过一番搜索,我想我无法在请求中重新分配 User-Agent 。这是对的还是我做错了?

编辑 1:

Headers 每个案例 console.log(UrlFetchApp.getRequest(url, params)): 当点击 spreadsheet 中的按钮时:

{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 时,没有错误,但显然不起作用。看起来 google 不允许更改此值。

将在 postman 中尝试不同的 headers 并可能确认此 header 是错误的原因。谢谢@TheMaster

编辑 2:

我通过 Postman 尝试了不同的 headers。所以,结果是当我用任何值添加到 headers X-Forwarded-For 键时,它 return "message": "An error has occurred." 当我不添加此密钥时,它运行良好。

因此,问题是通过 Google Apps 脚本禁用添加此 header 的任何方式。好像不是。

  • 在您的情况下,当 UrlFetchApp.fetch() 是来自电子表格上的按钮的 运行 时,X-Forwarded-For 会自动添加到 header。
  • X-Forwarded-For添加到header,出现An error has occurred.的错误。
  • 另一方面,X-Forwarded-For 没有在 header 中使用,不会发生错误。

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

示例脚本:

首先,请复制并粘贴以下脚本。请将 testFunction11() 设置为按钮。当 testFunction11() 为 运行 时,testFunction11() 请求网络应用程序 (doGet()),网络应用程序请求 https://api.apiservice.com/api/v1/xxx?fields=somefields。至此,X-Forwarded-For 不用于请求的 header。然后,返回 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 Apps。

  • 在脚本编辑器上
  • 发布 -> 部署为 Web 应用程序
    1. 创建新的项目版本
    2. 在 "Execute the app a" 秒,select "Me"
    3. 在 "Who has access to the app",
      • 如果该功能只有你一个人使用,select "Only myself".
      • 如果该功能被多个用户使用,select "Anyone"。
    4. 点击"Deploy"
    5. 复制"Current web app URL"
    6. 点击"OK"

注:

  • 修改脚本后,请重新部署 Web Apps 为新版本。这样,最新的脚本就会反映到 Web Apps。 这是一个重点。
  • 这是一个简单的示例脚本。所以请根据你的情况修改。

参考文献:

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

解决方案是避免使用 getRequest 而是自己构建请求 而不使用任何 X-Forwarded-For header,这允许请求成功完成。

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