【问题标题】:Node.js http.request Express multiple requests with single res.renderNode.js http.request 用单个 res.render 表达多个请求
【发布时间】:2017-11-14 20:16:20
【问题描述】:

我已经成功找出了 node.js/Express 代码,用于向我的服务器发出单个 http.request。但是,下一步是发出多个请求,最后使用相同的 res.render 语句。

这是我成功的工作代码:

module.exports = function (app) {
    // MODULES - INCLUDES
    var xml2js = require('xml2js');
    var parser = new xml2js.Parser();

    // FORM - SUBMIT - CUCMMAPPER
    app.post('/cucmmapper/submit', function (req, res) {

        // FORM - DATA COLLECTION
        var cucmpub = req.body.cucmpub;
        var cucmversion = req.body.cucmversion;
        var username = req.body.username;
        var password = req.body.password;

        // JS - VARIABLE DEFINITION
        var authentication = username + ":" + password;
        var soapreplyx = '';
        var cssx = '';
        var spacer = '-----';
        var rmline1 = '';
        var rmline2 = '';
        var rmline3 = '';
        var rmline4 = '';
        var rmbottomup1 = '';
        var rmbottomup2 = '';
        var rmbottomup3 = '';

        // HTTP.REQUEST - BUILD CALL
        var https = require("https");
        var headers = {
            'SoapAction': 'CUCM:DB ver=' + cucmversion + ' listCss',
            'Authorization': 'Basic ' + new Buffer(authentication).toString('base64'),
            'Content-Type': 'text/xml; charset=utf-8'
        };

        // SOAP - AXL CALL
        var soapBody = new Buffer('<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/11.5">' +
            '<soapenv:Header/>' +
            '<soapenv:Body>' +
            '<ns:listCss sequence="?">' +
            '<searchCriteria>' +
            '<name>%</name>' +
            '</searchCriteria>' +
            '<returnedTags uuid="?">' +
            '<name>?</name>' +
            '<description>?</description>' +
            '<clause>?</clause>' +
            '</returnedTags>' +
            '</ns:listCss>' +
            '</soapenv:Body>' +
            '</soapenv:Envelope>');

        // HTTP.REQUEST - OPTIONS
        var options = {
            host: cucmpub, // IP ADDRESS OF CUCM PUBLISHER
            port: 8443, // DEFAULT CISCO SSL PORT
            path: '/axl/', // AXL URL
            method: 'POST', // AXL REQUIREMENT OF POST
            headers: headers, // HEADER VAR
            rejectUnauthorized: false // REQUIRED TO ACCEPT SELF-SIGNED CERTS
        };

        // HTTP.REQUEST - Doesn't seem to need this line, but it might be useful anyway for pooling?
        options.agent = new https.Agent(options);

        // HTTP.REQUEST - OPEN SESSION
        let soapRequest = https.request(options, soapResponse => {
            soapResponse.setEncoding('utf8');
            soapResponse.on('data', chunk => {
                soapreplyx += chunk
            });
            // HTTP.REQUEST - RESULTS + RENDER
            soapResponse.on('end', () => {

                // EDIT - SCRUB XML OUTPUT
                var rmline1 = soapreplyx.replace(/<\?xml\sversion='1\.0'\sencoding='utf-8'\?>/g, '');
                var rmline2 = rmline1.replace(/<soapenv:Envelope\sxmlns:soapenv="http:\/\/schemas.xmlsoap.org\/soap\/envelope\/">/g, '');
                var rmline3 = rmline2.replace(/<soapenv:Body>/g, '');
                var rmline4 = rmline3.replace(/<ns:listCssResponse\sxmlns:ns="http:\/\/www\.cisco\.com\/AXL\/API\/[0-9]*\.[0-9]">/g, '');
                var rmbottomup1 = rmline4.replace(/<\/soapenv:Envelope>/g, '');
                var rmbottomup2 = rmbottomup1.replace(/<\/soapenv:Body>/g, '');
                var xmlscrubbed = rmbottomup2.replace(/<\/ns:listCssResponse>/g, '');
                // console.log(xmlscrubbed);
                // console.log(spacer);

                // XML2JS - TESTING
                parser.parseString(xmlscrubbed, function (err, result) {
                    var cssx = result['return']['css'];
                    //   console.log(cssx);
                    //   console.log(spacer);
                    res.render('cucmmapper-results.html', {
                        title: 'CUCM Toolbox',
                        cucmpub: cucmpub,
                        cssx: cssx,
                        soapreply: soapreplyx,
                        xmlscrubbed: xmlscrubbed
                    });
                });
            });
        });

        // SOAP - SEND AXL CALL
        soapRequest.write(soapBody);
        soapRequest.end();
    });
}

