在Node.js Express中进行HTTP GET请求

228

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


在 Node.js 18 中,默认情况下在全局范围内提供了 fetch API。 - Abolfazl Roshanzamir
13个回答

243

这是从我的一个示例中获取的一段代码片段。它是异步的,并返回一个JSON对象。它可以执行任何形式的GET请求。

请注意,有更优化的方式(只是一个示例) - 例如,不是将您放入数组并连接的块串联起来等等...希望它能让您朝着正确的方向开始:

const http = require('http');
const https = require('https');

/**
 * getJSON:  RESTful GET request returning JSON object(s)
 * @param options: http options object
 * @param callback: callback to pass the results JSON object(s) back
 */

module.exports.getJSON = (options, onResult) => {
  console.log('rest::getJSON');
  const port = options.port == 443 ? https : http;

  let output = '';

  const req = port.request(options, (res) => {
    console.log(`${options.host} : ${res.statusCode}`);
    res.setEncoding('utf8');

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

    res.on('end', () => {
      let obj = JSON.parse(output);

      onResult(res.statusCode, obj);
    });
  });

  req.on('error', (err) => {
    // res.send('error: ' + err.message);
  });

  req.end();
};

通过创建像这样的选项对象来调用:

const options = {
  host: 'somesite.com',
  port: 443,
  path: '/some/path',
  method: 'GET',
  headers: {
    'Content-Type': 'application/json'
  }
};

同时提供一个回调函数。

例如,在服务中,我需要使用 REST 模块,然后执行以下操作:

rest.getJSON(options, (statusCode, result) => {
  // I could work with the resulting HTML/JSON here. I could also just return it
  console.log(`onResult: (${statusCode})\n\n${JSON.stringify(result)}`);

  res.statusCode = statusCode;

  res.send(result);
});

更新

如果你正在寻找支持async/await(线性,无回调)、Promises、编译时支持和智能提示的轻量级HTTP和REST客户端,我们已经创建了一个符合这些要求的客户端:

Microsoft typed-rest-client


1
@bryanmac,如果您允许的话,我想使用我目前正在构建的这个grunt插件代码。不确定何时完成,但将在完成后开源。 - JeffH
@JeffH - 没问题。这里没有什么高深的技术,只是标准的HTTP调用 :) - bryanmac
3
尝试使用请求模块,它更简单:http://www.sitepoint.com/making-http-requests-in-node-js/ - saurshaz
6
是的 - 请求模块很简单,但这是更底层的展示,展示了像请求模块这样的库正在做什么。如果您需要更低级别的控制或HTTP请求(在大型下载中显示进度等...),则此示例展示了如何实现。 - bryanmac
1
@KrIsHnA - Node.js有一个querystring对象:https://nodejs.org/api/querystring.html和一个url对象:https://nodejs.org/docs/latest/api/url.html。 - bryanmac
显示剩余7条评论

109

尝试使用node.js中简单的http.get(options, callback)函数:

var http = require('http');
var options = {
  host: 'www.google.com',
  path: '/index.html'
};

var req = http.get(options, function(res) {
  console.log('STATUS: ' + res.statusCode);
  console.log('HEADERS: ' + JSON.stringify(res.headers));

  // Buffer the body entirely for processing as a whole.
  var bodyChunks = [];
  res.on('data', function(chunk) {
    // You can process streamed parts here...
    bodyChunks.push(chunk);
  }).on('end', function() {
    var body = Buffer.concat(bodyChunks);
    console.log('BODY: ' + body);
    // ...and/or process the entire body here.
  })
});

req.on('error', function(e) {
  console.log('ERROR: ' + e.message);
});

另外还有一个通用的http.request(options, callback)函数,允许您指定请求方法和其他请求细节。


OP要求的服务器响应内容在哪里? - Dan Dascalescu
谢谢更新。看起来需要一个“结束”处理程序来连接这些块。这基本上就等于@bryanmac的答案,对吗? - Dan Dascalescu
@DanDascalescu:如果你想将整个正文作为一个整体处理(这很有可能),那么你可能需要进行缓冲并在“结束”时处理。为了完整起见,我也会更新我的答案。 - maerics
抱歉,我无法确定回调函数使用了哪些参数...我该如何获取正文并且那些参数的属性和参考文献在哪里。 - Muhammad Umer
@maerics 我如何使用这个GET请求,如果我有这个网址? graph.facebook.com/debug_token? input_token={token-to-inspect} &access_token={app-token-or-admin-token} ? - frank17
Node团队为什么选择不包含一个方便的方法来连接请求体?几乎每个网页上的https请求片段都包含了这种繁琐的连接方式,其中许多是错误的、低效的或者不够优化的。 - Kevin McDonough

