如何在 Node.js 中使用核心 HTTP 创建 HTTP 客户端

作者选择了COVID-19 救济基金来接受捐赠,作为Write for DOnations计划的一部分。

介绍

现代 Web 应用程序与其他服务器通信以完成任务是很常见的。例如,允许您在线购买图书的 Web 应用程序可能涉及客户订单服务器、图书库存服务器和支付服务器之间的通信。在此设计中,不同的服务通过 Web API 进行通信——标准格式允许您以编程方式发送和接收数据。Node.js应用程序中,您可以通过发出 HTTP 请求与 Web API 进行通信。

Node.js 捆绑了一个http和 一个https模块这些模块具有创建 HTTP 服务器的功能,以便 Node.js 程序可以响应 HTTP 请求。他们还可以向其他服务器发出 HTTP 请求。这一关键功能使 Node.js 程序员能够使用 Node.js 创建现代的、API 驱动的 Web 应用程序。由于它是核心模块,因此您无需安装任何库即可使用它。

在本教程中,您将使用该https模块向JSON Placeholder发出 HTTP 请求,这是一个用于测试目的的假REST API您将首先发出GET请求,即接收数据的标准 HTTP 请求。然后,您将查看自定义请求的方法,例如添加标头。最后,您将发出POSTPUTDELETE请求,以便您可以修改外部服务器中的数据。

先决条件

第 1 步 – 提出GET请求

当您与 API 交互时,您通常会发出GET请求以从 Web 服务器检索数据。在这一步中,您将查看两个GET在 Node.js 中发出请求的函数您的代码将从可公开访问的 API 中检索用户配置文件JSON 数组

https模块有两个发出GET请求的get()函数——只能发出GET请求的request()函数发出其他类型请求函数。您将首先使用该get()函数发出请求

提出请求 get()

使用该get()函数的HTTP 请求具有以下格式:

https.get(URL_String, Callback_Function) {
    Action
}

第一个参数是一个字符串,其中包含您要向其发出请求的端点。第二个参数是一个回调函数,用于处理响应。

首先,设置您的编码环境。在您的终端中,创建一个文件夹来存储本指南的所有 Node.js 模块:

  • mkdir requests

进入该文件夹:

  • cd requests

在文本编辑器中创建并打开一个新文件。本教程将nano在终端中使用:

  • nano getRequestWithGet.js

要在 Node.js 中发出 HTTP 请求,请https通过添加以下行来导入模块:

请求/getRequestWithGet.js
const https = require('https');

注意:: Node.js 有一个http和一个https模块。它们具有相同的功能并以类似的方式运行,但https通过传输层安全性 (TLS/SSL)发出请求由于您使用的 Web 服务器可通过 HTTPS 访问,因此您将使用该https模块。如果您正在向只有 HTTP 的 URL 发出请求,那么您将使用该http模块。

现在使用该http 对象GETAPI 发出请求以检索用户列表。您将使用JSON Placeholder,这是一个用于测试的公开 API。此 API 不会记录您在请求中所做的任何更改。它模拟真实服务器,并在您发送有效请求时返回模拟响应。

在文本编辑器中编写以下突出显示的代码:

请求/getRequestWithGet.js
const https = require('https');

let request = https.get('https://jsonplaceholder.typicode.com/users?_limit=2', (res) => { });

正如函数签名中提到的,该get()函数有两个参数。第一个是您以字符串格式向其发出请求的 API URL ,第二个是处理 HTTP 响应的回调。要从您的响应中读取数据,您必须在回调中添加一些代码。

HTTP 响应带有状态代码。状态代码是一个数字,表示响应的成功程度。200 到 299 之间的状态代码是肯定响应,而 400 和 599 之间的代码是错误。您可以在我们的如何对常见 HTTP 错误代码进行故障排除指南中了解有关状态代码的更多信息

对于此请求,成功的响应将具有 200 状态代码。您在回调中要做的第一件事是验证状态代码是否符合您的预期。将以下代码添加到回调函数中:

