在调用一些 API 或抓取网页的时候可能需要发送 GET 或 POST 请求,这里就来简单写一下 Node.js 发送 GET 和 POST 请求。

在浏览器中可以用 XMLHttpRequest 发送 GET 和 POST 请求,而在 Node 中就没有 XMLHttpRequest API,不过 Node 也提供了一些模块用来发送 GET 和 POST 请求,这里要用的 HTTP 和 HTTPS 模块就能发送 GET 和 POST 请求。

GET 请求

下面使用 HTTP 模块给本地的 localhost 的 PHP 发送一个 GET 请求:

const http = require('http');  // 引入 HTTP 模块
// 调用 request 方法发送 get 请求
const req = http.request({
  hostname: 'localhost',
  path: '/php/test/api.php',
  port: 80,
  method: 'GET'
}, res => {
  // 如果状态码不是 200 就在控制台输出状态码
  if (res.statusCode !== 200) console.log(res.statusCode);

  res.on('data', d => {
    // 把接收到的数据转为字符串在控制台输出
    console.log(d.toString());
  });
});

// 如果出错就在控制台输出错误信息
req.on('error', err => {
  console.log(err);
});

req.end();  // 结束

上面给 localhost/php/test/api.php 发送 GET 请求,然后在控制台输出接收到的数据。

下面是 HTTP 模块的简单说明:

http.request(options[, callback])

发送 HTTP 请求,options 参数是选项 需要传入一个对象,callback 参数是一个回调函数。

下面简单写一下上面用到的选项:

  • hostname :请求的 IP 或域名
  • path :请求的页面路径
  • port :服务器的端口
  • method :请求方法,默认为 GET

请求成功会触发 response 事件,也包括 response 上的 data 事件,也就是上面的 res

data 事件接收到的数据是一个 Buffer ,可以使用 toString() 方法转为字符串。

请求结束需要调用 end() 方法,end() 可以传入一个回调函数。

如果需要发送数据可以把数据写在 URL 后面,也就是 path 后面,如下:

const options = {
  hostname: 'localhost',
  path: '/php/test/api.php?id=2&name=blog',
  port: 80,
  method: 'GET'
};

如果需要发送的键值对较多的话,可以使用对象来定义键值对,然后用 querystring 模块转为 URL 键值对。

简单演示:

const querystring = require('querystring');  // 引入 querystring 模块
// 要发送的键值对
let data = {
  id: 2,
  title: 'Tutorial',
  content: 'This is JavaScript tutorial'
};
// 转为 URL 键值对
data = querystring.stringify(data);
console.log(data);

转换后的 URL 键值对如下:

id=2&title=Tutorial&content=This%20is%20JavaScript%20tutorial

querystring.stringify 在转换时会对特殊字符进行 URL 编码。

HTTP 模块还有个 get 方法也可以发送 GET 请求,如下:

const http = require('http');  // 引入 HTTP 模块
// 调用 get 方法发送 get 请求
const get = http.get({
  hostname: 'localhost',
  path: '/php/test/api.php',
  port: 80
}, res => {
  // 如果状态码不是 200 就输出状态码
  if (res.statusCode !== 200) console.log(res.statusCode);

  res.on('data', d => {
    // 把接收到的数据转为字符串在控制台输出
    console.log(d.toString());
  });
});

get.on('error', err => {
  console.log(err);
});

get.end();  // 结束

参数之类的和 request 方法差不多,只是没有 method 选项。

POST 请求

下面还是使用 HTTP 的 request 方法来发送 POST 请求:

const http = require('http');  // 引入 HTTP 模块

const data = 'id=1&name=Louis';  // 要发送的内容
// 使用 request 方法发送 POST 请求
const req = http.request({
  hostname: 'localhost',
  path: '/php/test/api.php',
  port: 80,
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': data.length
  }
}, res => {
  // 如果状态码不是 200 就输出状态码
  if (res.statusCode !== 200) console.log(res.statusCode);

  res.on('data', d => {
    // 把接收到的内容转为字符串在控制台输出
    console.log(d.toString())
  });
});

// 设置要发送的内容
req.write(data);
// 如果出错就在控制台输出错误信息
req.on('error', err => {
  console.log(err);
});

req.end();  // 结束

发送 POST 请求和 GET 请求差不多,POST 选项 methodPOSTheaders 是请求头,Content-Type 是发送的内容类型,方便服务端解析,这里的类型是 application/x-www-form-urlencoded ,也就是最常见的表单类型,Content-Length 是内容长度,这里直接获取了要发送的内容的长度。

requestwrite 方法可以把数据写入请求主体,在发送 POST 请求的时候数据就需要放到 write 里。

HTTPS

HTTPS 和 HTTP 模块差不多,如果你请求的服务器使用了 HTTPS 的话建议使用 HTTPS,下面使用 HTTPS 的 request 方法发送 GET 请求:

const https = require('https');  // 引入 HTTPS 模块

const req = https.request({
  hostname: 'www.misterma.com',
  path: '/sitemap.xml',
  port: 443,
  method: 'GET'
}, res => {
  // 如果状态码不是 200 就输出状态码
  if (res.statusCode !== 200) console.log(res.statusCode);

  res.on('data', d => {
    // 把接收到的内容转为字符串在控制台输出
    console.log(d.toString());
  });
});

// 如果出错就输出错误信息
req.on('error', err => {
  console.log(err);
});

req.end();  // 结束

HTTPS 的默认端口一般是 443,HTTP 的默认端口一般是 80。

HTTPS 发送 POST 请求和上面的 HTTP 差不多,这里就不写了。