CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-undici

An HTTP/1.1 client, written from scratch for Node.js

Pending
Overview
Eval results
Files

headers-body.mddocs/

Headers and Body Processing

HTTP headers management and request/response body handling with multiple content types and streaming support.

Capabilities

Headers

WHATWG Headers API implementation for managing HTTP headers with case-insensitive access and validation.

/**
 * HTTP headers management
 */
class Headers {
  constructor(init?: HeadersInit);
  
  append(name: string, value: string): void;
  delete(name: string): void;
  get(name: string): string | null;
  getSetCookie(): string[];
  has(name: string): boolean;
  set(name: string, value: string): void;
  
  keys(): IterableIterator<string>;
  values(): IterableIterator<string>;
  entries(): IterableIterator<[string, string]>;
  forEach(callback: (value: string, key: string, parent: Headers) => void, thisArg?: any): void;
  
  [Symbol.iterator](): IterableIterator<[string, string]>;
}

type HeadersInit = 
  | Headers 
  | Record<string, string | ReadonlyArray<string>> 
  | Iterable<readonly [string, string]>;

Usage Examples:

import { Headers } from 'undici';

// Create headers from object
const headers = new Headers({
  'Content-Type': 'application/json',
  'Authorization': 'Bearer token123'
});

// Create headers from array
const headersFromArray = new Headers([
  ['content-type', 'text/html'],
  ['cache-control', 'no-cache']
]);

// Manipulate headers
headers.append('accept', 'application/json');
headers.set('user-agent', 'my-app/1.0');
headers.delete('authorization');

// Access headers (case-insensitive)
console.log(headers.get('content-type')); // 'application/json'
console.log(headers.has('Content-Type')); // true

// Iterate headers
for (const [name, value] of headers) {
  console.log(`${name}: ${value}`);
}

headers.forEach((value, name) => {
  console.log(`${name}: ${value}`);
});

// Handle Set-Cookie headers specially
const responseHeaders = new Headers();
responseHeaders.append('set-cookie', 'session=abc123; Path=/');
responseHeaders.append('set-cookie', 'theme=dark; Path=/');

const setCookies = responseHeaders.getSetCookie();
console.log(setCookies); // ['session=abc123; Path=/', 'theme=dark; Path=/']

FormData

WHATWG FormData API implementation for handling multipart/form-data and form submissions.

/**
 * Form data handling for multipart/form-data
 */
class FormData {
  constructor();
  
  append(name: string, value: string | Blob, filename?: string): void;
  delete(name: string): void;
  get(name: string): FormDataEntryValue | null;
  getAll(name: string): FormDataEntryValue[];
  has(name: string): boolean;
  set(name: string, value: string | Blob, filename?: string): void;
  
  keys(): IterableIterator<string>;
  values(): IterableIterator<FormDataEntryValue>;
  entries(): IterableIterator<[string, FormDataEntryValue]>;
  forEach(callback: (value: FormDataEntryValue, key: string, parent: FormData) => void, thisArg?: any): void;
  
  [Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>;
}

type FormDataEntryValue = string | File;

Usage Examples:

import { FormData, fetch } from 'undici';
import { readFileSync } from 'fs';

// Create form data
const formData = new FormData();

// Add text fields
formData.append('name', 'Alice');
formData.append('email', 'alice@example.com');
formData.append('message', 'Hello world!');

// Add file data
const fileBuffer = readFileSync('./document.pdf');
const file = new Blob([fileBuffer], { type: 'application/pdf' });
formData.append('document', file, 'document.pdf');

// Submit form data
const response = await fetch('https://api.example.com/upload', {
  method: 'POST',
  body: formData
  // Content-Type header is automatically set with boundary
});

// Process existing form data
const existingFormData = new FormData();
existingFormData.append('field1', 'value1');
existingFormData.append('field2', 'value2');
existingFormData.append('field1', 'another value'); // Multiple values

console.log(existingFormData.get('field1')); // 'value1' (first value)
console.log(existingFormData.getAll('field1')); // ['value1', 'another value']

// Iterate form data
for (const [name, value] of existingFormData) {
  console.log(`${name}: ${value}`);
}

Body Processing

Body handling utilities and types for request and response body processing.

/**
 * Body mixin for consuming request/response bodies
 */
interface BodyMixin {
  readonly body: ReadableStream | null;
  readonly bodyUsed: boolean;
  
  arrayBuffer(): Promise<ArrayBuffer>;
  blob(): Promise<Blob>;
  bytes(): Promise<Uint8Array>;
  json(): Promise<any>;
  text(): Promise<string>;
}

type BodyInit = 
  | ArrayBuffer 
  | AsyncIterable<Uint8Array> 
  | Blob 
  | FormData 
  | Iterable<Uint8Array> 
  | NodeJS.ArrayBufferView 
  | URLSearchParams 
  | null 
  | string;

interface BodyReadable extends Readable {
  arrayBuffer(): Promise<ArrayBuffer>;
  blob(): Promise<Blob>;
  bytes(): Promise<Uint8Array>;
  json(): Promise<any>;
  text(): Promise<string>;
}

Usage Examples:

import { fetch, request } from 'undici';

// Process different response body types
const response = await fetch('https://api.example.com/data');

// JSON response
if (response.headers.get('content-type')?.includes('application/json')) {
  const data = await response.json();
  console.log(data);
}

// Text response
if (response.headers.get('content-type')?.includes('text/')) {
  const text = await response.text();
  console.log(text);
}

// Binary response
if (response.headers.get('content-type')?.includes('image/')) {
  const blob = await response.blob();
  const arrayBuffer = await response.arrayBuffer();
  const bytes = await response.bytes();
}

// Streaming response body
const streamResponse = await fetch('https://api.example.com/large-data');
const reader = streamResponse.body.getReader();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  
  // Process chunk
  console.log('Received chunk:', value.length, 'bytes');
}

