我试图将chatbot API集成到node js应用程序中。从chatbot获得响应后,我试图调用REST API(托管在HTTPS服务器上),但它引发以下错误。我以为POST请求有问题,所以我也尝试了GET请求,但它抛出了同样的错误。

Exception has occurred: TypeError
TypeError: **First argument must be a string or Buffer**
    at write_ (_http_outgoing.js:645:11)
    at ServerResponse.write (_http_outgoing.js:620:10)
    at IncomingMessage.<anonymous> (c:\Users\ChatBot.js:107:26)
    at emitOne (events.js:116:13)
    at IncomingMessage.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)
    at IncomingMessage.Readable.push (_stream_readable.js:208:10)
    at HTTPParser.parserOnBody (_http_common.js:141:22)


以下是mychatbot.js代码

const request = require('request');
const auth = require('basic-auth');
const url = require('url');
const http = require('http');

const port = '3008';
const botId = '[email protected]';
const secretKey = 'password1234';

if (!botId || !secretKey) {
    console.error(`Usage: <script> <port> <botId> <secret>`);
    process.exit(1);
}

// Start the express server
let app = startHttpServer();

registerBot(botId, secretKey, port)
    .then(() => {
        console.log('Chatbot registered and ready to receive messages...');
    })
    .catch(error => {
        console.error('Error registering chat bot:', error);
        process.exit(2);
    });

// Handle the message and generate the response
function getResponse(from, message) {
    if (message.indexOf('prod') > -1) {
        // Call the REST API to get information for requested product
        var messageArray = message.split(' ');
        return getProductData(messageArray[1]);
    } else {
        return `Hello <span style='color:blue;'>${from}</span>, you said: <span style='color:red;'>${message}</span>`;
    }
}

function getProductData(message) {
    var postURL = "https://myexample.com:8443/Products/SearchProduct";

    var query = "db.Products.find( { $and : [{ productID : '" + message + "' }, { recTime : {$lt : '2018-05-23T23:59:59Z' }}, { recTime : {$gt : '2018-05-22T23:59:59Z' }} ] },  {productID:1,productType:1,productCol:1 } ).sort({_id:-1}).limit(10)";


    /* Try with GET request
    request.get(
        'https://myexample.com:8443/Products/AllProduct',
        function (error, response, body) {
            if (!error && response.statusCode == 200) {
                console.log(body)
            }
        }
    );
    */

    // Try with POST request
    request.post(
        'https://myexample.com:8443/Products/SearchProduct',
        { json: { query: query } },
        function (error, response, body) {
            if (!error && response.statusCode == 200) {
                console.log(body)
            }
        }
    );
}

function startHttpServer() {
    const server = http.createServer((request, response) => {

        let message;
        // How to get the message body depends on the Method of the request
        if (request.method === 'POST') {
            var body = '';

            request.on('data', function (data) {
                body += data;
            });

            request.on('end', function () {
                 var post = JSON.parse(body);
                 response.writeHead(200);
                 response.write(getResponse(post.from, post.message), "UTF8");
                 response.end();
            });
        }
        else if (request.method === 'GET') {
            var p = url.parse(request.url, true);
            response.writeHead(200);
            response.write(getResponse(p.query.from, p.query.message), "UTF8");
            response.end();
        }
    });

    server.listen(Number(port));
    return server;
}

// Dynamically register the bot's URL on startup
function registerBot(id, secret, port) {
    return new Promise((resolve, reject) => {
        request
            .post('http://mrchatbots.com:19219/registerurl', {
                proxy: '',
                body: `http://auto:${port}`,
                headers: {
                    'Content-Type': 'text/plain'
                }
            })
            .auth(id, secret)
            .on('response', (response) => {
                if (response.statusCode !== 200) {
                    reject(response.statusMessage);
                    return;
                }
                resolve();
            });
    });
}

最佳答案

req.write()使用stringBuffer,但您传递的是undefined

response.write(getResponse(post.from, post.message), "UTF8");


getResponse在调用undefined时返回getProductData,因为它没有返回值,并且是一个异步函数。

getProductData是异步的,但您将其视为同步。

您应该用request包装Promise或使用request-promise包。然后,您可以在async/await侦听器上使用request.on('end'),直到getProductData完成。

function getProductData(message) {
    var postURL = "https://myexample.com:8443/Products/SearchProduct";

    var query = "...";

    return new Promise((resolve, reject) => {

        request.post(
            'https://myexample.com:8443/Products/SearchProduct',
            { json: { query: query } },
            function (error, response, body) {
                if (!error && response.statusCode == 200) {
                    return resolve(body);
                }

                reject(error || body);
            }
        );

    });
}


function startHttpServer() {
    const server = http.createServer((request, response) => {

        let message;
        // How to get the message body depends on the Method of the request
        if (request.method === 'POST') {

            /* ... */
            request.on('end', async function () {
                              // ^^ notice async
                 var post = JSON.parse(body);
                 response.writeHead(200);
                 response.write(await getResponse(post.from, post.message), "UTF8");
                 response.end();
            });
        }

        /* ... */
        // Do the same for GET requests
    });

    server.listen(Number(port));
    return server;
}

10-04 13:03