Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js AWS Lambda无法调用外部https端点_Node.js_Amazon Web Services_Aws Lambda - Fatal编程技术网

Node.js AWS Lambda无法调用外部https端点

Node.js AWS Lambda无法调用外部https端点,node.js,amazon-web-services,aws-lambda,Node.js,Amazon Web Services,Aws Lambda,我们正在研究Alexa技能,它需要接触外部RESTAPI来获取数据。出于某种原因,我很难在lambda函数中使用它。我也很难确定问题是在我的node.js代码中没有正确使用回调函数,还是在我的函数的VPC设置中。这是我的代码,我去掉了不必要的东西 /* eslint-disable func-names */ /* eslint quote-props: ["error", "consistent"]*/ /** * This sample demonstrates a simple ski

我们正在研究Alexa技能,它需要接触外部RESTAPI来获取数据。出于某种原因,我很难在lambda函数中使用它。我也很难确定问题是在我的node.js代码中没有正确使用回调函数,还是在我的函数的VPC设置中。这是我的代码,我去掉了不必要的东西

/* eslint-disable  func-names */
/* eslint quote-props: ["error", "consistent"]*/
/**
 * This sample demonstrates a simple skill built with the Amazon Alexa Skills
 * nodejs skill development kit.
 * This sample supports multiple lauguages. (en-US, en-GB, de-DE).
 * The Intent Schema, Custom Slots and Sample Utterances for this skill, as well
 * as testing instructions are located at https://github.com/alexa/skill-sample-nodejs-fact
 **/

'use strict';

const Alexa = require('alexa-sdk');

const APP_ID = undefined;  // TODO replace with your app ID (OPTIONAL).

const https = require('https');

const handlers = {
    'LaunchRequest': function () {
        this.emit('GetFact');
    },
    'GetNewFactIntent': function () {
        this.emit('GetFact');
    },
    'maintenanceIntent': function () {
        console.log('inside maintenanceIntent');

    var options = {
        host: 'api.forismatic.com',
        path: '/api/1.0/?method=getQuote&lang=en&format=text',
        method: 'GET'
    };

    getQuote(options, function (quote){
            if(quote === ''){
                console.log("No quote");
                //speechOutput = "Please try again later";
            }
            else{console.log(quote)}
            //self.emit(':tellWithCard', speechOutput, SKILL_NAME, text);
        });

        // Create speech output
        // Place holder
        var randomFact = 'Test Fact';
        const speechOutput = randomFact;
        this.emit(':tellWithCard', speechOutput, 'test skill name', randomFact);
    },
    'AMAZON.HelpIntent': function () {
        const speechOutput = this.t('HELP_MESSAGE');
        const reprompt = this.t('HELP_MESSAGE');
        this.emit(':ask', speechOutput, reprompt);
    },
    'AMAZON.CancelIntent': function () {
        this.emit(':tell', this.t('STOP_MESSAGE'));
    },
    'AMAZON.StopIntent': function () {
        this.emit(':tell', this.t('STOP_MESSAGE'));
    },
};

