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

时间:2018-12-11 18:31:45

标签: httprequest azure-functions dialogflow dialogflow-fulfillment

我正在为对话框流程构建自己的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://imgur.com/yzcj0Kw

2 个答案:

答案 0 :(得分:1)

我知道这应该是一条评论(因为这并不是真正的答案),但是它很冗长,我不希望它迷失在噪音中。

我在本地计算机上使用WebAPI时遇到相同的问题(使用ngrok隧道返回Kestrel)。我的一个朋友有有效的代码(他在AWS而不是Azure中托管),所以我开始研究我们的响应之间的区别。我注意到以下内容:

  1. Azure Functions和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);
});

此代码禁用了响应分块,这现在在Google控制台中对我造成了一个新的且稍微有趣的错误:

* Webhook呼叫失败。错误:无法解析webhook JSON响应:com.google.gson.stream.MalformedJsonException:第1行第94列路径中的未终止对象$。\ u0000 \\“ \ u0000f \ u0000u \ u0000l \ u0000f \ u0000i \ u0000l \ u0000l \ u0000m \ u0000e \ u0000n \ u0000t \ u0000M \ u0000e \ u0000s \ u0000s \ u0000a \ u0000g \ u0000e \ u0000s \ u0000 \\“ \ u0000。\

我认为起初可能是编码,所以我将JSON存放为字符串,并使用各种Encoding类在它们之间进行转换,无济于事。

我启动了Postman并调用了我的终结点(使用与Google相同的有效负载),我可以正确地看到整个响应有效负载-几乎就像Google的终端在读取过程中部分终止了流一样。

希望,这些附加信息将帮助我们了解发生了什么!

更新

经过更多挖掘和各种服务器/ 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
};

答案 1 :(得分:-1)

尽管HTTP标头说字符集为utf-8,但绝对使用utf-16le字符集,然后接收方将其视为utf-16be。鉴于您正在Azure上运行,听起来您需要在Azure Functions中进行一些配置,以将输出表示为UTF-8而不是使用UTF-16字符串。