Documentation Index Fetch the complete documentation index at: https://mintlify.com/cloudflare/workerd/llms.txt
Use this file to discover all available pages before exploring further.
The Fetch API provides a modern interface for making HTTP requests and handling responses. Workerd implements the standard Fetch API with extensions for serverless environments.
Overview
The Fetch API consists of several core interfaces:
Request - Represents an HTTP request
Response - Represents an HTTP response
Headers - Manages HTTP headers
fetch() - Executes HTTP requests
Implementation: src/workerd/api/http.h and http.c++
Making requests
The global fetch() function sends HTTP requests:
const response = await fetch ( 'https://api.example.com/data' );
const json = await response . json ();
Request options
Customize requests with options:
const response = await fetch ( 'https://api.example.com/data' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'Authorization' : 'Bearer token'
},
body: JSON . stringify ({ key: 'value' })
});
Request object
Create reusable Request objects:
const request = new Request ( 'https://api.example.com/data' , {
method: 'POST' ,
headers: new Headers ({
'Content-Type' : 'application/json'
}),
body: JSON . stringify ({ key: 'value' })
});
const response = await fetch ( request );
Working with responses
Reading response data
The Response object provides multiple methods to read the body:
// Read as text
const text = await response . text ();
// Read as JSON
const json = await response . json ();
// Read as ArrayBuffer
const buffer = await response . arrayBuffer ();
// Read as Blob
const blob = await response . blob ();
// Read as FormData
const formData = await response . formData ();
Response properties
Access response metadata:
const response = await fetch ( 'https://example.com' );
console . log ( response . status ); // 200
console . log ( response . statusText ); // "OK"
console . log ( response . ok ); // true
console . log ( response . headers ); // Headers object
console . log ( response . url ); // Final URL after redirects
Creating responses
Return custom responses from your worker:
export default {
async fetch ( request ) {
return new Response ( 'Hello World' , {
status: 200 ,
headers: {
'Content-Type' : 'text/plain'
}
});
}
} ;
The Headers interface manages HTTP headers:
const headers = new Headers ();
headers . set ( 'Content-Type' , 'application/json' );
headers . append ( 'X-Custom-Header' , 'value' );
if ( headers . has ( 'Content-Type' )) {
console . log ( headers . get ( 'Content-Type' ));
}
headers . delete ( 'X-Custom-Header' );
// Iterate over headers
for ( const [ key , value ] of headers ) {
console . log ( ` ${ key } : ${ value } ` );
}
Request body types
Workerd supports multiple body types:
// String body
const response1 = new Response ( 'Hello World' );
// ArrayBuffer body
const bytes = new Uint8Array ([ 72 , 101 , 108 , 108 , 111 ]);
const response2 = new Response ( bytes );
// ReadableStream body
const stream = new ReadableStream ({
start ( controller ) {
controller . enqueue ( new TextEncoder (). encode ( 'Hello ' ));
controller . enqueue ( new TextEncoder (). encode ( 'World' ));
controller . close ();
}
});
const response3 = new Response ( stream );
// Blob body
const blob = new Blob ([ 'Hello World' ]);
const response4 = new Response ( blob );
// FormData body
const formData = new FormData ();
formData . append ( 'key' , 'value' );
const response5 = new Response ( formData );
Generator bodies
Workerd supports async generators as request/response bodies:
async function* generateData () {
yield new TextEncoder (). encode ( 'Hello ' );
yield new TextEncoder (). encode ( 'World' );
}
const response = new Response ( generateData ());
const text = await response . text (); // "Hello World"
Source: src/workerd/api/tests/fetch-test.js:26
Body mixin
The Body class (defined in src/workerd/api/http.h:30) is a mixin that provides body-related functionality to both Request and Response.
Body types
using Initializer = kj ::OneOf < jsg ::Ref < ReadableStream > ,
kj ::String,
kj ::Array < byte > ,
jsg ::Ref < Blob > ,
jsg ::Ref < FormData > ,
jsg ::Ref < URLSearchParams > ,
jsg ::Ref < url ::URLSearchParams > ,
jsg ::AsyncGeneratorIgnoringStrings < jsg ::Value >> ;
This allows bodies to be constructed from various sources while maintaining the ability to retransmit (important for redirects).
Advanced features
Request cloning
Clone requests for multiple uses:
const request = new Request ( 'https://example.com' );
const clone = request . clone ();
// Both can be used independently
await fetch ( request );
await fetch ( clone );
Response cloning
Clone responses to read the body multiple times:
const response = await fetch ( 'https://example.com' );
const clone = response . clone ();
const text = await response . text ();
const buffer = await clone . arrayBuffer ();
Redirect handling
Control redirect behavior:
const response = await fetch ( 'https://example.com' , {
redirect: 'follow' // 'follow', 'error', or 'manual'
});
Method normalization
With the upper_case_all_http_methods compatibility flag, method names are converted to uppercase:
const request = new Request ( 'https://example.com' , {
method: 'patch'
});
console . log ( request . method ); // "PATCH"
Source: src/workerd/api/tests/fetch-test.js:10
Error handling
Handle fetch errors gracefully:
try {
const response = await fetch ( 'https://example.com' );
if ( ! response . ok ) {
throw new Error ( `HTTP error! status: ${ response . status } ` );
}
const data = await response . json ();
return new Response ( JSON . stringify ( data ));
} catch ( error ) {
return new Response ( `Error: ${ error . message } ` , {
status: 500
});
}
Best practices
Always check response.ok or response.status before processing the body: const response = await fetch ( url );
if ( ! response . ok ) {
throw new Error ( `HTTP ${ response . status } ` );
}
Use response.body as a ReadableStream for large responses: const response = await fetch ( url );
const reader = response . body . getReader ();
while ( true ) {
const { done , value } = await reader . read ();
if ( done ) break ;
// Process chunk
}
Create reusable request templates: const template = new Request ( 'https://api.example.com' , {
headers: { 'Authorization' : 'Bearer token' }
});
const response = await fetch ( template );
Implementation details
The Fetch API implementation is located in:
src/workerd/api/http.h - Header definitions (1300+ lines)
src/workerd/api/http.c++ - Implementation (3500+ lines)
src/workerd/api/headers.h / headers.c++ - Headers implementation
src/workerd/api/blob.h / blob.c++ - Blob implementation
The Body class provides the extraction algorithm from the Fetch spec and handles various body types through the Initializer OneOf type.