作者选择了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 请求。然后,您将查看自定义请求的方法,例如添加标头。最后,您将发出POST
、PUT
和DELETE
请求,以便您可以修改外部服务器中的数据。
先决条件
-
本教程要求您安装了 Node.js。安装后,您将能够访问
https
本教程中使用的模块。本教程使用 Node.js 版本 10.19.0。要在 macOS 或 Ubuntu 18.04 上安装 Node.js,请按照如何在 macOS 上安装 Node.js 和创建本地开发环境或如何在 Ubuntu 18.04 上安装 Node.js 的使用 PPA 安装部分中的步骤进行操作。 -
用于发送 HTTP 请求的方法具有基于 Stream 的 API。在 Node.js 中,流是事件发射器的实例。响应来自流的数据的方式与响应来自事件的数据的方式相同。如果您很好奇,可以阅读我们的在 Node.js 中使用事件发射器指南,以更深入地了解事件发射器。
第 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
通过添加以下行来导入模块:
const https = require('https');
注意:: Node.js 有一个http
和一个https
模块。它们具有相同的功能并以类似的方式运行,但https
通过传输层安全性 (TLS/SSL)发出请求。由于您使用的 Web 服务器可通过 HTTPS 访问,因此您将使用该https
模块。如果您正在向只有 HTTP 的 URL 发出请求,那么您将使用该http
模块。
现在使用该http
对象向GET
API 发出请求以检索用户列表。您将使用JSON Placeholder,这是一个用于测试的公开 API。此 API 不会记录您在请求中所做的任何更改。它模拟真实服务器,并在您发送有效请求时返回模拟响应。
在文本编辑器中编写以下突出显示的代码:
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 状态代码。您在回调中要做的第一件事是验证状态代码是否符合您的预期。将以下代码添加到回调函数中:
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 以便您的应用程序可以使用它。
修改请求回调以包含以下代码:
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 请求时捕获错误:
...
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
您的控制台将显示此响应:
OutputRetrieved 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
模块:
const https = require('https');
接下来,创建一个包含method
键的新 JavaScript 对象:
const https = require('https');
const options = {
method: 'GET'
};
method
此对象中的键将告诉request()
函数请求使用的是什么 HTTP 方法。
接下来,在您的代码中发出请求。以下代码块突出显示了与使用该get()
方法发出的请求不同的代码。在您的编辑器中,输入以下所有行:
...
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 会认为你还有数据要添加到请求中。
保存并退出nano
用CTRL+X
,或等值用文本编辑器。
在你的终端中运行这个程序:
- node getRequestWithRequest.js
您将收到此输出,与第一个模块相同:
OutputRetrieved 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
变量和回调函数:
const https = require('https');
const options = {
method: 'GET',
};
let request = https.request(options, (res) => {
...
现在将以下属性添加到options
对象:
const https = require('https');
const options = {
host: 'jsonplaceholder.typicode.com',
path: '/users?_limit=2',
method: 'GET'
};
let request = https.request(options, (res) => {
...
您有两个属性——host
和,而不是一个字符串 URL path
。该host
是域名或你所访问的服务器的IP地址。路径是域名后的所有内容,包括查询参数(问号后的值)。
选项对象可以保存进入请求的其他有用数据。例如,您可以在选项中提供请求标头。标头通常发送有关请求的元数据。
开发者在创建 API 时,可能会选择支持不同的数据格式。一个 API 端点可能能够以 JSON、CSV或XML 格式返回数据。在这些 API 中,服务器可能会查看Accept
标头以确定正确的响应类型。
所述Accept
标头指定用户可以处理的数据的类型。虽然这些示例中使用的 API 仅返回 JSON,但您可以将Accept
标头添加到您的请求中以明确声明您需要 JSON。
添加以下代码行以附加Accept
标题:
const https = require('https');
const options = {
host: 'jsonplaceholder.typicode.com',
path: '/users?_limit=2',
method: 'GET',
headers: {
'Accept': 'application/json'
}
};
通过添加标题,你已经涵盖了在Node.js的HTTP请求发送的四种最流行的选择:host
,path
,method
,和headers
。Node.js 支持更多选项;您可以在官方 Node.js 文档中阅读更多信息以获取更多信息。
输入CTRL+X
以保存您的文件并退出nano
。
接下来,再次运行您的代码以仅使用选项发出请求:
- node getRequestWithRequest.js
结果将与您之前的运行相同:
OutputRetrieved 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 中创建一个请求。您将请求在users
API 中创建新用户。
尽管与 不同的方法GET
,您将能够在编写请求时重用先前请求中的代码POST
。但是,您必须进行以下调整:
- 将
options
对象中的方法更改为POST
- 添加标头以说明您正在上传 JSON
- 检查状态代码以确认用户已创建
- 上传新用户的数据
要进行这些更改,首先创建一个名为postRequest.js
. 在nano
或其他文本编辑器中打开此文件:
- nano postRequest.js
首先导入https
模块并创建一个options
对象:
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
请求所需的内容。您还更新了method
到POST
。最后,您在 options 中添加了一个新标题Content-Type
。此标头告诉服务器您正在上传什么类型的数据。在这种情况下,您将使用UTF-8 编码上传 JSON 数据。
接下来,使用request()
函数发出请求。这与您发出GET
请求的方式类似,但现在您要查找与 200 不同的状态代码。将以下行添加到代码末尾:
...
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
请求一起发送:
...
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
函数将其转换为字符串。
要完成此模块,请结束请求并检查错误:
...
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
将显示以下输出:
OutputAdded 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
:
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}`);
});
您首先更改对象的path
和method
属性options
。path
在这种情况下,标识您要更新的用户。当您发出请求时,您会检查响应代码是否为 200,这意味着请求没有问题。您现在上传的数据仅包含您正在更新的属性。
保存并退出nano
用CTRL+X
。
现在在你的终端中执行这个 Node.js 程序:
- node putRequest.js
您将收到此输出:
OutputUpdated 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 中的第一个用户:
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
程序会输出这个:
OutputDeleted user
{}
虽然 API 没有返回响应正文,但您仍然收到了 200 响应,因此请求没有问题。
您现在已经学习了如何DELETE
使用 Node.js 核心模块发出请求。
结论
在本教程中,你让GET
,POST
,PUT
,和DELETE
在Node.js的请求 没有安装库;这些请求是使用标准https
模块提出的。虽然GET
可以使用get()
函数发出请求,但所有其他 HTTP 方法都是通过该request()
方法完成的。
您编写的代码是为公开可用的测试 API 编写的。但是,您编写请求的方式适用于所有类型的 API。如果您想了解有关 API 的更多信息,请查看我们的API 主题页面。有关在 Node.js 中进行开发的更多信息,请返回“如何在 Node.js 中编码”系列。