我的猜测是我必须设置几件事才能使这项工作:

  • 我的新请求的另一个“var soapBody”(我可以这样做)。
  • 另一个“让soapRequest”(我也很擅长这个)。
  • 另一个“soapRequest.write”语句(同样,很简单)。
  • 将“res.render”语句从特定的“let soapRequest”语句中分离出来并收集所有变量(这是我遇到的问题)。

我的猜测是我需要使用async。但是,我无法终生思考如何让“res.render”与异步一起工作。

这是我能得出的最接近的答案。但是,“cssx”和“partitionsx”变量不会转换为“函数完成”。它们仍然显示为 null。

module.exports = function (app) {

    // MODULES - INCLUDES
    var xml2js = require('xml2js');
    var parser = new xml2js.Parser();

    // FORM - SUBMIT - CUCMMAPPER
    app.post('/cucmmapper/submit', function (req, res) {

        // FORM - DATA COLLECTION
        var cucmpub = req.body.cucmpub;
        var cucmversion = req.body.cucmversion;
        var username = req.body.username;
        var password = req.body.password;

        // JS - VARIABLE DEFINITION - GLOBAL
        var authentication = username + ":" + password;
        var soapreplyx = '';
        var cssx = null;
        var spacer = '-----';
        var rmline1 = '';
        var rmline2 = '';
        var rmline3 = '';
        var rmline4 = '';
        var rmbottomup1 = '';
        var rmbottomup2 = '';
        var rmbottomup3 = '';
        var soapreplyp = '';
        var partitionsx = null;
        var rmline1p = '';
        var rmline2p = '';
        var rmline3p = '';
        var rmline4p = '';
        var rmbottomup1p = '';
        var rmbottomup2p = '';
        var rmbottomup3p = '';

        // HTTP.REQUEST - BUILD CALL - GLOBAL
        var https = require("https");
        var headers = {
            'SoapAction': 'CUCM:DB ver=' + cucmversion + ' listCss',
            'Authorization': 'Basic ' + new Buffer(authentication).toString('base64'),
            'Content-Type': 'text/xml; charset=utf-8'
        };

        // SOAP - AXL CALL - CSS
        var soapBody = new Buffer('<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/11.5">' +
            '<soapenv:Header/>' +
            '<soapenv:Body>' +
            '<ns:listCss sequence="?">' +
            '<searchCriteria>' +
            '<name>%</name>' +
            '</searchCriteria>' +
            '<returnedTags uuid="?">' +
            '<name>?</name>' +
            '<description>?</description>' +
            '<clause>?</clause>' +
            '</returnedTags>' +
            '</ns:listCss>' +
            '</soapenv:Body>' +
            '</soapenv:Envelope>');

        // SOAP - AXL CALL - PARTITIONS
        var soapBody2 = new Buffer('<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/11.5">' +
            '<soapenv:Header/>' +
            '<soapenv:Body>' +
            '<ns:listRpite{artotopm} sequence="?">' +
            '<searchCriteria>' +
            '<name>%</name>' +
            '</searchCriteria>' +
            '<returnedTags uuid="?">' +
            '<name>?</name>' +
            '</returnedTags>' +
            '</ns:listRoutePartition>' +
            '</soapenv:Body>' +
            '</soapenv:Envelope>');

        // HTTP.REQUEST - OPTIONS - GLOBAL
        var options = {
            host: cucmpub, // IP ADDRESS OF CUCM PUBLISHER
            port: 8443, // DEFAULT CISCO SSL PORT
            path: '/axl/', // AXL URL
            method: 'POST', // AXL REQUIREMENT OF POST
            headers: headers, // HEADER VAR
            rejectUnauthorized: false // REQUIRED TO ACCEPT SELF-SIGNED CERTS
        };

        // HTTP.REQUEST - GLOBAL (Doesn't seem to need this line, but it might be useful anyway for pooling?)
        options.agent = new https.Agent(options);

        // HTTP.REQUEST - OPEN SESSION - CSS
        var soapRequest = https.request(options, soapResponse => {
            soapResponse.setEncoding('utf8');
            soapResponse.on('data', chunk => {
                soapreplyx += chunk
            });
            // HTTP.REQUEST - RESULTS + RENDER
            soapResponse.on('end', () => {

                // EDIT - SCRUB XML OUTPUT
                var rmline1 = soapreplyx.replace(/<\?xml\sversion='1\.0'\sencoding='utf-8'\?>/g, '');
                var rmline2 = rmline1.replace(/<soapenv:Envelope\sxmlns:soapenv="http:\/\/schemas.xmlsoap.org\/soap\/envelope\/">/g, '');
                var rmline3 = rmline2.replace(/<soapenv:Body>/g, '');
                var rmline4 = rmline3.replace(/<ns:listCssResponse\sxmlns:ns="http:\/\/www\.cisco\.com\/AXL\/API\/[0-9]*\.[0-9]">/g, '');
                var rmbottomup1 = rmline4.replace(/<\/soapenv:Envelope>/g, '');
                var rmbottomup2 = rmbottomup1.replace(/<\/soapenv:Body>/g, '');
                var xmlscrubbed = rmbottomup2.replace(/<\/ns:listCssResponse>/g, '');
                // console.log(xmlscrubbed);
                // console.log(spacer);

                // XML2JS - TESTING
                parser.parseString(xmlscrubbed, function (err, result) {
                    var cssx = result['return']['css'];
                    //   console.log(cssx);
                    //   console.log(spacer);
                    complete();
                });
            });
        });

        // SOAP - SEND AXL CALL - CSS
        soapRequest.write(soapBody);
        soapRequest.end();

        // SOAP - SEND AXL CALL - PARTITIONS
        var soapRequest2 = https.request(options, soapResponse2 => {
            soapResponse2.setEncoding('utf8');
            soapResponse2.on('data', chunk => {
                soapreplyp += chunk
            });
            // HTTP.REQUEST - RESULTS + RENDER
            soapResponse2.on('end', () => {

                // EDIT - SCRUB XML OUTPUT
                var rmline1p = soapreplyy.replace(/<\?xml\sversion='1\.0'\sencoding='utf-8'\?>/g, '');
                var rmline2p = rmline1.replace(/<soapenv:Envelope\sxmlns:soapenv="http:\/\/schemas.xmlsoap.org\/soap\/envelope\/">/g, '');
                var rmline3p = rmline2.replace(/<soapenv:Body>/g, '');
                var rmline4p = rmline3.replace(/<ns:listCssResponse\sxmlns:ns="http:\/\/www\.cisco\.com\/AXL\/API\/[0-9]*\.[0-9]">/g, '');
                var rmbottomup1p = rmline4.replace(/<\/soapenv:Envelope>/g, '');
                var rmbottomup2p = rmbottomup1.replace(/<\/soapenv:Body>/g, '');
                var xmlscrubbedp = rmbottomup2.replace(/<\/ns:listCssResponse>/g, '');
                console.log(xmlscrubbedp);
                console.log(spacer);

                // XML2JS - TESTING
                parser.parseString(xmlscrubbedp, function (err, result) {
                    var partitionsx = result['return']['css'];
                    //   console.log(partitionsx);
                    //   console.log(spacer);
                    complete();
                });
            });
        });
        // SOAP - SEND AXL CALL - PARTITIONS
        soapRequest2.write(soapBody2);
        soapRequest2.end();

        // PAGE - RENDER
        function complete() {
            if (cssx !== null && partitionsx !== null) {
                res.render('cucmmapper-results.html', {
                    title: 'CUCM Toolbox',
                    cucmpub: cucmpub,
                    cssx: cssx,
                    partitionsx: partitionsx,
                })
            } else {
                res.render('cucmerror.html', {
                    title: 'CUCM Toolbox',
                })
            }
        };
    });
}

