1

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

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

4

2 回答 2

1

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

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

  1. Azure Functions 和 WebAPI 会发生这种情况(所以不是这样)
  2. JSON 有效负载是相同的(所以不是那样)
  3. 工作负载未分块
  4. 工作负载没有内容类型

作为一个实验,我Startup.csConfigure方法中添加了这段代码:

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.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
};
于 2018-12-31T15:10:43.477 回答
-1

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

于 2018-12-15T14:21:35.073 回答