Вызов веб-перехватчика не удался. Ошибка: не удалось проанализировать ответ 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

Но когда я тестирую своего бота в диалоговом режиме, он возвращает следующее:

Вызов веб-перехватчика не удался. Ошибка: не удалось проанализировать ответ JSON веб-перехватчика: ожидается объект сообщения, но получено: «笀 ഀ ਀ ∀ 昀 甀 氀 昀 氀 氀 洀 渀 琀 吀 攀 㨀 ∀ 攀 氀 挀 洀 礀 愀. 最 攀 渀 琀 ℀℀∀Ⰰ ഀ ਀ ∀ 琀 䌀 漀 渀 琀 攀 砀 猀 ∀ 嬀 ਀ 紀 ".

Есть китайские символы !? Вот видео, в котором я тестировал его в DialogFlow: https://imgur.com/yzcj0Kw


person AskYous    schedule 11.12.2018    source источник
comment
Вы используете редактор портала Azure для написания функции? У меня была точно такая же проблема. Мое решение заключалось в том, чтобы вместо этого создать функцию Visual Studio (docs.microsoft.com/en-us/azure/azure-functions/) и использование ngrok для создания туннеля к локальному хосту, который диалоговый процесс может вызывать как веб-перехватчик.   -  person mintsponge    schedule 12.12.2018
comment
@mintsponge Я пишу это локально в коде NodeJS и Visual Studio. Я не понял, что вы имели в виду, говоря о нгроках. Я не знаю, что такое нгрок.   -  person AskYous    schedule 13.12.2018
comment
@mintsponge, вы как-то запускали ngrok на своем локальном компьютере разработчика или в функциях Azure?   -  person AskYous    schedule 14.12.2018
comment
какой URL-адрес вы используете в разделе выполнения диалогового потока? Использование URL-адреса Azure - вот что вызвало у меня проблему. Вместо этого я запустил функцию в VS, которая развернула ее на локальном хосте. Но поскольку Dialogflow может получить доступ только к общедоступным URL-адресам, ngrok был запущен (локально) для создания общедоступного URL-адреса ngrok.   -  person mintsponge    schedule 16.12.2018


Ответы (2)


Я знаю, что это должен быть комментарий (поскольку на самом деле это не ответ), но он довольно подробный, и я не хотел, чтобы он терялся в шуме.

У меня такая же проблема с использованием 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);
});

Этот код отключает фрагменты ответа, что теперь вызывает новую и немного более интересную для меня ошибку в консоли Google:

* Сбой вызова веб-перехватчика. Ошибка: не удалось проанализировать ответ 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 завершал поток на полпути через чтение ...

Надеюсь, эта дополнительная информация поможет нам разобраться в происходящем!

Обновлять

После еще нескольких поисков и различных конфигураций сервера / лямбда я заметил этот пост здесь: 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
};
person gplumb    schedule 31.12.2018
comment
Чтобы исключить мой прокси (ngrok), я создал функцию Azure с жестко запрограммированной полезной нагрузкой JSON (которая действительна и быстро реагирует). К сожалению, конфигурация моего локального компьютера не является проблемой, поскольку проблема сохраняется. Это также исключает JSON.net как основную причину, так что сейчас я как бы в тупике ... - person gplumb; 31.12.2018
comment
Оказывается, виноват json.net! Я обновил свой ответ выше. - person gplumb; 31.12.2018

Несмотря на то, что в заголовке HTTP указано, что кодировка - это utf-8, он определенно использует набор символов utf-16le, а затем принимающая сторона обрабатывает их как utf-16be. Учитывая, что вы работаете в Azure, похоже, что вам нужно выполнить некоторую конфигурацию в Функциях Azure, чтобы представить вывод как UTF-8 вместо использования строк UTF-16.

person Prisoner    schedule 15.12.2018