请求/getRequestWithGet.js
const https = require('https');

let request = https.get('https://jsonplaceholder.typicode.com/users?_limit=2', (res) => {
  if (res.statusCode !== 200) {
    console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
    res.resume();
    return;
  }
});

回调中可用的响应对象有一个statusCode存储状态代码属性。如果状态代码不是 200,则将错误记录到控制台并退出。

请注意具有res.resume(). 您包含该行以提高性能。发出 HTTP 请求时,Node.js 将使用随请求发送的所有数据。res.resume()方法告诉 Node.js 忽略流的数据。反过来,Node.js 通常会比将数据留给垃圾收集(一个释放应用程序内存的周期性过程)更快地丢弃数据

既然您已经捕获了错误响应,请添加代码来读取数据。Node.js 响应以块的形式传输其数据。检索数据的策略是侦听数据何时来自响应,整理所有块,然后解析 JSON 以便您的应用程序可以使用它。

修改请求回调以包含以下代码:

请求/getRequestWithGet.js
const https = require('https');

let request = https.get('https://jsonplaceholder.typicode.com/users?_limit=2', (res) => {
  if (res.statusCode !== 200) {
    console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
    res.resume();
    return;
  }

  let data = '';

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

  res.on('close', () => {
    console.log('Retrieved all data');
    console.log(JSON.parse(data));
  });
});

首先创建一个data空字符串的新变量您可以将数据存储为表示字节数据或字符串的数字数组。本教程使用后者,因为将 JSON 字符串转换为JavaScript 对象更容易

创建data变量后,您将创建一个事件侦听器Node.js 以块的形式流式传输 HTTP 响应的数据。因此,当响应对象发出data事件时,您将获取它接收到的数据并将其添加到您的data变量中。

当收到来自服务器的所有数据时,Node.js 会发出一个close事件。此时,您解析存储在其中的 JSON 字符串data并将结果记录到控制台。

您的 Node.js 模块现在可以与 JSON API 通信并记录用户列表,该列表将是一个包含三个用户的 JSON 数组。但是,您可以先做一个小的改进。

如果您无法发出请求,此脚本将引发错误。例如,如果您失去互联网连接,您可能无法提出请求。添加以下代码以在您无法发送 HTTP 请求时捕获错误:

请求/getRequestWithGet.js
...
  res.on('data', (chunk) => {
    data += chunk;
  });

  res.on('close', () => {
    console.log('Retrieved all data');
    console.log(JSON.parse(data));
  });

});

request.on('error', (err) => {
  console.error(`Encountered an error trying to make a request: ${err.message}`);
});

当发出请求但无法发送时,请求对象会发出一个error事件。如果一个error事件被发出但没有被监听,Node.js 程序就会崩溃。因此,要捕获错误,请使用该on()函数添加事件侦听器并侦听error事件。当您收到错误时,您会记录其消息。

这就是这个文件的所有代码。nano保存并退出CTRL+X

现在执行这个程序node

  • node getRequestWithGet.js

您的控制台将显示此响应:

Output
Retrieved all data [ { id: 1, name: 'Leanne Graham', username: 'Bret', email: '[email protected]', address: { street: 'Kulas Light', suite: 'Apt. 556', city: 'Gwenborough', zipcode: '92998-3874', geo: [Object] }, phone: '1-770-736-8031 x56442', website: 'hildegard.org', company: { name: 'Romaguera-Crona', catchPhrase: 'Multi-layered client-server neural-net', bs: 'harness real-time e-markets' } }, { id: 2, name: 'Ervin Howell', username: 'Antonette', email: '[email protected]', address: { street: 'Victor Plains', suite: 'Suite 879', city: 'Wisokyburgh', zipcode: '90566-7771', geo: [Object] }, phone: '010-692-6593 x09125', website: 'anastasia.net', company: { name: 'Deckow-Crist', catchPhrase: 'Proactive didactic contingency', bs: 'synergize scalable supply-chains' } } ]

