Alexa 的 AWS Lambda 函数中的 HTTP 请求失败

HTTP request failing in AWS Lambda function for Alexa

我试图在我的内联 Lambda 函数中 return 来自外部 api 的数据,但是当我在 Alexa 的开发人员控制台中测试它时,我得到 'There was a problem with the requested skills response' 并且我可以找出原因。 此外,当我从 AWS 控制台执行此操作时,我无法 console.log 看到它实际上是什么 returned。
(为了 post,我删除了默认意图)

const request = require('request');

const handlers = {
'LaunchRequest': function () {
    this.emit(':ask', 'Welcome');
},
'GiveUpdateIntent': function (){
    var slot = this.event.request.intent.slots.line.value;

    httpGet(slot, (theResult) => {
            this.response.speak(theResult);
            this.emit(':responseReady');
        });

}

};
function httpGet(query, callback) {
var options = {
    host: 'api.tfl.gov.uk',
    path: '/line/' + encodeURIComponent(query) + '/status',
    method: 'GET',
};

var req = http.request(options, res => {
    res.setEncoding('utf8');
    var responseString = "";

    //accept incoming data asynchronously
    res.on('data', chunk => {
        responseString += chunk;
    });

    //return the data when streaming is complete
    res.on('end', () => {
        console.log(responseString[0]);
        callback(responseString[0]);
    });

});
req.end();
}


exports.handler = function (event, context, callback) {
    const alexa = Alexa.handler(event, context, callback);
    alexa.APP_ID = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

"There was a problem with the requested skills response" 通常意味着您的技能响应不是预期的格式。

你的API请求

例如:维多利亚

https://api.tfl.gov.uk/Line/victoria/Status  

returns a JSON,您不能直接将它作为响应传递给 Alexa。在你把它发回给 Alexa 之前,取出 status 你真的想让 Alexa 说话。然后把它写成任何技能使用者都能理解的有意义的句子并发回。

例如你可以return这样的东西:

var speech = "Status severity description for " + 
              this.event.request.intent.slots.line.value +
              " is "
              + responseBody[0].lineStatuses.statusSeverityDescription;
this.emit(':ask',speech, "your re-prompt here");

这是我得到的样本 JSON

[
  {
    "$type": "Tfl.Api.Presentation.Entities.Line, Tfl.Api.Presentation.Entities",
    "id": "victoria",
    "name": "Victoria",
    "modeName": "tube",
    "disruptions": [],
    "created": "2018-07-31T12:11:08.477Z",
    "modified": "2018-07-31T12:11:08.477Z",
    "lineStatuses": [
      {
        "$type": "Tfl.Api.Presentation.Entities.LineStatus, Tfl.Api.Presentation.Entities",
        "id": 0,
        "statusSeverity": 10,
        "statusSeverityDescription": "Good Service",
        "created": "0001-01-01T00:00:00",
        "validityPeriods": []
      }
    ],
    "routeSections": [],
    "serviceTypes": [
      {
        "$type": "Tfl.Api.Presentation.Entities.LineServiceTypeInfo, Tfl.Api.Presentation.Entities",
        "name": "Regular",
        "uri": "/Line/Route?ids=Victoria&serviceTypes=Regular"
      },
      {
        "$type": "Tfl.Api.Presentation.Entities.LineServiceTypeInfo, Tfl.Api.Presentation.Entities",
        "name": "Night",
        "uri": "/Line/Route?ids=Victoria&serviceTypes=Night"
      }
    ],
    "crowding": {
      "$type": "Tfl.Api.Presentation.Entities.Crowding, Tfl.Api.Presentation.Entities"
    }
  }
]

CloudWatch: 始终使用 CloudWatch 查看您的 Lambda 函数的日志,您将在 Lambda 函数的 Monitoring 选项卡下获得 link。

配置 Lambda 测试事件:您可以通过在内联编辑器的 Test 菜单下配置 Lambda Test Events,直接从内联编辑器测试 Lambda 代码。一个函数最多可以有 10 个测试事件。

这是因为您的 handler 在调用回调之前返回。我强烈建议放弃 NodeJS 中基于回调的开发,而改用 Promise

我刚刚回答了一个类似的问题,并提供了带有承诺的示例代码。在这里查看

事实证明问题出在使用 http 本身而不是 https。

我得到的唯一响应是状态代码 302,这是一个重定向,因为我调用的 api 将所有 http 请求更改为 https。

因此,我将导入更改为 https 并使用 https.get 方法(而不是 http.get)调用 api 并返回了正确的响应。