Google 脚本中带有服务帐户凭据的 UrlFetchApp 会引发 post、put、patch 错误

发布于 2025-01-13 04:07:38 字数 2947 浏览 2 评论 0原文

我有一个私人测试电子表格,已共享到 GAS 项目的服务帐户电子邮件。下面是:

  1. 使用 UrlFetchApp 和服务帐户 oAuth2 凭据从该电子表格“获取”数据的函数。 (获取的范围值:“'sName'!A1:B3”;工作表具有第 1 行列标题:A - “uId”;B - “标题”)。它与共享到服务帐户电子邮件(具有编辑权限)的电子表格配合得很好。如果没有该共享,它会因缺乏授权而失败。因此,oAuth 凭据似乎是正确的,具有电子表格的范围。 (我正在使用 此代码 由 Spencer Easton 生成 oAuth服务帐户的 clientToken。)

  2. 用于更新(发布、放置、修补)同一测试电子表格的函数。所有三种方法都失败,但出现不同的错误消息,如下所示:

Put:“收到无效的 JSON 负载。未知名称“标题”:无法绑定查询参数。在以下位置找不到字段“标题”请求消息。”如果选项中包含 contentType:'application/json',则错误将更改为:“收到无效的 JSON 负载。意外的令牌。\nuId=id3&title=Update\n^” (获取 updateRange 值:“'sName'!A3:B3”或“'sName'!A4:B4”)

Post:“请求的 URL /v4/spreadsheets/[实际 ssId]在此服务器上找不到 /values/'sName'!A4:B4 这就是我们所知道的。”

补丁:与帖子相同,带有 updateRange= "'sName'!A3:B3"

我已经浏览了与这些错误相关的 SO 问答帖子。有人说问题在于选项中包含 contentType(或标题中的 Content-Type:)。这并没有解决问题,但确实使用“put”方法更改了错误消息,如上所述。 Google UrlFetchApp 文档说更新不需要它(因此下面显示为注释掉)。

我希望我只是忽略了使用 UrlFetchApp 正确配置更新范围或选项的一些基本内容。

感谢您提供解决更新问题的指导。

  1. GET DATA -- 正确检索数据
function getData(ssId,range) {
   if (!clientToken) { return "Authorization Failed";}
      var url= `https://sheets.googleapis.com/v4/spreadsheets/${ssId}/values/${range}`
      var options = {
             method:  'get',    
             contentType: 'application/json',
         headers: { Authorization: 'Bearer ' + clientToken }
          };
      response = UrlFetchApp.fetch(url,options);
      return response;
    
 } //end getData function
 var fetchData = getData(ssId,range);
  1. UPDATE DATA -- post、put 和 patch 的错误

更新数据对象: var updateData = {'uId':'id3', 'title':'Update Title'}

function postData(ssId,updateRange,updateData) {
    if (!clientToken) {return "Authorization Failed";}
    var url= `https://sheets.googleapis.com/v4/spreadsheets/${ssId}/values/${updateRange}`
        var options = {
    //           contentType: 'application/json',  
             valueInputOption: 'RAW',
             method:   'put',     //patch, post, or put 
             payload: updateData,     
             headers: { Authorization: 'Bearer ' + clientToken }
             };
     var response= UrlFetchApp.fetch(url,options);
     var responseCode = response.getResponseCode();
     var responseBody = response.getContentText();
    if (responseCode === 200) {
                var responseJson = JSON.parse(responseBody);
                return responseJson; 
      } else {
             Logger.log(Utilities.formatString("Request failed. Expected 200, got %d: %s", responseCode, responseBody))
                 return responseCode;
                 }      
   } //end postData function
 var dataUpdate = postData(ssId,updateRange,updateData);

