javascript - 如何在 Web 界面中授权应用脚本?
问题描述
我有一个简单的应用程序脚本,它在驱动器中搜索名为“某物”的文件夹,并在该文件夹不存在时列出其中的文件名,它会创建它。
function doGet() {
var folders = DriveApp.getFoldersByName('something');
if (folders.hasNext()) {
var files = folders.next().getFiles();
var fileNames = [];
while (files.hasNext()) {
var file = files.next();
fileNames.push(file.getName())
};
return ContentService.createTextOutput(JSON.stringify({
'status': 'success',
'output': fileNames
}))
} else {
DriveApp.createFolder('something');
return ContentService.createTextOutput(JSON.stringify({
'status': 'success',
'output': 'folder created'
}))
}
}
我将脚本部署为 Web 应用程序,以我自己的身份执行该应用程序,使用来自浏览器中的 react 应用程序的 fetch 调用对其进行测试,一切都按预期工作。
然后我以 Web 应用程序的形式重新发布,以访问 Web 应用程序的用户身份执行。这次没有任何效果。我在浏览器中收到以下错误
访问从源“ http://localhost:3000 ”获取的“ https://script.google.com/macros/s/AKfycbx4eQ60DziUy4hSjnJidW9WVwBsT_qruQHa_BrK508T4oD9ILY/exec ”已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源。
我预计会出现错误,因为没有身份验证。我在 react 应用程序上设置了 google OAuth2,添加了脚本和驱动范围,在 google 开发人员控制台中注册了该应用程序并设置了所有内容,以便accessToken
我可以通过对 google 脚本的 fetch 调用将其发送到标题中。
但我仍然得到与上述相同的错误。
我应该如何授权应用程序脚本应用程序以便任何人都可以运行它?
我正在尝试创建一个带有google
登录按钮的网络应用程序,当用户登录时调用appscript
我部署的并在他们的驱动器中搜索文件夹名称“某物”,以便我可以在我的网络应用程序中显示文件的名称。
这不是 cors 问题,如果我以自己的身份执行 web 应用程序,则没有 cors 问题并且对代码的更改为零。我的问题是关于我如何授权应用脚本?我只提到了 cors 错误,因为我展示了我到目前为止所尝试的内容。
解决方案
如果您的调用中的任何函数引发异常,您将收到 CORS 错误,因为您没有try...catch
处理程序。当部署的 webapp未能返回有效响应(即 anHtmlOutput
或TextOutput
)时,Google 的错误页面不包含任何 CORS 标头。
为防止这些“屏蔽”CORS 错误,请将您的 Web 应用程序入口点包装起来,try...catch
以便报告实际错误。
即使不使用 包装您的 web 应用程序的入口点try...catch
,您也很可能能够通过查看项目的 Stackdriver 日志/Stackdriver 错误报告来访问底层错误。
这是一个简单的示例,演示了一些事件对象验证,以确保请求来自您关心的某个地方并且格式正确,然后调用一个可能为无效/未经授权的操作抛出异常的函数。无论哪种情况,它都会返回一个不透明的面向用户的响应(“对不起!”),并且对于错误将生成一个 Stackdriver 日志。它无法捕获因执行时间配额违规而发生的异常,因为您的脚本只是被杀死了。
function doGet(e) {
if (!e || !validate_(e)) {
return fail_();
}
try {
return walkDriveContent(...);
}
catch (err) {
console.error({message: "Drive walk failed: " + err.message, stack: err.stack, error: err});
return fail_();
}
}
function fail_() {
return ContentService.createTextOutput("Sorry!");
}
function validate_(eventObj) {
/** your code here that ensures this is a valid event object you can work with */
// return true;
// or
// return false;
}
function walkDriveContent(folderName) {
/**
* Your code that may throw exceptions here, but otherwise
* returns TextOutput or HtmlOutput
*/
}
推荐阅读
- arrays - 使用枚举查找数组中的所有组合(Swift 5)
- android - 如何只请求一次权限?
- ocaml - K 框架在 OCaml 后端产生错误
- javascript - 在 react-transition-group 中放置回调函数的位置
- linux - MassTransit 无法从 Linux 连接到 Rabbit Broker,但可以从 Windows - .Net Core 2.1
- html - 如何相对于图像定位文本?
- reactjs - 使用 JWT 和 axios 保持用户登录的最佳方法
- java - jdk12中appletviewer的替代方案
- ajax - 在 AJAX 调用 Laravel 后重定向到不同的视图
- python - 如何将str转换为int