Google 脚本中带有服务帐户凭据的 UrlFetchApp 会引发 post、put、patch 错误
我有一个私人测试电子表格,已共享到 GAS 项目的服务帐户电子邮件。下面是:
使用 UrlFetchApp 和服务帐户 oAuth2 凭据从该电子表格“获取”数据的函数。 (获取的范围值:“'sName'!A1:B3”;工作表具有第 1 行列标题:A - “uId”;B - “标题”)。它与共享到服务帐户电子邮件(具有编辑权限)的电子表格配合得很好。如果没有该共享,它会因缺乏授权而失败。因此,oAuth 凭据似乎是正确的,具有电子表格的范围。 (我正在使用 此代码 由 Spencer Easton 生成 oAuth服务帐户的 clientToken。)
用于更新(发布、放置、修补)同一测试电子表格的函数。所有三种方法都失败,但出现不同的错误消息,如下所示:
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 正确配置更新范围或选项的一些基本内容。
感谢您提供解决更新问题的指导。
- 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);
- 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:
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.)
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.
- 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);
- 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不幸的是,我无法确认您想在第二个脚本中使用的方法。但是,从您的端点来看,我猜测您可能想要“方法:电子表格.values.update”。 参考
如果我的理解是正确的,
UrlFetchApp.fetch()
中没有valueInputOption
属性。如果标题行的“A”和“B”列中包含
uId
和title
,并且您希望将id3
和 < code>Update Title 为updateRange
,下面的修改如何?来自:
至:
注意:
参考文献:
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.valueInputOption
inUrlFetchApp.fetch()
.If the header row has
uId
andtitle
in the columns "A" and "B" and you want to put the values ofid3
andUpdate Title
toupdateRange
, how about the following modification?From:
To:
Note:
References: