如何从Node.js或Express.js中发出HTTP请求?我需要连接到另一个服务。我希望调用是异步的,并且回调包含远程服务器的响应。


当前回答

你也可以使用Requestify,这是我为nodeJS +编写的一个非常酷且非常简单的HTTP客户端,它支持缓存。

只需对GET方法请求执行以下操作:

var requestify = require('requestify');

requestify.get('http://example.com/api/resource')
  .then(function(response) {
      // Get the response body (JSON parsed or jQuery object for XMLs)
      response.getBody();
  }
);

其他回答

这个版本是基于bryanmac函数最初提出的,它使用承诺,更好的错误处理,并在ES6中重写。

let http = require("http"),
    https = require("https");

/**
* getJSON:  REST get request returning JSON object(s)
* @param options: http options object
*/
exports.getJSON = function (options) {
    console.log('rest::getJSON');
    let reqHandler = +options.port === 443 ? https : http;

    return new Promise((resolve, reject) => {
        let req = reqHandler.request(options, (res) => {
            let output = '';
            console.log('rest::', options.host + ':' + res.statusCode);
            res.setEncoding('utf8');

            res.on('data', function (chunk) {
                output += chunk;
            });

            res.on('end', () => {
                try {
                    let obj = JSON.parse(output);
                    // console.log('rest::', obj);
                    resolve({
                        statusCode: res.statusCode,
                        data: obj
                    });
                }
                catch (err) {
                    console.error('rest::end', err);
                    reject(err);
                }
            });
        });

        req.on('error', (err) => {
            console.error('rest::request', err);
            reject(err);
        });

        req.end();
    });
};

因此,您不必传入回调函数,而是getJSON()返回一个承诺。在下面的例子中,该函数在ExpressJS路由处理程序中使用

router.get('/:id', (req, res, next) => {
    rest.getJSON({
        host: host,
        path: `/posts/${req.params.id}`,
        method: 'GET'
    }).then(({ statusCode, data }) => {
        res.json(data);
    }, (error) => {
        next(error);
    });
});

当出现错误时,它将错误委托给服务器错误处理中间件。

如果你需要向一个IP和一个域发送GET请求(其他答案没有提到你可以指定一个端口变量),你可以使用这个函数:

function getCode(host, port, path, queryString) {
    console.log("(" + host + ":" + port + path + ")" + "Running httpHelper.getCode()")

    // Construct url and query string
    const requestUrl = url.parse(url.format({
        protocol: 'http',
        hostname: host,
        pathname: path,
        port: port,
        query: queryString
    }));

    console.log("(" + host + path + ")" + "Sending GET request")
    // Send request
    console.log(url.format(requestUrl))
    http.get(url.format(requestUrl), (resp) => {
        let data = '';

        // A chunk of data has been received.
        resp.on('data', (chunk) => {
            console.log("GET chunk: " + chunk);
            data += chunk;
        });

        // The whole response has been received. Print out the result.
        resp.on('end', () => {
            console.log("GET end of response: " + data);
        });

    }).on("error", (err) => {
        console.log("GET Error: " + err);
    });
}

不要错过文件顶部的require模块:

http = require("http");
url = require('url')

另外请记住,您可以使用https模块在安全的网络上进行通信。所以这两条线会改变:

https = require("https");
...
https.get(url.format(requestUrl), (resp) => { ......

看看httpreq:这是我创建的一个节点库,因为我很沮丧,没有简单的http GET或POST模块;-)

看看shred。它是由spire创建和维护的节点HTTP客户端。io处理重定向、会话和JSON响应。它非常适合与rest api交互。详见这篇博客文章。

Request和Superagent是非常好的库。

注意:请求已弃用,使用风险自负!

使用要求:

var request=require('request');

request.get('https://someplace',options,function(err,res,body){
  if(err) //TODO: handle err
  if(res.statusCode === 200 ) //etc
  //TODO Do something with response
});