73

RequestSuperagent这两个库非常好用。

注意: request库已经弃用,使用时需要自行承担风险!

使用request库:

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
});

7
第二个 if 语句中应该是 res.statusCode === 200 吗? - Gleb Dolzikov
1
选项变量是什么?只传递未定义的变量吗?我有疑问。 - lxknvlk
npm 的 request 模块已被弃用。 - João Pimentel Ferreira

37
你可以使用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();
  }
);

1
如果现有的工具集已经足够,那么“尝试其他工具”不是一个可接受的回答。 - Sean Munson
7
当然,另一种解决方案总是好事。 - Coty Embry

14

这个版本基于最初由bryanmac 提出的函数,该函数使用了 promises、更好的错误处理,并且是使用 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()返回一个Promise。在以下示例中,该函数在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);
    });
});

在错误情况下,它将错误委托给服务器错误处理中间件。


1
是的,这个例子展示了如何在Express的get路由定义中实现它,而许多帖子在这方面缺乏。 - Micros
在你的第二段代码中,关于这个express example,它看起来像是服务器端的代码,而第一段代码则是客户端的代码。第二段代码中的rest.getJSON是什么?这是一个笔误,应该是res.getJSON吗? - Timo
rest 是在第一个代码块中导出的对象。因此,为了访问 getJSON(),您可以导入整个 rest 对象或仅从第一个文件中导入 getJSON。它们都是服务器端摘录。 - maqduni

9

Unirest是我在Node中使用的最好的HTTP请求库。它旨在成为一个多平台框架,因此如果您需要在Ruby、PHP、Java、Python、Objective C、.Net或Windows 8上使用HTTP客户端,学习如何在Node上使用它将对您有所帮助。据我所知,unirest库大多数都由现有的HTTP客户端支持(例如,在Java上,使用Apache HTTP客户端,在Node上,Mikeal's Request libary)—— Unirest只是在其之上提供了更好的API。

这里有一些Node.js的代码示例:

var unirest = require('unirest')

// GET a resource
unirest.get('http://httpbin.org/get')
  .query({'foo': 'bar'})
  .query({'stack': 'overflow'})
  .end(function(res) {
    if (res.error) {
      console.log('GET error', res.error)
    } else {
      console.log('GET response', res.body)
    }
  })

// POST a form with an attached file
unirest.post('http://httpbin.org/post')
  .field('foo', 'bar')
  .field('stack', 'overflow')
  .attach('myfile', 'examples.js')
  .end(function(res) {
    if (res.error) {
      console.log('POST error', res.error)
    } else {
      console.log('POST response', res.body)
    }
  })

您可以直接跳转到Node文档这里


4

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


4

请查看shred。这是一个由spire.io创建和维护的node HTTP客户端,可处理重定向、会话和JSON响应。它非常适合与rest API交互。更多详情请查看此博客文章


3

对于任何想在NodeJS中发送HTTP请求的人,axios也是一个不错的选择。它支持Promises :)

安装 (npm): npm install axios

示例GET请求:

const axios = require('axios');

axios.get('https://google.com')
  .then(function (response) {
    // handle success
    console.log(response);
  })
  .catch(function (error) {
    // handle error
    console.log(error);
  })

Github页面


更新于2022年10月02日

Node.js在实验模式下将fetch集成在v17.5.0中。现在,您可以像在客户端一样使用fetch发送请求。目前,这是一个实验性功能,所以要小心。 在这里输入图片描述


0

如果您只需要进行简单的GET请求,并且不需要支持任何其他HTTP方法,请查看:simple-get

var get = require('simple-get');

get('http://example.com', function (err, res) {
  if (err) throw err;
  console.log(res.statusCode); // 200
  res.pipe(process.stdout); // `res` is a stream
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接