如何使用 UrlFetchApp 服务发送 JSON 有效负载?

Posted

技术标签:

【中文标题】如何使用 UrlFetchApp 服务发送 JSON 有效负载?【英文标题】:How to send a JSON payload with UrlFetchApp service? 【发布时间】:2012-06-04 20:57:19 【问题描述】:

我正在尝试 POST 到期望使用 Google Apps 脚本获取 JSON 作为有效负载的网络服务。我正在使用以下代码:

var options =

  "method" : "post",
  "contentType" : "application/json",
  "headers" : 
    "Authorization" : "Basic <Base64 of user:password>"  
  ,
  "payload" :  "endDate": "2012-06-03" 
;

var response = UrlFetchApp.fetch("http://www.example.com/service/expecting/json", options);

在服务器端我收到以下错误:

WARN [facade.SettingsServlet] 04 Jun 2012 15:30:26 - Unable to parse request body: endDate=2012-06-03
net.liftweb.json.JsonParser$ParseException: unknown token e

我假设服务器期望得到

 "endDate": "2012-06-03" 

而不是

endDate=2012-06-03

但我不知道如何让UrlFetchApp 做到这一点。

【问题讨论】:

【参考方案1】:

我不明白服务器端错误,但“有效负载”参数必须是此处指定的字符串:https://developers.google.com/apps-script/class_urlfetchapp?hl=fr-FR#fetch。

尝试:

var options =

  "method" : "post",
  "contentType" : "application/json",
  "headers" : 
    "Authorization" : "Basic <Base64 of user:password>"  
  ,
  "payload" : ' "endDate": "2012-06-03" '
;

【讨论】:

链接中关于payload的说法是:“...它可以是字符串、字节数组或javascript键/值映射。参见示例。”。当我尝试您的建议时,我从服务器收到错误代码 400。我也尝试了 Utilities.jsonStringify 以及相同的 400 响应代码。 但是服务器端的错误信息是一样的吗?尝试捕获请求以查看主体的外观。 错误消息不同,因为我根本没有收到对服务器的请求(400)。我无法捕获来自客户端(Google Apps 脚本)的请求,也没有看到它通过 Tomcat。在 Tomcat 日志中没有任何记录。 是的,我错了,您可以发送字符串、字节数组或 js 键/值映射。但在你的情况下,我认为你需要发送一个字符串。在你 fetch 之后尝试使用这个命令来捕获 GAS 发送的 HTTP 请求:Logger.log(UrlFetchApp.getRequest("example.com/service/expecting/json", options).toSource()); JSON.stringify 优于 Utilities.jsonStringify。后者有一些 id 的问题,而前者没有。【参考方案2】: 如果您将有效负载设置为字符串,它将直接传递(作为 UTF-8 字符串)。 如果您将有效负载设置为对象,它将像这样发送 一个 html 表单(如果 字段很简单,或者如果对象包含一个 'multipart/form-data' blob/文件)。

对于您的用例(服务器期望接收 JSON),听起来 Utilities.jsonStringify() 是要走的路。

【讨论】:

我怀疑在这种情况下 GAS 可能存在问题,因为在这种情况下请求的正文在某种程度上是无效的。通常从其他来源解析正文中的 JSON 的服务器无法解析来自 GAS 的传入请求。我尝试使用'...'和 Utilities.jsonStringify(...) 两种版本的 Stringing the payload。 也许要比较请求,尝试 POST 到回显 URL,例如:responseecho.appspot.com【参考方案3】:

类似的情况对我有用:

我没有创建 payload 并添加到 options,而是将参数构建到一个字符串中以附加到 URL:

var params = "id=2179853&amp;price=62755";

然后,我将参数附加到 url 字符串:

var result = UrlFetchApp.getRequest(url + '?' + params, options);

所以,我的 options 仅包含 标头

对于我的项目,这就像一个魅力。

【讨论】:

【参考方案4】:

下面是应该与一些重要的 cmets 一起使用的代码:

function testMe() 
    var products_authkey = "------------";
    try 
        var url = "https://app.ecwid.com/api/v1/---------/product?id=----------&secure_auth_key=" + products_authkey;
        //url= "http://requestb.in/----------"; // you can actually debug what you send out with PUTs or POSTs using Requestb.in service
        var payload = 
            id: "21798583", // id is necessary and should be a string, or it might be sent in scientific representation (with E)
            price: 62755
        ; 

        payload = JSON.stringify(payload); // the payload needs to be sent as a string, so we need this
        var options = 
            method: "put",
            contentType: "application/json", // contentType property was mistyped as ContentType - case matters
            payload: payload
        ; 
        var result = UrlFetchApp.getRequest(url, options);
        Logger.log(result) // a better way to debug
        var result = UrlFetchApp.fetch(url, options); // works perfectly in my case
        Logger.log(result)
     catch (e) 
        Logger.log(e)
    

【讨论】:

应该是JSON.stringify(payload)

以上是关于如何使用 UrlFetchApp 服务发送 JSON 有效负载?的主要内容,如果未能解决你的问题,请参考以下文章

Google 应用程序脚本:urlfetchapp - 服务调用次数过多

如何在谷歌工作区插件中使用 UrlFetchApp.fetchAll 和日历 API

如何在 Google Apps 脚本中使用 UrlFetchApp 发出 Drive API 批处理请求

如何在 Google Apps 脚本中向 UrlFetchApp 添加 API 密钥

在 Gmail 插件中使用 UrlFetchApp 的权限错误

Discord API 告诉我:“401:未经授权”,当我使用 Google 脚本进行 GET 时:“UrlFetchApp.fetch()”