这意味着您已成功GET向核心 Node.js 库发出请求。

get()你使用的方法是一种方便的方法Node.js的提供,因为GET请求是请求一个很常见的类型。Node.js 提供了request()一种发出任何类型请求的方法。接下来,本教程将研究如何GET使用request().

提出请求 request()

request()方法支持多个函数签名。您将在接下来的示例中使用这个:

https.request(URL_String, Options_Object, Callback_Function) {
    Action
}

第一个参数是带有 API 端点的字符串。第二个参数是一个 JavaScript 对象,包含请求的所有选项。最后一个参数是处理响应的回调函数。

为名为 的新模块创建一个新文件getRequestWithRequest.js

  • nano getRequestWithRequest.js

您将编写的代码类似于您之前编写的getRequestWithGet.js模块。首先,导入https模块:

请求/getRequestWithRequest.js
const https = require('https');

接下来,创建一个包含method的新 JavaScript 对象

请求/getRequestWithRequest.js
const https = require('https');

const options = {
  method: 'GET'
};

method此对象中键将告诉request()函数请求使用的是什么 HTTP 方法。

接下来,在您的代码中发出请求。以下代码块突出显示了与使用该get()方法发出的请求不同的代码在您的编辑器中,输入以下所有行:

请求/getRequestWithRequest.js
...

let request = https.request('https://jsonplaceholder.typicode.com/users?_limit=2', options, (res) => {
  if (res.statusCode !== 200) {
    console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
    res.resume();
    return;
  }

  let data = '';

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

  res.on('close', () => {
    console.log('Retrieved all data');
    console.log(JSON.parse(data));
  });
});

request.end();

request.on('error', (err) => {
  console.error(`Encountered an error trying to make a request: ${err.message}`);
});

要使用 发出请求request(),您需要在第一个参数中提供 URL,在第二个参数中提供一个带有 HTTP 选项的对象,并在第三个参数中提供一个用于处理响应的回调。

options您之前创建变量是第二个参数,告诉 Node.js 这是一个GET请求。回调与您第一次编写时没有变化。

您还调用end()request变量方法这是使用request()函数时必须调用的重要方法它完成请求,允许它被发送。如果你不调用它,程序将永远不会完成,因为 Node.js 会认为你还有数据要添加到请求中。

保存并退出nanoCTRL+X,或等值用文本编辑器。

在你的终端中运行这个程序:

  • node getRequestWithRequest.js

您将收到此输出,与第一个模块相同:

Output
Retrieved all data [ { id: 1, name: 'Leanne Graham', username: 'Bret', email: '[email protected]', address: { street: 'Kulas Light', suite: 'Apt. 556', city: 'Gwenborough', zipcode: '92998-3874', geo: [Object] }, phone: '1-770-736-8031 x56442', website: 'hildegard.org', company: { name: 'Romaguera-Crona', catchPhrase: 'Multi-layered client-server neural-net', bs: 'harness real-time e-markets' } }, { id: 2, name: 'Ervin Howell', username: 'Antonette', email: '[email protected]', address: { street: 'Victor Plains', suite: 'Suite 879', city: 'Wisokyburgh', zipcode: '90566-7771', geo: [Object] }, phone: '010-692-6593 x09125', website: 'anastasia.net', company: { name: 'Deckow-Crist', catchPhrase: 'Proactive didactic contingency', bs: 'synergize scalable supply-chains' } } ]

您现在已使用该request()方法发出GET请求。了解此功能很重要,因为它允许您以该get()方法无法使用的方式自定义您的请求,例如使用其他 HTTP 方法发出请求。

接下来,您将使用该request()功能配置和自定义您的请求

第 2 步 – 配置 HTTPrequest()选项

request()函数允许您发送 HTTP 请求而无需在第一个参数中指定 URL。在这种情况下,URL 将包含在options对象中,并且request()将具有以下函数签名:

