Webhook调用失败.错误:无法解析webhook JSON响应:预期消息对象,但得到:[中文字母]



我正在为对话框流构建自己的WebhookClient。我的代码如下(使用Azure函数,类似于Firebase函数(:

module.exports = async function(context, req) {
const agent = new WebhookClient({ request: context.req, response: context.res });
function welcome(agent) {
agent.add(`Welcome to my agent!!`);
}
let intentMap = new Map();
intentMap.set("Look up person", welcome);
agent.handleRequest(intentMap);
}

我测试了查询,响应负载如下所示:

{
"fulfillmentText": "Welcome to my agent!!",
"outputContexts": []
}

响应中的标题如下:

Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Tue, 11 Dec 2018 18:16:06 GMT

但当我在对话框流中测试我的机器人时,它会返回以下内容:

Webhook调用失败。错误:无法分析webhook JSON响应:预期消息对象,但得到:"笀ഀ਀  ∀昀甀氀昀椀氀氀洀攀渀琀吀攀砀琀∀㨀 ∀圀攀氀挀漀洀攀 琀漀 洀礀 愀最攀渀琀℀℀∀Ⰰഀ਀  ∀漀甀琀瀀甀琀䌀漀渀琀攀砀琀猀∀㨀 嬀崀ഀ਀紀".

有中文符号!?下面是我在DialogFlow中测试它的视频:https://i.stack.imgur.com/d1C8d.jpg

我知道这应该是一个注释(因为它不是真正的答案(,但它相当冗长,我不想让它迷失在噪音中。

我在本地机器上使用WebAPI也有同样的问题(使用ngrok隧道返回Kestrel(。我的一个朋友有工作代码(他在AWS而不是Azure中托管(,所以我开始研究我们的反应之间的差异。我注意到以下内容:

  1. 这发生在Azure函数和WebAPI中(所以不是这样(
  2. JSON有效负载是相同的(所以不是这样(
  3. 工作负载未分块
  4. 工作负载没有内容类型

作为一个实验,我将此代码添加到Startup.cs中,使用Configure方法:

app.Use(async (context, next) =>
{
var original = context.Response.Body;
var memory = new MemoryStream();
context.Response.Body = memory;
await next();
memory.Seek(0, SeekOrigin.Begin);
if (!context.Response.Headers.ContentLength.HasValue)
{
context.Response.Headers.ContentLength = memory.Length;
context.Response.ContentType = null;
}
await memory.CopyToAsync(original);
});

这段代码禁用了响应分块,这现在在谷歌控制台中给我带来了一个新的、稍微有趣一点的错误:

*Webhook调用失败。错误:无法解析webhook JSON响应:com.google.gson.stream.AlformedJson异常:第1行第94列路径$处的对象未终止。\u0000\\"\u0000f\u0000u\u0000l\u0000f\u0000i\u0000l\u0000l\u00000m\u0000e\u0000n\u0000t\u0000m\u0000e\u0000s\u0000s\u0000a\u0000g\u0000e\u0000s\u0000 \\"\u0000.\

起初我认为这可能是编码,所以我将JSON作为字符串存储起来,并使用各种Encoding类在它们之间进行转换,但没有成功。

我启动了Postman并调用了我的端点(使用与谷歌相同的有效负载(,我可以正确地看到整个响应有效负载——这几乎就像谷歌的端在阅读的中途终止了流。。。

希望这些额外的信息能帮助我们弄清楚发生了什么!

更新

经过更多的挖掘和各种服务器/lambda配置,我在这里发现了这篇文章:https://github.com/googleapis/google-cloud-dotnet/issues/2258

事实证明,json.net是罪魁祸首!我想这与正在退出管道的格式化程序有关。为了证明这一点,我将这个硬编码的响应添加到我的POST控制器中,它起了作用:(

return new ContentResult()
{
Content = "{"fulfillmentText": null,"fulfillmentMessages": [],"source": null,"payload": {"google": {"expectUserResponse": false,"userStorage": null,"richResponse": {"items": [{"simpleResponse": {"textToSpeech": "Why hello there","ssml": null,"displayText": "Why hello there"}}],"suggestions": null,"linkOutSuggestion": null}}}}",
ContentType = "application/json",
StatusCode = 200
};

尽管HTTP头说字符集是utf-8,但这肯定是在使用utf-16le字符集,然后接收方将其视为utf-16be。假设你在Azure上运行,听起来你需要在Azure函数中进行一些配置,以将输出表示为UTF-8,而不是使用UTF-16字符串。

最新更新