cMalformedResponse:Webhook错误(206)同时看似有效的Webhook响应-Node.js中对Google Dialogflow应用的操作

时间:2019-03-08 19:55:45

标签: node.js google-cloud-functions dialogflow actions-on-google

问题

我正在通过Dialogflow使用Firebase Google Functions上托管的Node.js在Google上的库中开发Google上的Actions应用程序(用于Google Home)。我经常但不定期地(且难以复制)遇到错误,迫使Google上的操作(模拟器或Google Home本身)关闭我的应用程序。我将所有Dialogflow意图(包括回退)路由到我的Webhook实现中,并且-基于日志文件-Webhook快速响应(约200毫秒内)并且具有有效响应(调查JSON响应)。但是,Google上的操作似乎拒绝了响应,并触发了Dialogflow默认文本响应。 我最担心的是,它发生在对话的不同阶段,有时已经发生在欢迎事件中。也值得注意的是-即使完成响应以毫秒为单位(〜200),“操作” Google / Dialogflow需要一些时间,而且-我相信-会超时。以下是我对潜在原因的探索。但坦率地说,我没有主意。

-编辑-

该服务现在似乎运行得更好-我没有遇到此错误。我已经更改了代码,以通过使用全局数据库并将其传递通过,从而减少了对admin.firestore()的调用。我有一种预感,可能会同时调用https函数,这可能以某种方式导致格式错误的响应。

const database = admin.firestore();

// code

if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'functionname') {
 exports.functionname = functions.https.onRequest((req, res) => {
    require('./functions').functionname(req, res, database);
 });
}

我还发现我的意图处理存在缺陷,导致没有意图被匹配。我已经对Dialogflow意图进行了重组,以减少这种无意图的可能性(我基本上提出了一个两步式问题来确定用户的意图)。但是,由于Webhook确实能够正确响应,所以我不认为这是问题所在。尽管如此,我仍然发现它是一个奇怪的错误-因此,如果有人有更多的指针,请!

-结束编辑-

日志

这是来自Webhook的响应,从Google Functions日志中可以看到-表示已将响应发送到Dialogflow应用。

Function execution took 289 ms, finished with status code: 200 

Response {
  "status": 200,
  "headers": {
    "content-type": "application/json;charset=utf-8"
  },
  "body": {
    "payload": {
      "google": {
        "expectUserResponse": true,
        "richResponse": {
          "items": [{
            "simpleResponse": {
              "textToSpeech": "Welcome back! Which Widget do you want to work with?"
            }
          }]
        }
      }
    },
    "outputContexts": [{
        "name": "****anonymized****/contexts/widget",
        "lifespanCount": 1
      },
      {
        "name": "***anonymized****/contexts/_actions_on_google",
        "lifespanCount": 99,
        "parameters": {
          "data": "{\"started\":1552071670}"
        }
      }
    ]
  }
}

但是,这就是在Google控制台上显示的操作。 textToSpeech响应是默认的文本响应,如果实现失败(如https://medium.com/google-developers/debugging-common-actions-on-google-errors-7c8527378d27的建议,DialogFlow可以退回到该文本响应)

{
  "conversationToken": "[]",
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "simpleResponse": {
            "textToSpeech": "Sorry! I cannot access my online service. Please try again!"
          }
        }
      ]
    }
  },
  "responseMetadata": {
    "status": {
      "code": 14,
      "message": "Webhook error (206)"
    },
    "queryMatchInfo": {
      "queryMatched": true,
      "intent": "e0bf4b96-9440-4545-a8a6-d0915cacd34f"
    }
  }
}

堆栈驱动程序日志还指示后一种情况,即接收到Dialogflow的默认响应。

想法

