Node.js undici 库请求示例详解
什么是 undici
undici 是 Node.js 官方团队开发的高性能 HTTP/1.1 客户端库,旨在提供比内置 http
模块更高效、更现代的 HTTP 请求能力。它支持 Promise API、流式处理、连接池等特性,特别适合需要高性能 HTTP 客户端的场景。
基础请求示例
简单 GET 请求
const { request } = require('undici')
async function getRequest(port = 3001) {
const {
statusCode,
headers,
body
} = await request(`http://localhost:${port}/`)
const data = await body.text()
console.log('响应状态码:', statusCode)
console.log('响应头:', headers)
console.log('响应数据:', data)
}
关键点解析:
request
方法返回一个 Promise,可以使用 async/await 处理- 响应对象包含
statusCode
、headers
和body
三个主要部分 body
对象提供了多种解析方法,.text()
用于获取文本内容
JSON POST 请求
const { request } = require('undici')
async function postJSONRequest(port = 3001) {
const requestBody = { hello: 'JSON POST 示例数据' }
const {
statusCode,
headers,
body
} = await request(
`http://localhost:${port}/json`,
{
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(requestBody)
}
)
const decodedJson = await body.json()
console.log('响应状态码:', statusCode)
console.log('响应头:', headers)
console.log('JSON 数据:', decodedJson)
}
技术要点:
- 设置
method: 'POST'
指定请求方法 - 必须设置
Content-Type: application/json
头 - 请求体需要使用
JSON.stringify()
序列化 - 响应体使用
.json()
方法解析为 JavaScript 对象
表单请求处理
URL 编码表单提交
const { request } = require('undici')
const qs = require('node:querystring')
async function postFormRequest(port = 3001) {
const requestBody = { hello: 'URL 编码表单数据' }
const {
statusCode,
headers,
body
} = await request(
`http://localhost:${port}/form`,
{
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
body: qs.stringify(requestBody)
}
)
const data = await body.text()
console.log('响应状态码:', statusCode)
console.log('响应头:', headers)
console.log('响应数据:', data)
}
注意事项:
- 使用
querystring
模块的stringify
方法格式化表单数据 - 设置正确的
Content-Type
头为application/x-www-form-urlencoded
- 这种格式适合简单的键值对数据提交
多部分表单数据 (FormData) 提交
const { request } = require('undici')
const { openAsBlob } = require('fs')
async function formDataBlobRequest() {
const formData = new FormData()
formData.append('field', 42)
formData.set('file', await openAsBlob('./index.mjs'))
const {
statusCode,
headers,
body
} = await request('http://127.0.0.1:3000', {
method: 'POST',
body: formData
})
const data = await body.text()
console.log('响应状态码:', statusCode)
console.log('响应头:', headers)
console.log('响应数据:', data)
}
高级特性:
- 使用现代
FormData
API 构建多部分表单 - 可以混合普通字段和文件上传
openAsBlob
方法以 Blob 形式读取文件,适合大文件上传- undici 会自动设置正确的
Content-Type
和边界标识
其他 HTTP 方法
DELETE 请求示例
const { request } = require('undici')
async function deleteRequest(port = 3001) {
const {
statusCode,
headers,
body
} = await request(
`http://localhost:${port}/something`,
{ method: 'DELETE' }
)
console.log('响应状态码:', statusCode)
console.log('响应头:', headers)
if (statusCode === 204) {
console.log('删除成功')
await body.dump() // 清空响应体
} else {
const data = await body.text()
console.log('收到意外响应:', data)
}
}
最佳实践:
- RESTful API 通常使用 204 No Content 响应成功的 DELETE 请求
- 即使不需要响应体,也应该调用
body.dump()
释放资源 - 处理异常情况时读取响应体获取错误信息
生产环境配置
使用拦截器增强功能
import { Agent, interceptors, setGlobalDispatcher } from 'undici'
const { cache, dns, retry } = interceptors
const defaultDispatcher = new Agent({
connections: 100, // 连接池大小
headersTimeout: 10_000, // 头超时时间
bodyTimeout: 10_000, // 体超时时间
}).compose(cache(), dns(), retry())
setGlobalDispatcher(defaultDispatcher)
生产级配置详解:
-
连接池管理:
connections: 100
限制最大并发连接数,避免资源耗尽- 根据服务器负载能力调整此值
-
超时设置:
headersTimeout
控制等待响应头的超时bodyTimeout
控制接收响应体的超时- 根据网络状况和服务响应时间调整
-
拦截器组合:
cache()
提供响应缓存功能dns()
缓存 DNS 查询结果retry()
实现请求失败自动重试
-
全局调度器:
setGlobalDispatcher
使配置对所有请求生效- 确保应用内 HTTP 请求行为一致
总结
undici 提供了现代化、高性能的 HTTP 客户端能力,通过本文的示例可以看到:
- 支持各种 HTTP 方法和内容类型
- 提供简洁的 Promise API 和流式处理
- 内置对 FormData 和文件上传的支持
- 可通过拦截器扩展功能
- 适合生产环境的高性能配置
对于需要高性能 HTTP 客户端的 Node.js 应用,undici 是一个值得考虑的解决方案,特别是当内置 http
模块无法满足性能需求时。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考