https.request(Options_Object, Callback_Function) {
    Action
}

在此步骤中,您将使用此功能来配置您request()options对象。

Node.js 允许您在options传递给请求对象中输入 URL 要尝试此操作,请重新打开getRequestWithRequest.js文件:

  • nano getRequestWithRequest.js

request()调用中删除 URL,以便唯一的参数是options变量和回调函数:

请求/getRequestWithRequest.js
const https = require('https');

const options = {
  method: 'GET',
};

let request = https.request(options, (res) => {
...

现在将以下属性添加到options对象:

请求/getRequestWithRequest.js
const https = require('https');

const options = {
  host: 'jsonplaceholder.typicode.com',
  path: '/users?_limit=2',
  method: 'GET'
};

let request = https.request(options, (res) => {
...

您有两个属性——host,而不是一个字符串 URL pathhost是域名或你所访问的服务器的IP地址。路径是域名后的所有内容,包括查询参数(问号后的值)。

选项对象可以保存进入请求的其他有用数据。例如,您可以在选项中提供请求标头。标头通常发送有关请求的元数据。

开发者在创建 API 时,可能会选择支持不同的数据格式。一个 API 端点可能能够以 JSON、CSVXML 格式返回数据在这些 API 中,服务器可能会查看Accept标头以确定正确的响应类型。

所述Accept标头指定用户可以处理的数据的类型。虽然这些示例中使用的 API 仅返回 JSON,但您可以将Accept标头添加到您的请求中以明确声明您需要 JSON。

添加以下代码行以附加Accept标题:

请求/getRequestWithRequest.js
const https = require('https');

const options = {
  host: 'jsonplaceholder.typicode.com',
  path: '/users?_limit=2',
  method: 'GET',
  headers: {
    'Accept': 'application/json'
  }
};

通过添加标题,你已经涵盖了在Node.js的HTTP请求发送的四种最流行的选择:hostpathmethod,和headersNode.js 支持更多选项;您可以在官方 Node.js 文档中阅读更多信息以获取更多信息。

输入CTRL+X以保存您的文件并退出nano

接下来,再次运行您的代码以仅使用选项发出请求:

  • node getRequestWithRequest.js

结果将与您之前的运行相同:

Output
Retrieved all data [ { id: 1, name: 'Leanne Graham', username: 'Bret', email: '[email protected]', address: { street: 'Kulas Light', suite: 'Apt. 556', city: 'Gwenborough', zipcode: '92998-3874', geo: [Object] }, phone: '1-770-736-8031 x56442', website: 'hildegard.org', company: { name: 'Romaguera-Crona', catchPhrase: 'Multi-layered client-server neural-net', bs: 'harness real-time e-markets' } }, { id: 2, name: 'Ervin Howell', username: 'Antonette', email: '[email protected]', address: { street: 'Victor Plains', suite: 'Suite 879', city: 'Wisokyburgh', zipcode: '90566-7771', geo: [Object] }, phone: '010-692-6593 x09125', website: 'anastasia.net', company: { name: 'Deckow-Crist', catchPhrase: 'Proactive didactic contingency', bs: 'synergize scalable supply-chains' } } ]

由于 API 可能因提供者而异,因此options适应对象是适应其不同要求的关键,数据类型和标头是一些最常见的变化。

到目前为止,您只执行了GET检索数据的请求。接下来,您将POST使用 Node.js 发出请求,以便您可以将数据上传到服务器。

第 3 步 – 提出POST请求

当您将数据上传到服务器或希望服务器为您创建数据时,您通常会发送POST请求。在本节中,您将POST在 Node.js 中创建一个请求。您将请求在usersAPI 中创建新用户

尽管与 不同的方法GET,您将能够在编写请求时重用先前请求中的代码POST但是,您必须进行以下调整:

  • options对象中的方法更改POST
  • 添加标头以说明您正在上传 JSON
  • 检查状态代码以确认用户已创建
  • 上传新用户的数据

要进行这些更改,首先创建一个名为postRequest.js. nano或其他文本编辑器中打开此文件

  • nano postRequest.js

首先导入https模块并创建一个options对象:

请求/postRequest.js
const https = require('https');

const options = {
  host: 'jsonplaceholder.typicode.com',
  path: '/users',
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json; charset=UTF-8'
  }
};

您更改path以匹配POST请求所需的内容您还更新了methodPOST最后,您在 options 中添加了一个新标题Content-Type此标头告诉服务器您正在上传什么类型的数据。在这种情况下,您将使用UTF-8 编码上传 JSON 数据

接下来,使用request()函数发出请求这与您发出GET请求的方式类似,但现在您要查找与 200 不同的状态代码。将以下行添加到代码末尾:

请求/postRequest.js
...
const request = https.request(options, (res) => {
  if (res.statusCode !== 201) {
    console.error(`Did not get a Created from the server. Code: ${res.statusCode}`);
    res.resume();
    return;
  }

  let data = '';

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

  res.on('close', () => {
    console.log('Added new user');
    console.log(JSON.parse(data));
  });
});

突出显示的代码行检查状态代码是否为 201。201 状态代码用于指示服务器创建了资源。

POST请求旨在创建一个新用户。对于此 API,您需要上传用户详细信息。创建一些用户数据并将其与您的POST请求一起发送:

请求/postRequest.js
...

const requestData = {
  name: 'New User',
  username: 'digitalocean',
  email: '[email protected]',
  address: {
    street: 'North Pole',
    city: 'Murmansk',
    zipcode: '12345-6789',
  },
  phone: '555-1212',
  website: 'digitalocean.com',
  company: {
    name: 'DigitalOcean',
    catchPhrase: 'Welcome to the developer cloud',
    bs: 'cloud scale security'
  }
};

request.write(JSON.stringify(requestData));

您首先创建了requestData变量,它是一个包含用户数据的 JavaScript 对象。您的请求不包含id字段,因为服务器通常在保存新数据时生成这些字段。

接下来使用该request.write()函数,它接受一个字符串或缓冲区对象与请求一起发送。由于您的requestData变量是一个对象,因此您使用该JSON.stringify函数将其转换为字符串。

要完成此模块,请结束请求并检查错误:

请求/postRequest.js
...

request.end();

request.on('error', (err) => {
  console.error(`Encountered an error trying to make a request: ${err.message}`);
});

在使用end()函数之前写入数据很重要end()函数告诉 Node.js 没有更多数据要添加到请求中并发送它。

nano保存并退出CTRL+X

运行此程序以确认已创建新用户:

  • node postRequest.js

将显示以下输出:

Output
Added new user { name: 'New User', username: 'digitalocean', email: '[email protected]', address: { street: 'North Pole', city: 'Murmansk', zipcode: '12345-6789' }, phone: '555-1212', website: 'digitalocean.com', company: { name: 'DigitalOcean', catchPhrase: 'Welcome to the developer cloud', bs: 'cloud scale security' }, id: 11 }

输出确认请求成功。API 返回上传的用户数据以及分配给它的 ID。

现在您已经学会了如何发出POST请求,您可以将数据上传到 Node.js 中的服务器。接下来您将尝试PUT请求,这是一种用于更新服务器中数据的方法。

第 4 步 – 提出PUT请求

开发人员提出PUT将数据上传到服务器请求。虽然这可能类似于POST请求,但PUT请求具有不同的功能。PUT请求是幂等的——你可以PUT多次运行一个请求,它会得到相同的结果。

实际上,您编写的代码类似于POST请求的代码您可以设置选项、提出请求、编写要上传的数据并验证响应。

要尝试此操作,您将创建一个PUT请求来更新第一个用户的用户名。

由于代码与POST请求类似,您将使用该模块作为此模块的基础。将其复制postRequest.js到一个新文件中putRequest.js

  • cp postRequest.js putRequest.js

现在putRequest.js在文本编辑器中打开

  • nano putRequest.js

进行这些突出显示的更改,以便您向 发送PUT请求https://jsonplaceholder.typicode.com/users/1

请求/putRequest.js
const https = require('https');

const options = {
  host: 'jsonplaceholder.typicode.com',
  path: '/users/1',
  method: 'PUT',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json; charset=UTF-8'
  }
};

const request = https.request(options, (res) => {
  if (res.statusCode !== 200) {
    console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
    res.resume();
    return;
  }

  let data = '';

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

  res.on('close', () => {
    console.log('Updated data');
    console.log(JSON.parse(data));
  });
});

const requestData = {
  username: 'digitalocean'
};

request.write(JSON.stringify(requestData));

request.end();

request.on('error', (err) => {
  console.error(`Encountered an error trying to make a request: ${err.message}`);
});

您首先更改对象pathmethod属性optionspath在这种情况下,标识您要更新的用户。当您发出请求时,您会检查响应代码是否为 200,这意味着请求没有问题。您现在上传的数据仅包含您正在更新的属性。

保存并退出nanoCTRL+X

现在在你的终端中执行这个 Node.js 程序:

  • node putRequest.js

您将收到此输出:

Output
Updated data { username: 'digitalocean', id: 1 }

您发送了PUT更新现有用户请求。

到目前为止,您已经学习了如何检索、添加和更新数据。为了让我们通过 API 管理数据的完整命令,您接下来将DELETE发出从服务器中删除数据的请求。

第 5 步 – 提出DELETE请求

DELETE请求用于从服务器中删除数据。它可以有一个请求正文,但大多数 API 往往不需要它们。此方法用于从服务器中删除整个对象。在本节中,您将使用 API 删除用户。

您将编写的代码类似于GET请求的代码,因此请使用该模块作为此模块的基础。getRequestWithRequest.js文件复制到一个新deleteRequest.js文件中:

  • cp getRequestWithRequest.js deleteRequest.js

打开deleteRequest.js方式nano

  • nano deleteRequest.js

现在修改突出显示部分的代码,以便您可以删除 API 中的第一个用户:

请求/putRequest.js
const https = require('https');

const options = {
  host: 'jsonplaceholder.typicode.com',
  path: '/users/1',
  method: 'DELETE',
  headers: {
    'Accept': 'application/json',
  }
};

const request = https.request(options, (res) => {
  if (res.statusCode !== 200) {
    console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
    res.resume();
    return;
  }

  let data = '';

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

  res.on('close', () => {
    console.log('Deleted user');
    console.log(JSON.parse(data));
  });
});

request.end();

request.on('error', (err) => {
  console.error(`Encountered an error trying to make a request: ${err.message}`);
});

对于此模块,您首先path将选项对象属性更改为要删除的资源——第一个用户。然后将方法更改为DELETE

按 保存并退出此文件CTRL+X

运行此模块以确认它有效。在终端中输入以下命令:

  • node deleteRequest.js

程序会输出这个:

Output
Deleted user {}

虽然 API 没有返回响应正文,但您仍然收到了 200 响应,因此请求没有问题。

您现在已经学习了如何DELETE使用 Node.js 核心模块发出请求。

结论

在本教程中,你让GETPOSTPUT,和DELETE在Node.js的请求 没有安装库;这些请求是使用标准https模块提出的。虽然GET可以使用get()函数发出请求,但所有其他 HTTP 方法都是通过该request()方法完成的

您编写的代码是为公开可用的测试 API 编写的。但是,您编写请求的方式适用于所有类型的 API。如果您想了解有关 API 的更多信息,请查看我们的API 主题页面有关在 Node.js 中进行开发的更多信息,请返回“如何在 Node.js 中编码”系列

觉得文章有用?

点个广告表达一下你的爱意吧 !😁