我试图在模拟器,手机和Google Home上复制此错误。尽管似乎比以前更频繁地发生,但它发生在不同的时刻。我的三个预感如下:

  1. 超载。我的Google Functions托管8个功能,包括Dialogflow应用。也许如果在给定时刻也频繁调用其他功能,则Dialogflow应用程序处理来自Dialogflow(Google助手)的https请求会出问题。但是,我不知道这应该如何发生。通过在具有两个不同帐户的两个设备上调用应用程序,我可以复制(有时)问题。但是由于一个帐户也会发生这种情况,因此我认为这不是唯一的问题。我遵循了这个技巧来减少过载(https://stackoverflow.com/a/47985480/7053198),但这似乎对我的问题没有帮助。那么Google功能的升级是否会成为问题?
  2. 诺言。我正在使用许多Promise(或更多回调)与Firestore数据库进行通信以检索用户数据。但是,我可以很快地调用这些意图,并且它们可以很好地解决-直到它们无法解决为止。以下是这种意图的摘要。
  3. 我的应用大小。 Intent的数量已经非常多,并且Google Functions和Firestore数据库之间的通信很多。我只是不知道这将如何影响Dialogflow拒绝看似正确的响应。

带有承诺代码段的意图:

app.intent(I.WIDGETTEST, conv => {
  let database = admin.firestore();
  let offline = [];

  return database.collection('users').doc(conv.user.storage.userId).collection('widgets').get()
  .then((snapshot) => { 

    const promises = [];
    snapshot.forEach(doc => {
      if (doc.data().active) {
        if ((moment().unix()-doc.data().server.seen) > 360){
          offline.push(doc.data().name);
        }
        promises.push(doc.ref.update({'todo.test': true}));
      }
    });
    return Promise.all(promises);
  })
  .then(()=>{
    conv.contexts.set(C.WIDGET, 1);
    return conv.ask("Testing in progress. Which Widget do you want to work with now?");
  })
  .catch((err) => {
    console.log(err)
    throw err;
  });
});

问题示例日志

为了很好地衡量,这里是堆栈驱动程序方面的三个日志条目:

{
    "textPayload": "Sending request with post data: {\"user\":{\"userId\":\"***anonymized***\",\"locale\":\"en-US\",\"lastSeen\":\"2019-03-08T18:54:47Z\",\"userStorage\":\"{\\\"data\\\":{\\\"userId\\\":\\\"***anonymized***\\\"}}\",\"idToken\":\"eyJhbGciOiJSUzI1NiIsImtpZCI6ImNmMDIyYTQ5ZTk3ODYxNDhhZDBlMzc5Y2M4NTQ4NDRlMzZjM2VkYzEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE1NTIwNzEzNjAsImF1ZCI6Ijk4NzgxNjU4MTIzMC1ibWVtMm5wcTRsNnE3c2I5MnVpM3BkdGRhMWFmajJvNy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjEwMjk3OTk3NzIyNTM3NjY4MDEyOSIsImVtYWlsIjoiZGF2aWR2ZXJ3ZWlqQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJuYW1lIjoiRCBWZXJ3ZWlqIiwicGljdHVyZSI6Imh0dHBzOi8vbGg2Lmdvb2dsZXVzZXJjb250ZW50LmNvbS8taldtOFd3eE5iS3MvQUFBQUFBQUFBQUkvQUFBQUFBQUFyLUUvNEE2UmJiYVNwem8vczk2LWMvcGhvdG8uanBnIiwiZ2l2ZW5fbmFtZSI6IkQiLCJmYW1pbHlfbmFtZSI6IlZlcndlaWoiLCJpYXQiOjE1NTIwNzE2NjAsImV4cCI6MTU1MjA3NTI2MCwianRpIjoiYjE4MDYwMjc0YmE4MjJhYzFhYzc0MTYwZjI2YWM2MDk3MzBmZDY4ZSJ9.Y9G0qo0Gf28-noF7RYPhtfHRuA7Qo6bCBSuN56Y0AtgIXaQKZjnmYvABIt9u8WQ1qPWwQc3jOLyhfoXIk8j0zhcQ0M0oc7LjkBwVCgFnJHvUAiV5fGEqQa95pZyrZhYmHipTDdwk0UhJHFGJOXAHDPP6oBSHKC9h48jqUjVszz6iEy4frV0XIKIzRR2U2iY6OgJuxPsV0A7xNjvLXiMmwaRUVtlj9CPmiizd3G2PhqD5C54Fy2Qg5ch89qMOA10vNB5B4AX9pmAXHpmtIqFo7ljvAeGAj-pRuqyMllz2awAdvqqOFRERDYfm5Fyh7N0l1OhR2A2XRegsUIL1I1EVPQ\"},\"conversation\":{\"conversationId\":\"ABwppHH8PXibDZg8in1DjbP-caFy67Dtq025k_Uq2ofoPNXKtiPXrbJTmpGVUnVy-aY6H1MeZCFIpQ\",\"type\":\"NEW\"},\"inputs\":[{\"intent\":\"actions.intent.MAIN\",\"rawInputs\":[{\"inputType\":\"KEYBOARD\",\"query\":\"Talk to ***anonymized appname***\"}]}],\"surface\":{\"capabilities\":[{\"name\":\"actions.capability.SCREEN_OUTPUT\"},{\"name\":\"actions.capability.MEDIA_RESPONSE_AUDIO\"},{\"name\":\"actions.capability.AUDIO_OUTPUT\"},{\"name\":\"actions.capability.WEB_BROWSER\"}]},\"isInSandbox\":true,\"availableSurfaces\":[{\"capabilities\":[{\"name\":\"actions.capability.SCREEN_OUTPUT\"},{\"name\":\"actions.capability.AUDIO_OUTPUT\"},{\"name\":\"actions.capability.WEB_BROWSER\"}]}],\"requestType\":\"SIMULATOR\"}.",
    "insertId": "120zsprg2nqfayb",
    "resource": {
      "type": "assistant_action",
      "labels": {
        "action_id": "actions.intent.MAIN",
        "project_id": "***anonymized***",
        "version_id": ""
      }
    },
    "timestamp": "2019-03-08T19:01:00.243055001Z",
    "severity": "DEBUG",
    "labels": {
      "channel": "preview",
      "source": "AOG_REQUEST_RESPONSE",
      "querystream": "GOOGLE_USER"
    },

{
    "textPayload": "Received response from agent with body: HTTP/1.1 200 OK\r\nServer: nginx/1.13.6\r\nDate: Fri, 08 Mar 2019 19:01:10 GMT\r\nContent-Type: application/json;charset=UTF-8\r\nContent-Length: 330\r\nX-Cloud-Trace-Context: 7761b69610701e0a7d18cbc69eef9bde/3001560133061614360;o=0\r\nGoogle-Actions-API-Version: 2\r\nAccess-Control-Allow-Credentials: true\r\nVia: 1.1 google\r\nAlt-Svc: clear\r\n\r\n{\"conversationToken\":\"[]\",\"finalResponse\":{\"richResponse\":{\"items\":[{\"simpleResponse\":{\"textToSpeech\":\"Sorry! I cannot access my online service. Please try again!\"}}]}},\"responseMetadata\":{\"status\":{\"code\":14,\"message\":\"Webhook error (206)\"},\"queryMatchInfo\":{\"queryMatched\":true,\"intent\":\"e0bf4b96-9440-4545-a8a6-d0915cacd34f\"}}}.",
    "insertId": "120zsprg2nqfayc",
    "resource": {
      "type": "assistant_action",
      "labels": {
        "project_id": "***anonymized***",
        "version_id": "",
        "action_id": "actions.intent.MAIN"
      }
    },
    "timestamp": "2019-03-08T19:01:10.376894030Z",
    "severity": "DEBUG",
    "labels": {
      "channel": "preview",
      "source": "AOG_REQUEST_RESPONSE",
      "querystream": "GOOGLE_USER"
    },
    "logName": "projects/***anonymized***/logs/actions.googleapis.com%2Factions",
    "trace": "projects/987816581230/traces/ABwppHH8PXibDZg8in1DjbP-caFy67Dtq025k_Uq2ofoPNXKtiPXrbJTmpGVUnVy-aY6H1MeZCFIpQ",
    "receiveTimestamp": "2019-03-08T19:01:10.389139428Z"
  },
{
    "textPayload": "MalformedResponse: Webhook error (206)",
    "insertId": "1d4bzl9g3lossug",
    "resource": {
      "type": "assistant_action",
      "labels": {
        "project_id": "***anonymized***",
        "version_id": "",
        "action_id": "actions.intent.MAIN"
      }
    },
    "timestamp": "2019-03-08T19:01:10.377231474Z",
    "severity": "ERROR",
    "labels": {
      "channel": "preview",
      "source": "JSON_RESPONSE_VALIDATION",
      "querystream": "GOOGLE_USER"
    },
    "logName": "projects/***anonymized***/logs/actions.googleapis.com%2Factions",
    "trace": "projects/987816581230/traces/ABwppHH8PXibDZg8in1DjbP-caFy67Dtq025k_Uq2ofoPNXKtiPXrbJTmpGVUnVy-aY6H1MeZCFIpQ",
    "receiveTimestamp": "2019-03-08T19:01:10.388395945Z"
  }

帮助!

对于解决此问题的任何帮助或指导都非常感激。让我知道您是否曾经有过此经历,是否有潜在的解决方案,或者想查看代码或日志的更多详细信息。非常感谢!

1 个答案:

答案 0 :(得分:0)

当我尝试修改自己的Google助手应用程序之一时,出现了相同的错误。 一切正常,但是我突然遇到了与您相同的错误,我无法理解,并且与我的新发展无关。

{
 insertId:  "102mhl8g1omvh70"  
 labels: {
  channel:  "preview"   
  querystream:  "GOOGLE_USER"   
  source:  "JSON_RESPONSE_VALIDATION"   
 }
 logName:  "projects/myprojectID/logs/actions.googleapis.com%2Factions"  
 receiveTimestamp:  "2019-04-22T16:56:11.508733115Z"  
 resource: {
  labels: {
   action_id:  "actions.intent.MAIN"    
   project_id:  "myprojectID"    
   version_id:  ""    
  }
  type:  "assistant_action"   
 }
 severity:  "ERROR"  
 textPayload:  "MalformedResponse: Webhook error (206)"  
 timestamp:  "2019-04-22T16:56:11.498787357Z"  
 trace:  "projects/168413137357/traces/ABwppHG8ckJJgXMT5Jedih2WUtGNZZc9i0BVG5S-CkxCT8mkhy7mDr8L9GPd9p_EvXIIlTz3SK2z16jBK8Id"  
}

我试图通过禁用Webhook并在dialogflow目的中设置播放负载来解决该问题。无论如何,我仍然遇到此错误。

因此,我尝试通过上传旧版本的intentneted意向回退我的开发,但这没有用,并且仍然出现错误 看着我的功能日志,我看到了

SyntaxError: Unexpected token : in JSON at position 6
at Object.parse (native)
at new User (/user_code/node_modules/actions-on-google/dist/service/actionssdk/conversation/user.js:75:43)
at DialogflowConversation.Conversation (/user_code/node_modules/actions-on-google/dist/service/actionssdk/conversation/conversation.js:47:21)
at DialogflowConversation (/user_code/node_modules/actions-on-google/dist/service/dialogflow/conv.js:36:9)
at WebhookClient.conv (/user_code/node_modules/dialogflow-fulfillment/src/dialogflow-fulfillment.js:415:14)
at welcome (/user_code/index.js:37:26)
at WebhookClient.handleRequest (/user_code/node_modules/dialogflow-fulfillment/src/dialogflow-fulfillment.js:273:44)
at exports.dialogflowFirebaseFulfillment.functions.https.onRequest (/user_code/index.js:247:11)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/providers/https.js:37:41)
at /var/tmp/worker/worker.js:783:7

我不明白如何无法正确解析助手的json,我感到非常惊讶。我比较了该错误前后的JSON输入,发现userstorage条目的格式不正确。

我有类似的东西:

"user":{"userStorage":"\"data\":}","lastSeen":"2019-04-22T16:22:10Z","locale":"Mylanguage","userId":"ABwppHGoZFMQwTpdqZaOYBaIh32-hXH2kUN_EPJglUXMl5MeH7QlLyB9O0bCgZ0SQ9L0B2Ks-JQ9rHfRoAh-"}

代替此:

"user":{"userStorage":"{\"data\":{}}","lastSeen":"2019-04-21T17:55:21Z","locale":"Mylanguage","userId":"ABwppHGoZFMQwTpdqZaOYBaIh32-hXH2kUN_EPJglUXMl5MeH7QlLyB9O0bCgZ0SQ9L0B2Ks-JQ9rHfRoAh-"}

当您尝试像这样从代理获取对话时,此json会引发错误:

 let conv = agent.conv();

我仍然不知道这怎么可能,但是我有一个解决方法。 我通过在对话之前更正json来解决它。 在我的应用中,我不需要任何用户存储,因此在进行此类对话之前,我总是正确地初始化用户存储:

request.body.originalDetectIntentRequest.payload.user.userStorage = "{\"data\":{}}";

我将与dialogflow支持人员联系,以告知他们我认为是一个错误

我希望这个答案对您有所帮助!