如何从 google 脚本发送错误状态代码,如 Bad Request (400)?
How to send an error status code like Bad Request (400) from a google script?
这是 Google 应用中的一个 doPost
函数,returns 一个 Hello World 消息。
function doPost(e){
return ContentService.createTextOutput('Hello World');
}
现在假设我只想接受有效的 JSON 发布到此 Google 应用程序端点,并且我想发送状态为错误请求的响应。我怎样才能做到这一点。这是伪代码:
function doPost(e){
try{
const data = JSON.parse(e.postData.contents);
return ContentService.createTextOutput('Hello World');
}catch(err){
// Send Bad Request
}
}
问题和解决方法:
很遗憾,在当前阶段,ContentService
无法修改状态码。我看ClassContentService的官方文档,找不到这样的方法。 Ref 好像是现在的规格
那么在你的情况下,作为当前的解决方法,将值作为 JSON 数据返回怎么样?这样,您可以使用 JSON 数据的键检查值。例如,下面的示例脚本怎么样?
当返回没有错误的正确值时,
return ContentService.createTextOutput(JSON.stringify({value: 'value'}));
返回错误值时,
return ContentService.createTextOutput(JSON.stringify({error: 'Error message'}));
需要.setMimeType(ContentService.MimeType.JSON)
的时候请加这个
注:
- 当我在 Google 问题跟踪器上搜索此内容时,我找不到它。那么将此报告为未来的请求怎么样? Ref
参考:
这是另一种解决方法,允许在客户端针对 Web 应用程序端的错误引发错误。例如,客户端可能需要捕获诸如发送到 Web 应用程序的错误 url args 之类的错误(即 OP 的问题),或者捕获从 doGet()
或 doPost()
.
据我所知,当 doGet()
或 doPost()
的下游抛出错误时,文本错误消息是 return 在响应中编辑的,但是网络应用程序请求本身成功,因此客户端不会抛出任何错误。正如@Tanaike 所说,Google 网络应用程序开发人员似乎仍然无法从应用程序中抛出 HTTP 错误(例如 400 Bad Request
或 500 Internal Server Error
)。
这个想法涉及 return 从 Web 应用程序创建一个函数体,客户端可以使用它来创建和 运行 通过 Function()
构造函数创建一个动态函数(假设 Javascript在客户端可用)。
因此网络应用程序可以写入:
- return 一个函数体,它会因错误的参数、服务器方法错误等而抛出错误。
- return 一个函数体,它将 return 在没有错误的情况下 JSON
这有点hack,但它统一了客户端的错误处理。客户端发出 http 请求,使用在响应中 returned 的函数体构建一个函数,然后 运行s 这个函数,所有这些都在一个 try{}
块中。然后 Google 引发的 http 错误和 Web 应用下游错误都可以在 catch{}
块中捕获。
Google Apps 脚本客户端向 Google 网络应用发出请求的示例设置:
(1) 在网络应用 doGet()
或 doPost()
函数中:
// this string will be returned by the webapp
var fnBody;
// for bad url args, return a fnBody that will throw an error with an indicative message
if(!urlArgsOk()) {
fnBody = "'use strict'; throw new Error('POST args error');";
}
// if url args are ok, call server method
else {
try {
// if the method call succeeds, return a fnBody that will return the intended JSON
var returnObj = myServerMethod(methodArgs);
fnBody = "'use strict'; return JSON.stringify(" + JSON.stringify(returnObj) + ");";
}
catch(serverErr) {
// if the method call fails, return a fnBody that will throw an error ...
// ... simple example shown here, but info from serverErr can be included in fnBody
fnBody = "'use strict'; throw new Error('server error');";
}
}
// return fnBody, which can be run via Function() on the client
return ContentService.createTextOutput(fnBody).setMimeType(ContentService.MimeType.TEXT);
(2) 在客户端(Google 应用程序脚本客户端发出 POST 请求)
// Set the url, payload, and fetch options
var url = "https://script.google.com/_______/exec?arg1=val1&arg2=val2";
var payload = getPayloadString(); // whatever POST payload needs to be sent
var options = {
'method' : 'POST',
'contentType': 'application/json',
'muteHttpExceptions': false, // let Google http exceptions come through
'payload' : payload,
'headers': {authorization: "Bearer " + ScriptApp.getOAuthToken()}
};
// Send a request to the web app
try {
// make the POST request - this throws Google-generated HTTP errors if any
var response = UrlFetchApp.fetch(url, options);
// create the dynamic function from the fnBody returned
var responseFn = new Function(response.getContentText());
// run the function - this returns intended JSON content
// or throws web app downstream errors if any
var responseJson = responseFn();
}
catch(err) {
// handle either source of error
console.log(err.message);
}
动态代码存在潜在的安全风险,因此我不确定它的适用范围。我可能会在一个完全位于私有 GCP 域中的应用程序中使用它,即 Web 应用程序仅限于同域用户,而客户端应用程序也在同一个域中。 'use strict'
指令也增加了一些安全性,它通过将其 this
设置为 undefined
(ref). But it's still a good idea to think through the dynamic code implications (ref1, ref2).
来封装动态函数
这是 Google 应用中的一个 doPost
函数,returns 一个 Hello World 消息。
function doPost(e){
return ContentService.createTextOutput('Hello World');
}
现在假设我只想接受有效的 JSON 发布到此 Google 应用程序端点,并且我想发送状态为错误请求的响应。我怎样才能做到这一点。这是伪代码:
function doPost(e){
try{
const data = JSON.parse(e.postData.contents);
return ContentService.createTextOutput('Hello World');
}catch(err){
// Send Bad Request
}
}
问题和解决方法:
很遗憾,在当前阶段,ContentService
无法修改状态码。我看ClassContentService的官方文档,找不到这样的方法。 Ref 好像是现在的规格
那么在你的情况下,作为当前的解决方法,将值作为 JSON 数据返回怎么样?这样,您可以使用 JSON 数据的键检查值。例如,下面的示例脚本怎么样?
当返回没有错误的正确值时,
return ContentService.createTextOutput(JSON.stringify({value: 'value'}));
返回错误值时,
return ContentService.createTextOutput(JSON.stringify({error: 'Error message'}));
需要
.setMimeType(ContentService.MimeType.JSON)
的时候请加这个
注:
- 当我在 Google 问题跟踪器上搜索此内容时,我找不到它。那么将此报告为未来的请求怎么样? Ref
参考:
这是另一种解决方法,允许在客户端针对 Web 应用程序端的错误引发错误。例如,客户端可能需要捕获诸如发送到 Web 应用程序的错误 url args 之类的错误(即 OP 的问题),或者捕获从 doGet()
或 doPost()
.
据我所知,当 doGet()
或 doPost()
的下游抛出错误时,文本错误消息是 return 在响应中编辑的,但是网络应用程序请求本身成功,因此客户端不会抛出任何错误。正如@Tanaike 所说,Google 网络应用程序开发人员似乎仍然无法从应用程序中抛出 HTTP 错误(例如 400 Bad Request
或 500 Internal Server Error
)。
这个想法涉及 return 从 Web 应用程序创建一个函数体,客户端可以使用它来创建和 运行 通过 Function()
构造函数创建一个动态函数(假设 Javascript在客户端可用)。
因此网络应用程序可以写入:
- return 一个函数体,它会因错误的参数、服务器方法错误等而抛出错误。
- return 一个函数体,它将 return 在没有错误的情况下 JSON
这有点hack,但它统一了客户端的错误处理。客户端发出 http 请求,使用在响应中 returned 的函数体构建一个函数,然后 运行s 这个函数,所有这些都在一个 try{}
块中。然后 Google 引发的 http 错误和 Web 应用下游错误都可以在 catch{}
块中捕获。
Google Apps 脚本客户端向 Google 网络应用发出请求的示例设置:
(1) 在网络应用 doGet()
或 doPost()
函数中:
// this string will be returned by the webapp
var fnBody;
// for bad url args, return a fnBody that will throw an error with an indicative message
if(!urlArgsOk()) {
fnBody = "'use strict'; throw new Error('POST args error');";
}
// if url args are ok, call server method
else {
try {
// if the method call succeeds, return a fnBody that will return the intended JSON
var returnObj = myServerMethod(methodArgs);
fnBody = "'use strict'; return JSON.stringify(" + JSON.stringify(returnObj) + ");";
}
catch(serverErr) {
// if the method call fails, return a fnBody that will throw an error ...
// ... simple example shown here, but info from serverErr can be included in fnBody
fnBody = "'use strict'; throw new Error('server error');";
}
}
// return fnBody, which can be run via Function() on the client
return ContentService.createTextOutput(fnBody).setMimeType(ContentService.MimeType.TEXT);
(2) 在客户端(Google 应用程序脚本客户端发出 POST 请求)
// Set the url, payload, and fetch options
var url = "https://script.google.com/_______/exec?arg1=val1&arg2=val2";
var payload = getPayloadString(); // whatever POST payload needs to be sent
var options = {
'method' : 'POST',
'contentType': 'application/json',
'muteHttpExceptions': false, // let Google http exceptions come through
'payload' : payload,
'headers': {authorization: "Bearer " + ScriptApp.getOAuthToken()}
};
// Send a request to the web app
try {
// make the POST request - this throws Google-generated HTTP errors if any
var response = UrlFetchApp.fetch(url, options);
// create the dynamic function from the fnBody returned
var responseFn = new Function(response.getContentText());
// run the function - this returns intended JSON content
// or throws web app downstream errors if any
var responseJson = responseFn();
}
catch(err) {
// handle either source of error
console.log(err.message);
}
动态代码存在潜在的安全风险,因此我不确定它的适用范围。我可能会在一个完全位于私有 GCP 域中的应用程序中使用它,即 Web 应用程序仅限于同域用户,而客户端应用程序也在同一个域中。 'use strict'
指令也增加了一些安全性,它通过将其 this
设置为 undefined
(ref). But it's still a good idea to think through the dynamic code implications (ref1, ref2).