exports.handler = function (event, context, callback) {
    const alexa = Alexa.handler(event, context);
    alexa.APP_ID = APP_ID;
    // To enable string internationalization (i18n) features, set a resources object.
    //alexa.resources = languageStrings;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

function getQuote(options, callback){
    var text = '';
    console.log("in getquote");
    https.get(options, function(res) {
        console.error("Got response: " + res.statusCode);
        res.on("data", function(chunk) {
        console.error("BODY: " + chunk);
        text = '' + chunk;
        return callback(text);
    });
    }).on('error', function(e) {
        text = 'error' + e.message;
        console.error("Got error: " + e.message);
});
}
现在,当我调用MaintenanceContent时,这就是我在日志中看到的内容

{"timestamp":1508426249817,"message":"START RequestId: 9f66123e-b4e0-11e7-baac-1bfb01d2abc8 Version: $LATEST","logStream":"2017/10/19/[$LATEST]0e048ab2fc5441cda8007e4a1963bf02","logGroup":"/aws/lambda/factDemo","requestID":"9f66123e-b4e0-11e7-baac-1bfb01d2abc8"}
{"timestamp":1508426250256,"message":"Warning: Application ID is not set","logStream":"2017/10/19/[$LATEST]0e048ab2fc5441cda8007e4a1963bf02","logGroup":"/aws/lambda/factDemo","requestID":"9f66123e-b4e0-11e7-baac-1bfb01d2abc8"}
{"timestamp":1508426250256,"message":"inside maintenanceIntent","logStream":"2017/10/19/[$LATEST]0e048ab2fc5441cda8007e4a1963bf02","logGroup":"/aws/lambda/factDemo","requestID":"9f66123e-b4e0-11e7-baac-1bfb01d2abc8"}
{"timestamp":1508426250256,"message":"in getquote","logStream":"2017/10/19/[$LATEST]0e048ab2fc5441cda8007e4a1963bf02","logGroup":"/aws/lambda/factDemo","requestID":"9f66123e-b4e0-11e7-baac-1bfb01d2abc8"}
{"timestamp":1508426250256,"message":"END RequestId: 9f66123e-b4e0-11e7-baac-1bfb01d2abc8","logStream":"2017/10/19/[$LATEST]0e048ab2fc5441cda8007e4a1963bf02","logGroup":"/aws/lambda/factDemo","requestID":"9f66123e-b4e0-11e7-baac-1bfb01d2abc8"}
{"timestamp":1508426250256,"message":"REPORT RequestId: 9f66123e-b4e0-11e7-baac-1bfb01d2abc8\tDuration: 378.28 ms\tBilled Duration: 400 ms \tMemory Size: 128 MB\tMax Memory Used: 33 MB\t","logStream":"2017/10/19/[$LATEST]0e048ab2fc5441cda8007e4a1963bf02","logGroup":"/aws/lambda/factDemo","requestID":"9f66123e-b4e0-11e7-baac-1bfb01d2abc8"}
所以我可以看到它实际上在调用getQuote函数。我没有看到任何错误或成功消息。我想也许我没有正确地使用回调(node不是我的正常开发语言),但实际上我直接从GitHub上的一个Amazon示例中提取了代码,我甚至无法实现这一点。(此代码与之非常相似,只是略短一些。)

如果我将其剥离并通过节点在本地运行,它就可以正常工作

至于网络方面,我遵循以下指南: . 我也尝试过Amazon指南,但在这一点上,我甚至不确定如何检查互联网连接,或者这是否是问题所在

如果您能帮助我们走上正轨,我们将不胜感激

--编辑--

我把代码也改了。这是直接从alexa在

相同的想法,但从端点获取结果的执行略有不同。这是日志输出

{"timestamp":1508434982754,"message":"START RequestId: f4a39351-b4f4-11e7-a563-fbf7599fa72f Version: $LATEST","logStream":"2017/10/19/[$LATEST]3252e394be9b4a229c3a0d042deffbf8","logGroup":"/aws/lambda/factDemo","requestID":"f4a39351-b4f4-11e7-a563-fbf7599fa72f"}
{"timestamp":1508434982887,"message":"exports handler","logStream":"2017/10/19/[$LATEST]3252e394be9b4a229c3a0d042deffbf8","logGroup":"/aws/lambda/factDemo","requestID":"f4a39351-b4f4-11e7-a563-fbf7599fa72f"}
{"timestamp":1508434982887,"message":"Warning: Application ID is not set","logStream":"2017/10/19/[$LATEST]3252e394be9b4a229c3a0d042deffbf8","logGroup":"/aws/lambda/factDemo","requestID":"f4a39351-b4f4-11e7-a563-fbf7599fa72f"}
{"timestamp":1508434982887,"message":"inside maintenanceIntent","logStream":"2017/10/19/[$LATEST]3252e394be9b4a229c3a0d042deffbf8","logGroup":"/aws/lambda/factDemo","requestID":"f4a39351-b4f4-11e7-a563-fbf7599fa72f"}
{"timestamp":1508434982887,"message":"in","logStream":"2017/10/19/[$LATEST]3252e394be9b4a229c3a0d042deffbf8","logGroup":"/aws/lambda/factDemo","requestID":"f4a39351-b4f4-11e7-a563-fbf7599fa72f"}
{"timestamp":1508434982887,"message":"Florida","logStream":"2017/10/19/[$LATEST]3252e394be9b4a229c3a0d042deffbf8","logGroup":"/aws/lambda/factDemo","requestID":"f4a39351-b4f4-11e7-a563-fbf7599fa72f"}
{"timestamp":1508434983307,"message":"req.end","logStream":"2017/10/19/[$LATEST]3252e394be9b4a229c3a0d042deffbf8","logGroup":"/aws/lambda/factDemo","requestID":"f4a39351-b4f4-11e7-a563-fbf7599fa72f"}
{"timestamp":1508434983309,"message":"post execute","logStream":"2017/10/19/[$LATEST]3252e394be9b4a229c3a0d042deffbf8","logGroup":"/aws/lambda/factDemo","requestID":"f4a39351-b4f4-11e7-a563-fbf7599fa72f"}
{"timestamp":1508434983367,"message":"END RequestId: f4a39351-b4f4-11e7-a563-fbf7599fa72f","logStream":"2017/10/19/[$LATEST]3252e394be9b4a229c3a0d042deffbf8","logGroup":"/aws/lambda/factDemo","requestID":"f4a39351-b4f4-11e7-a563-fbf7599fa72f"}
{"timestamp":1508434983367,"message":"REPORT RequestId: f4a39351-b4f4-11e7-a563-fbf7599fa72f\tDuration: 608.20 ms\tBilled Duration: 700 ms \tMemory Size: 128 MB\tMax Memory Used: 35 MB\t","logStream":"2017/10/19/[$LATEST]3252e394be9b4a229c3a0d042deffbf8","logGroup":"/aws/lambda/factDemo","requestID":"f4a39351-b4f4-11e7-a563-fbf7599fa72f"}

我在VPC内外都尝试过这个方法,结果是一样的。

所以这个问题解决了,这要归功于这个问题:

尤其是这一行

:tell函数将调用lambda回调并终止lambda函数的执行

将httpsGet外部的this.emit移动到其中,就像这样解决了这个问题

httpsGet(myRequest,  (myResult) => {
                console.log("sent     : " + myRequest);
                console.log("received : " + myResult);

                this.response.speak('The population of ' + myRequest + ' is ' + myResult);
                this.emit(':responseReady');

                // Create speech output
                // Place holder
                var randomFact = 'Test Fact';
                const speechOutput = randomFact;
                this.emit(':tellWithCard', speechOutput, 'test skill name', randomFact);
            }
        );

您的子网/NAT设置中可能存在错误配置。要验证您的函数是否可以调用
api.forismatic.com
,请将lambda从vpc中取出。完成后,您可以重新访问网络设置。您也不会调用Handler中提供的
回调
函数。如果Lambda函数位于专有网络中,则它将无法访问专有网络之外的任何资源。如果希望Lambda功能能够访问专有网络资源和外部资源,则必须将Lambda功能放置在专有网络的私有子网中,该子网具有到NAT网关的路由。我看不到您在Lambda函数中实际执行任何需要VPC访问的操作。如果你真的不需要VPC访问,最快的修复方法就是从你的VPC中删除你的功能。@Unglückspilz我已经用lambda从VPC中删除了它,结果是一样的。我用新信息编辑了这篇文章。另外,不确定您的意思是什么,它没有调用处理程序中的回调函数。我对node不太熟悉,但我看到的所有示例似乎都与我尝试使用的代码相匹配。@MarkB我在没有VPC的情况下尝试了它,得到了相同的结果。
httpsGet(myRequest,  (myResult) => {
                console.log("sent     : " + myRequest);
                console.log("received : " + myResult);

                this.response.speak('The population of ' + myRequest + ' is ' + myResult);
                this.emit(':responseReady');

                // Create speech output
                // Place holder
                var randomFact = 'Test Fact';
                const speechOutput = randomFact;
                this.emit(':tellWithCard', speechOutput, 'test skill name', randomFact);
            }
        );