Node.js undici 库请求示例详解

Node.js undici 库请求示例详解

undici An HTTP/1.1 client, written from scratch for Node.js undici 项目地址: https://gitcode.com/gh_mirrors/un/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)
}

关键点解析:

  1. request 方法返回一个 Promise,可以使用 async/await 处理
  2. 响应对象包含 statusCodeheadersbody 三个主要部分
  3. 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)
}

技术要点:

  1. 设置 method: 'POST' 指定请求方法
  2. 必须设置 Content-Type: application/json
  3. 请求体需要使用 JSON.stringify() 序列化
  4. 响应体使用 .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)
}

注意事项:

  1. 使用 querystring 模块的 stringify 方法格式化表单数据
  2. 设置正确的 Content-Type 头为 application/x-www-form-urlencoded
  3. 这种格式适合简单的键值对数据提交

多部分表单数据 (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)
}

高级特性:

  1. 使用现代 FormData API 构建多部分表单
  2. 可以混合普通字段和文件上传
  3. openAsBlob 方法以 Blob 形式读取文件,适合大文件上传
  4. 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)
  }
}

最佳实践:

  1. RESTful API 通常使用 204 No Content 响应成功的 DELETE 请求
  2. 即使不需要响应体,也应该调用 body.dump() 释放资源
  3. 处理异常情况时读取响应体获取错误信息

生产环境配置

使用拦截器增强功能

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)

生产级配置详解:

  1. 连接池管理

    • connections: 100 限制最大并发连接数,避免资源耗尽
    • 根据服务器负载能力调整此值
  2. 超时设置

    • headersTimeout 控制等待响应头的超时
    • bodyTimeout 控制接收响应体的超时
    • 根据网络状况和服务响应时间调整
  3. 拦截器组合

    • cache() 提供响应缓存功能
    • dns() 缓存 DNS 查询结果
    • retry() 实现请求失败自动重试
  4. 全局调度器

    • setGlobalDispatcher 使配置对所有请求生效
    • 确保应用内 HTTP 请求行为一致

总结

undici 提供了现代化、高性能的 HTTP 客户端能力,通过本文的示例可以看到:

  1. 支持各种 HTTP 方法和内容类型
  2. 提供简洁的 Promise API 和流式处理
  3. 内置对 FormData 和文件上传的支持
  4. 可通过拦截器扩展功能
  5. 适合生产环境的高性能配置

对于需要高性能 HTTP 客户端的 Node.js 应用,undici 是一个值得考虑的解决方案,特别是当内置 http 模块无法满足性能需求时。

undici An HTTP/1.1 client, written from scratch for Node.js undici 项目地址: https://gitcode.com/gh_mirrors/un/undici

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伍畅晗Praised

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值