// Using undici.request for body processing
const { body } = await request('https://api.example.com/data');
const jsonData = await body.json();

// Send different body types
await fetch('https://api.example.com/upload', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ message: 'hello' })
});

await fetch('https://api.example.com/upload', {
  method: 'POST',
  headers: { 'content-type': 'application/octet-stream' },
  body: new ArrayBuffer(1024)
});

await fetch('https://api.example.com/upload', {
  method: 'POST',
  body: new URLSearchParams({ key: 'value', name: 'test' })
});

MIME Type Processing

MIME type parsing and serialization utilities for content type handling.

/**
 * Parse MIME type strings according to WHATWG spec
 * @param input - MIME type string to parse
 * @returns Parsed MIME type object or failure
 */
function parseMIMEType(input: string): MimeType | 'failure';

/**
 * Serialize MIME type object to string
 * @param mimeType - MIME type object to serialize
 * @returns Serialized MIME type string
 */
function serializeAMimeType(mimeType: MimeType): string;

interface MimeType {
  type: string;
  subtype: string;
  parameters: Map<string, string>;
  essence: string;
}

Usage Examples:

import { parseMIMEType, serializeAMimeType } from 'undici';

// Parse MIME types
const mimeType = parseMIMEType('text/html; charset=utf-8');
if (mimeType !== 'failure') {
  console.log(mimeType.type);     // 'text'
  console.log(mimeType.subtype);  // 'html'
  console.log(mimeType.essence);  // 'text/html'
  console.log(mimeType.parameters.get('charset')); // 'utf-8'
}

// Parse complex MIME type
const complexType = parseMIMEType('application/json; charset=utf-8; boundary=something');
if (complexType !== 'failure') {
  console.log(complexType.parameters.get('boundary')); // 'something'
}

// Serialize MIME type
const serialized = serializeAMimeType({
  type: 'application',
  subtype: 'json',
  parameters: new Map([['charset', 'utf-8']]),
  essence: 'application/json'
});
console.log(serialized); // 'application/json; charset=utf-8'

// Handle parsing failures
const invalid = parseMIMEType('invalid-mime-type');
if (invalid === 'failure') {
  console.log('Failed to parse MIME type');
}

Header Utilities

Low-level header parsing utilities for advanced use cases.

/**
 * Parse raw headers into structured format
 * @param headers - Raw headers to parse
 * @returns Parsed headers object
 */
function parseHeaders(headers: Buffer | string): Record<string, string | string[]>;

/**
 * Convert header names to canonical string format
 * @param headerName - Header name to convert
 * @returns Canonical header name string
 */
function headerNameToString(headerName: string | Buffer): string;

Usage Examples:

import { parseHeaders, headerNameToString } from 'undici';

// Parse raw headers
const rawHeaders = Buffer.from(
  'Content-Type: application/json\r\n' +
  'Authorization: Bearer token123\r\n' +
  'Set-Cookie: session=abc\r\n' +
  'Set-Cookie: theme=dark\r\n'
);

const parsed = parseHeaders(rawHeaders);
console.log(parsed);
// {
//   'content-type': 'application/json',
//   'authorization': 'Bearer token123',
//   'set-cookie': ['session=abc', 'theme=dark']
// }

// Convert header names
console.log(headerNameToString('content-type'));  // 'content-type'
console.log(headerNameToString(Buffer.from('AUTHORIZATION'))); // 'authorization'

MIME Type Processing

Utilities for parsing and serializing MIME types according to RFC specifications.

/**
 * Parse a MIME type string into structured components
 * @param input - MIME type string to parse
 * @returns Parsed MIME type object or null if invalid
 */
function parseMIMEType(input: string): MIMEType | null;

/**
 * Serialize a MIME type object back into a string
 * @param mimeType - MIME type object to serialize
 * @returns Serialized MIME type string
 */
function serializeAMimeType(mimeType: MIMEType): string;

interface MIMEType {
  type: string;
  subtype: string;
  parameters: Map<string, string>;
}

Usage Examples:

import { parseMIMEType, serializeAMimeType } from 'undici';

// Parse MIME type
const mimeType = parseMIMEType('text/html; charset=utf-8; boundary=something');
console.log(mimeType);
// {
//   type: 'text',
//   subtype: 'html',
//   parameters: Map {
//     'charset' => 'utf-8',
//     'boundary' => 'something'
//   }
// }

// Create MIME type object
const customMime = {
  type: 'application',
  subtype: 'json',
  parameters: new Map([['charset', 'utf-8']])
};

// Serialize to string
const serialized = serializeAMimeType(customMime);
console.log(serialized); // 'application/json; charset=utf-8'

// Handle invalid MIME types
const invalid = parseMIMEType('not-a-valid-mime-type');
console.log(invalid); // null

Types

Content Types

interface File extends Blob {
  readonly name: string;
  readonly lastModified: number;
}

interface Blob {
  readonly size: number;
  readonly type: string;
  arrayBuffer(): Promise<ArrayBuffer>;
  bytes(): Promise<Uint8Array>;
  slice(start?: number, end?: number, contentType?: string): Blob;
  stream(): ReadableStream<Uint8Array>;
  text(): Promise<string>;
}

Header Types

type IncomingHttpHeaders = Record<string, string | string[]>;
type OutgoingHttpHeaders = Record<string, string | string[] | number>;

Install with Tessl CLI

npx tessl i tessl/npm-undici

docs

caching.md

connection-management.md

cookies.md

core-http.md

errors.md

global-config.md

headers-body.md

index.md

interceptors.md

mock-testing.md

web-standards.md

tile.json