360 Secure SkillHub
360 安全技能中心

Use undici for HTTP requests, fetch, connection pooling, proxies, Mock testing, interceptors, caching.

这是Node.js的高性能HTTP/1.1客户端,是Node.js v18+内置fetch的底层引擎,比axios快3-4倍。核心功能含多种请求API(request/fetch等)、连接池管理、代理、Mock测试、缓存拦截。适合需高性能HTTP请求、代理访问、接口模拟测试的场景,通过JS代码调用,输出响应状态、头部及可消费的响应体,需注意必须消费响应体避免连接泄漏,无CORS限制。

openlark
openlark
热度 27.42
最近更新 2026-05-16 09:56:46
分类:开发依赖:纯提示词应用场景:API 集成 / 代码生成 / 调试排错

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add undici
Metadata
name
undici
description
Use undici for HTTP requests, fetch, connection pooling, proxies, Mock testing, interceptors, caching. Note that undici's fetch differs from built-in fetch (no CORS, must consume body).

undici

Node.js HTTP/1.1 client, written from scratch. The underlying engine for the built-in fetch() in Node.js v18+. Current version 8.x, ESM/CJS dual mode.

Name meaning: Italian for "eleven" — 1.1 → 11 → Eleven → Undici (also a Stranger Things reference)

Trigger Scenarios

Use when the user needs HTTP requests, undici, fetch, proxied requests, or HTTP mocking.

Installation

npm i undici

Performance Hierarchy

undici.dispatch()  >  undici.request()  >  undici.stream()
>  undici.pipeline()  >  undici.fetch()  >>  node:http

Approximately 3-4x faster than axios (50 TCP connections, pipelining depth 10).

Core Usage

request() — Highest-level API, best performance

import { request } from 'undici';

const { statusCode, headers, body } = await request('http://localhost:3000/foo');
console.log(statusCode);               // 200
console.log(await body.json());        // Parse JSON

// body is a web ReadableStream, can also be read in chunks:
for await (const chunk of body) {
  console.log('chunk', chunk);
}

// ⚠️ Must consume body! Otherwise connection leaks
await body.dump(); // or .json() / .text() / for await

fetch() — Standard Web API compatible

import { fetch } from 'undici';

const res = await fetch('https://example.com');
const json = await res.json();

// With custom Agent
import { Agent } from 'undici';
const res = await fetch('https://example.com', {
  dispatcher: new Agent({ keepAliveTimeout: 10000 })
});

stream() — Stream processing

import { stream } from 'undici';
await stream('http://localhost:3000/foo', { method: 'GET' }, ({ statusCode, headers }) => {
  return new Writable({ write(chunk, _, cb) { console.log(chunk.toString()); cb(); } });
});

pipeline() — Returns a Duplex stream

import { pipeline } from 'undici';
import { Writable, Readable } from 'node:stream';

const duplex = pipeline('http://localhost:3000/foo', { method: 'POST' },
  ({ statusCode, headers }) => new Writable({ /* ... */ })
);
Readable.from(['data']).pipe(duplex);

Agent — Connection Pool Management

Agent manages connections to multiple origins, automatically reusing them:

import { Agent, setGlobalDispatcher, request } from 'undici';

const agent = new Agent({
  connections: 128,         // Max connections per origin
  pipelining: 10,           // Max pipelining depth per connection
  keepAliveTimeout: 4000,   // keep-alive timeout (ms)
  keepAliveMaxTimeout: 600000,
  bodyTimeout: 300000,
  headersTimeout: 300000,
});

setGlobalDispatcher(agent); // Set as global dispatcher
const data = await request('http://example.com');

Built-in vs undici Module

Aspect Built-in fetch() (v18+) undici Module
Dependencies Zero dependencies Requires installation
Version Bundled with Node.js Latest version
Performance High (has Web Streams overhead) request() is fastest
API Only fetch request/stream/pipeline/dispatch
Advanced features ❌ ✅ Agent/ProxyAgent/MockAgent/Interceptors
Error types TypeError wrappers More explicit error messages

FormData Consistency

⚠️ fetch and FormData must come from the same source:

// ✅ Correct: Use undici exclusively
import { fetch, FormData } from 'undici';
const body = new FormData();
body.set('name', 'value');
await fetch(url, { method: 'POST', body });

// ✅ Or call install() to replace globals
import { install } from 'undici';
install(); // After this, global fetch/FormData/WebSocket/EventSource are from undici

ProxyAgent — Proxy

import { ProxyAgent, request, fetch } from 'undici';

const proxyAgent = new ProxyAgent('http://proxy:8080');
// Or with authentication:
const proxyAgent = new ProxyAgent({
  uri: 'http://proxy:8080',
  token: `Basic ${Buffer.from('user:pass').toString('base64')}`
});

// Set as global
setGlobalDispatcher(proxyAgent);
// Or use locally
await fetch('http://example.com', { dispatcher: proxyAgent });

MockAgent — Testing Mock

import { MockAgent, setGlobalDispatcher, request } from 'undici';

const mockAgent = new MockAgent();
setGlobalDispatcher(mockAgent);

const mockPool = mockAgent.get('http://localhost:3000');
mockPool.intercept({ path: '/foo', method: 'GET' }).reply(200, { ok: true });

const { body } = await request('http://localhost:3000/foo');
console.log(await body.json()); // { ok: true }

Cache Interceptor

import { Agent, interceptors, cacheStores, setGlobalDispatcher } from 'undici';

const client = new Agent().compose(interceptors.cache({
  store: new cacheStores.MemoryCacheStore({
    maxSize: 100 * 1024 * 1024, // 100MB
  }),
  methods: ['GET', 'HEAD']
}));
setGlobalDispatcher(client);

Important Considerations

Must Consume Response Body

// ✅ Do
const { body } = await request(url);
await body.json(); // or .text() / .dump() / for await

// ❌ Don't — causes connection leaks
const { headers } = await request(url);

// ✅ Use HEAD method when only headers are needed
const headers = await fetch(url, { method: 'HEAD' }).then(r => r.headers);

No CORS

undici does not implement browser CORS. No preflight is needed in server environments. If CORS protection is required, you must implement it yourself.

body mixin can only be called once

Calling .text() after .json() will throw TypeError: unusable.

Path Separators

Always use /. \ is not supported as a path separator.

Reference Documentation

  • Low-level Dispatcher API (dispatch/handler) → references/dispatcher.md
  • Agent/Pool/Client connection management → references/connection.md