I have a private test spreadsheet that is shared to the Service Account email for a GAS project. Below is:

  1. A function to "get" data from that spreadsheet using UrlFetchApp with Service Account oAuth2 credentials. (Fetch has Range value: "'sName'!A1:B3"; sheet has Row 1 column headings: A - "uId"; B - "title"). It works fine with the spreadsheet shared (with edit rights) to the Service Account email. It fails for lack of authorization without that share. So, the oAuth credentials seem to be correct, with Scope of spreadsheets. (I'm working with this code by Spencer Easton to generate the oAuth clientToken for the service account.)

  2. A function for updating (post, put, patch) the same test spreadsheet. It fails with all three methods, but with different error messages as follows:

Put: "Invalid JSON payload received. Unknown name "title": Cannot bind query parameter. Field 'title' could not be found in request message." If contentType:'application/json' is included in options, the error changes to: "Invalid JSON payload received. Unexpected token.\nuId=id3&title=Update\n^"
(fetch updateRange value: "'sName'!A3:B3" or "'sName'!A4:B4")

Post: "The requested URL /v4/spreadsheets/[actual ssId]/values/'sName'!A4:B4 was not found on this server. That’s all we know."

Patch: same as Post, with updateRange= "'sName'!A3:B3"

I've gone through SO Q&A postings related to these errors. Some say the problem is including contentType in the options (or Content-Type: in the headers). That didn't fix things, but does change the error message with "put" method, as stated above. Google UrlFetchApp docs say it is not needed for updates (so below it is shown commented out).

I hope I'm just overlooking something basic in properly configuring the range or the options for updates using UrlFetchApp.

Thank you for any guidance in resolving this problem with updating.

  1. GET DATA -- Correctly retrieves data
function getData(ssId,range) {
   if (!clientToken) { return "Authorization Failed";}
      var url= `https://sheets.googleapis.com/v4/spreadsheets/${ssId}/values/${range}`
      var options = {
             method:  'get',    
             contentType: 'application/json',
         headers: { Authorization: 'Bearer ' + clientToken }
          };
      response = UrlFetchApp.fetch(url,options);
      return response;
    
 } //end getData function
 var fetchData = getData(ssId,range);
  1. UPDATE DATA -- errors for post, put and patch

The update data object: var updateData = {'uId':'id3', 'title':'Update Title'}

function postData(ssId,updateRange,updateData) {
    if (!clientToken) {return "Authorization Failed";}
    var url= `https://sheets.googleapis.com/v4/spreadsheets/${ssId}/values/${updateRange}`
        var options = {
    //           contentType: 'application/json',  
             valueInputOption: 'RAW',
             method:   'put',     //patch, post, or put 
             payload: updateData,     
             headers: { Authorization: 'Bearer ' + clientToken }
             };
     var response= UrlFetchApp.fetch(url,options);
     var responseCode = response.getResponseCode();
     var responseBody = response.getContentText();
    if (responseCode === 200) {
                var responseJson = JSON.parse(responseBody);
                return responseJson; 
      } else {
             Logger.log(Utilities.formatString("Request failed. Expected 200, got %d: %s", responseCode, responseBody))
                 return responseCode;
                 }      
   } //end postData function
 var dataUpdate = postData(ssId,updateRange,updateData);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

樱花坊 2025-01-20 04:07:38

不幸的是,我无法确认您想在第二个脚本中使用的方法。但是,从您的端点来看,我猜测您可能想要“方法:电子表格.values.update”。 参考

如果我的理解是正确的,

  • < code>var updateData = {'uId':'id3', 'title':'更新标题'} 不能直接在该方法中使用。
  • UrlFetchApp.fetch() 中没有 valueInputOption 属性。

如果标题行的“A”和“B”列中包含 uIdtitle,并且您希望将 id3 和 < code>Update Title 为 updateRange,下面的修改如何?

来自:

var url= `https://sheets.googleapis.com/v4/spreadsheets/${ssId}/values/${updateRange}`
    var options = {
//           contentType: 'application/json',  
         valueInputOption: 'RAW',
         method:   'put',     //patch, post, or put 
         payload: updateData,     
         headers: { Authorization: 'Bearer ' + clientToken }
         };

至:

// var updateData = [['uId', 'title'], ['id3', 'Update Title']]; // If you want to include the header row, please use this.
var updateData = {values: [['id3', 'Update Title']]};

var url = `https://sheets.googleapis.com/v4/spreadsheets/${ssId}/values/${updateRange}?valueInputOption=RAW`;
var options = {
  contentType: 'application/json',
  method: 'put',
  payload: JSON.stringify(updateData),
  headers: { Authorization: 'Bearer ' + clientToken }
};

注意:

  • 我认为如果您的访问令牌可用于将值放入 Google 电子表格,则此修改后的脚本可以工作。

参考文献:

Unfortunately, I cannot confirm the method you want to use in your 2nd script. But, from your endpoint, I guessed that you might have wanted to "Method: spreadsheets.values.update". Ref

If my understanding is correct,

  • var updateData = {'uId':'id3', 'title':'Update Title'} cannot be directly used in this method.
  • There is not property of valueInputOption in UrlFetchApp.fetch().

If the header row has uId and title in the columns "A" and "B" and you want to put the values of id3 and Update Title to updateRange, how about the following modification?

From:

var url= `https://sheets.googleapis.com/v4/spreadsheets/${ssId}/values/${updateRange}`
    var options = {
//           contentType: 'application/json',  
         valueInputOption: 'RAW',
         method:   'put',     //patch, post, or put 
         payload: updateData,     
         headers: { Authorization: 'Bearer ' + clientToken }
         };

To:

// var updateData = [['uId', 'title'], ['id3', 'Update Title']]; // If you want to include the header row, please use this.
var updateData = {values: [['id3', 'Update Title']]};

var url = `https://sheets.googleapis.com/v4/spreadsheets/${ssId}/values/${updateRange}?valueInputOption=RAW`;
var options = {
  contentType: 'application/json',
  method: 'put',
  payload: JSON.stringify(updateData),
  headers: { Authorization: 'Bearer ' + clientToken }
};

Note:

  • I think that if your access token can be used for putting values to Google Spreadsheet, this modified script works.

References:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文