任何帮助或建议将不胜感激。

【问题讨论】:

  • 让我确保我清楚。您想接收一个 POST 请求,然后向另一台服务器发送多个请求,然后将响应捆绑到一个对初始 POST 的响应中,对吗?
  • @Paul,感谢您提出并阅读我的问题。澄清一下,我只想向同一个服务器发出几个 POST 请求,处理响应数据,并将所有处理后的数据显示到一个 res.render 页面。这样更有意义吗?
  • 有点。那么这里的代码就是将在多个请求过程中创建这个聚合 SOAP 响应的服务器?
  • 确实如此。这实际上是 Electron 应用程序的一部分,该应用程序向服务器查询大量信息,并将它们以漂亮的格式组合在一起。

标签: javascript node.js express async.js


【解决方案1】:

好的,所以要记住的是,在 HTTP 中总是有一个请求映射到一个响应。所以你不能发送多个请求并期望只得到一个响应。

相反,您需要让服务器跟踪发布的内容(可能在生产应用程序的数据库中),并依次响应每个请求。一种方法可能是使用部分文档进行响应,或者使用表明提交已被接受但您需要发送另一个请求以推送更多信息的其他代码进行响应,诸如此类。

但同样,您不能严格接受多个请求而不响应,然后仅在给出所有请求后才响应。

【讨论】:

  • 感谢您的提醒。我最终编辑了我的问题以显示发送的两个单独的 HTTP 请求。我相信这是正确的做法。两个请求(一个标记为“HTTP.REQUEST - OPEN SESSION - CSS”和另一个“HTTP.REQUEST - OPEN SESSION - PARTITIONS”)都返回有效响应,我能够对两者进行数据操作;我只是不知道如何从两个请求中获取数据到单独的“res.render”语句中。这样更有意义吗?
猜你喜欢
  • 2016-04-02
  • 2016-03-29
  • 1970-01-01
  • 1970-01-01
  • 2018-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多