new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Cloudflare Workers · Runtime APIs · all subjects

handlers

183 notes in this subject, read out of this brain and free to use. This is page 2 of 4.

Headers API example with get, set, and append

Example showing Headers API usage: ```js let headers = new Headers(); headers.get('x-foo'); //=> null headers.set('x-foo', '123'); headers.get('x-foo'); //=> "123" headers.set('x-foo', 'hello'); headers.get('x-foo'); //=> "hello" headers.append('x-foo', 'world'); headers.get('x-foo'); //=> "hello, world" ``` This demonstrates that set() replaces the value, while append() adds to it with comma-delimited concatenation.

Workers Headers API differs from web standard

The Workers implementation of the Headers API differs from the web standard in several intentional ways that reflect the server-side nature of the Workers runtime.

getAll() method only works with Set-Cookie

Despite being obsolete in web browsers, Workers still provides the Headers.getAll method specifically for use with the Set-Cookie header because cookies often contain date strings with commas, making parsing difficult. Attempting to use Headers.getAll with other header names will throw an error.

Set-Cookie append behavior in Workers

Due to RFC 6265 prohibiting folding multiple Set-Cookie headers into a single header, the Headers.append method in Workers allows setting multiple Set-Cookie response headers instead of appending the value onto an existing header.

Set-Cookie append example

Example showing multiple Set-Cookie headers: ```js const headers = new Headers(); headers.append("Set-Cookie", "cookie1=value_for_cookie_1; Path=/; HttpOnly;"); headers.append("Set-Cookie", "cookie2=value_for_cookie_2; Path=/; HttpOnly;"); console.log(headers.getAll("Set-Cookie")); // Array(2) [ cookie1=value_for_cookie_1; Path=/; HttpOnly;, cookie2=value_for_cookie_2; Path=/; HttpOnly; ] ``` This shows that append() on Set-Cookie creates separate header entries rather than comma-delimited concatenation.

Headers.get returns USVString not ByteString

In Cloudflare Workers, the Headers.get method returns a USVString instead of a ByteString as specified by the web standard. For most scenarios, this should have no noticeable effect.

HTMLRewriter constructor and basic setup

The HTMLRewriter class is instantiated once in a Workers script with handlers attached using the on() and onDocument() functions. Example: new HTMLRewriter().on("*", new ElementHandler()).onDocument(new DocumentHandler());

ContentOptions object for HTMLRewriter

ContentOptions is an object with a single property: html (Boolean). If html is true, content is treated as raw HTML. If html is false or not provided, content is treated as text and proper HTML escaping is applied.

Text chunk properties

Text chunk properties: removed (boolean), text (string, read-only), lastInTextNode (boolean, read-only). Text chunks are not the same as text nodes in the lexical tree because Cloudflare performs zero-copy streaming parsing. A single text node can arrive as multiple chunks, and lastInTextNode is true when the last chunk arrives.

Text chunk methods

Text chunk methods: before(content: Content, contentOptions?: ContentOptions): Element, after(content: Content, contentOptions?: ContentOptions): Element, replace(content: Content, contentOptions?: ContentOptions): Element, remove(): Element.

Comment properties and methods

Comment properties: removed (boolean), text (string, assignable to modify comment text). Comment methods: before(content: Content, contentOptions?: ContentOptions): Element, after(content: Content, contentOptions?: ContentOptions): Element, replace(content: Content, contentOptions?: ContentOptions): Element, remove(): Element.

Doctype properties

Doctype properties: name (string | null, read-only), publicId (string | null, read-only), systemId (string | null, read-only).

DocumentEnd methods

DocumentEnd has one method: append(content: Content, contentOptions?: ContentOptions): DocumentEnd, which inserts content after the end of the document.

HTMLRewriter CSS selectors

HTMLRewriter supports the following selectors: * (any element), E (element type), E:nth-child(n), E:first-child, E:nth-of-type(n), E:first-of-type, E:not(s) (compound selector negation), E.warning (class), E#myid (id), E[foo] (attribute exists), E[foo="bar"] (attribute exact match), E[foo="bar" i] (case-insensitive match), E[foo="bar" s] (case-sensitive match), E[foo~="bar"] (whitespace-separated value match), E[foo^="bar"] (attribute begins with), E[foo$="bar"] (attribute ends with), E[foo*="bar"] (substring match), E[foo|="en"] (hyphen-separated value starts with), E F (descendant), E > F (child).

HTMLRewriter error handling behavior

If a handler throws an exception, parsing is immediately halted, the transformed response body is errored with the thrown exception, and the untransformed response body is canceled. If the transformed response body was already partially streamed to the client, the client will see a truncated response.

Text chunks arrive as multiple handler invocations

Since Cloudflare performs zero-copy streaming parsing, a single text node may not arrive all at once. Developers should concatenate text chunks together by checking the lastInTextNode property and accumulating text across multiple handler invocations.

HTMLRewriter element handler example

Example element handler processing div elements: class ElementHandler { element(element) { console.log(`Incoming element: ${element.tagName}`); } comments(comment) { // An incoming comment } text(text) { // An incoming piece of text } } async function handleRequest(req) { const res = await fetch(req); return new HTMLRewriter().on("div", new ElementHandler()).transform(res); }

Element handler methods

An element handler responds to element, comments, and text methods when attached using .on(). The element method receives an incoming element, comments method receives comments, and text method receives text content.

Document handler methods

A document handler responds to doctype, comments, text, and end methods. These functions are not scoped by a selector and are called for all content on the page including content outside the top-level HTML tag.

Async handlers in HTMLRewriter

All functions defined on both element and document handlers can return void or Promise<void>. Making handler functions async allows accessing external resources such as APIs via fetch, Workers KV, Durable Objects, or the cache.

Element properties and methods

Element properties: tagName (string, assignable to modify tag), attributes (Iterator read-only of [name, value] pairs), removed (boolean), namespaceURI (string). Element methods: getAttribute(name: string): string | null, hasAttribute(name: string): boolean, setAttribute(name: string, value: string): Element, removeAttribute(name: string): Element, before(content: Content, contentOptions?: ContentOptions): Element, after(content: Content, contentOptions?: ContentOptions): Element, prepend(content: Content, contentOptions?: ContentOptions): Element, append(content: Content, contentOptions?: ContentOptions): Element, replace(content: Content, contentOptions?: ContentOptions): Element, setInnerContent(content: Content, contentOptions?: ContentOptions): Element, remove(): Element, removeAndKeepContent(): Element, onEndTag(handler: Function<void>): void.

EndTag properties and methods

EndTag properties: name (string, assignable to modify tag). EndTag methods: before(content: Content, contentOptions?: ContentOptions): EndTag, after(content: Content, contentOptions?: ContentOptions): EndTag, remove(): EndTag.

HTMLRewriter async element handler with fetch

Example async element handler that fetches external resources: class UserElementHandler { async element(element) { let response = await fetch(new Request("/user")); // fill in user info using response } } async function handleRequest(req) { const res = await fetch(req); return new HTMLRewriter() .on("div#user_info", new UserElementHandler()) .transform(res); }

HTMLRewriter error handling example

Example showing error handling behavior: async function handle(request) { let oldResponse = await fetch(request); let newResponse = new HTMLRewriter() .on("*", { element(element) { throw new Error("A really bad error."); }, }) .transform(oldResponse); // At this point, await newResponse.text() will throw the error. // Any use of newResponse.body will throw the same error, // and oldResponse.body will be closed. // This will produce a truncated response to the client: return newResponse; }

Content type for HTMLRewriter insertions

Content inserted in the output stream should be a string, Response, or ReadableStream.

https.request example

import { request } from "node:https"; import { strictEqual, ok } from "node:assert"; export default { async fetch() { const { promise, resolve, reject } = Promise.withResolvers(); const req = request( "https://developers.cloudflare.com/robots.txt", { method: "GET", }, (res) => { strictEqual(res.statusCode, 200); let data = ""; res.setEncoding("utf8"); res.on("data", (chunk) => { data += chunk; }); res.once("error", reject); res.on("end", () => { ok(data.includes("User-agent")); resolve(new Response(data)); }); }, ); req.end(); return promise; }, };

https.createServer method implementation

The https.createServer method creates an HTTPS server instance that can handle incoming secure requests. It is a convenience function that creates a new Server instance and optionally sets up a request listener callback. The httpServerHandler function integrates Node.js HTTPS servers with the Cloudflare Workers request model; when a request arrives at the Worker, the handler automatically routes it to the Node.js server running on the specified port.

HTTPS server resource management pitfall

Failing to call close() on an HTTPS server may result in the server being leaked. To prevent this, call close() when done with the server, or use explicit resource management with the await using statement to automatically close the server when it goes out of scope.

https.Agent implementation

The Workers implementation of https.Agent is a stub implementation that does not support connection pooling or keep-alive. Unlike Node.js where an Agent manages HTTPS connection reuse by maintaining request queues per host/port, in the Workers environment such low-level network management is handled by the Cloudflare infrastructure instead.

https.Server implementation differences from Node.js

In Workers, https.Server and http.Server are functionally similar because secure request handling is provided by the Cloudflare infrastructure. The following differences exist: connection management methods such as closeAllConnections() and closeIdleConnections() are not implemented; only listen() variants with a port number or no parameters are supported (listen(), listen(0, callback), listen(callback), etc.); server options maxHeaderSize, insecureHTTPParser, keepAliveTimeout, and connectionsCheckingInterval are not supported; TLS/SSL-specific options such as ca, cert, key, pfx, rejectUnauthorized, and secureProtocol are not supported (use mTLS binding for mTLS functionality).

https.request unsupported options

The following options are not supported in the Workers implementation of https.request: ca, cert, ciphers, clientCertEngine, crl, dhparam, ecdhCurve, honorCipherOrder, key, passphrase, pfx, rejectUnauthorized, secureOptions, secureProtocol, servername, sessionIdContext, and highWaterMark.

Response constructor parameters

The Response constructor accepts two optional parameters: body and init. The body can be null or one of: BufferSource, FormData, ReadableStream, URLSearchParams, or USVString. The init parameter is an options object with custom settings.

Response init options: cf, encodeBody, headers, status, statusText, webSocket

Response init options include: cf (any | null, Cloudflare-specific information for informational purposes only), encodeBody (string, set to 'manual' for pre-compressed data or defaults to 'automatic'), headers (Headers | ByteString, key-value pairs), status (int, HTTP status code like 200), statusText (string, status message like 'OK'), webSocket (WebSocket | null, present in successful WebSocket handshake responses).

Response properties: body, bodyUsed, headers, ok, redirected, status, statusText, url, webSocket

Response has the following properties: body (ReadableStream getter for body contents), bodyUsed (boolean indicating if body was used), headers (Headers for the response), ok (boolean for successful response with status 200-299), redirected (boolean for redirect responses), status (int status code), statusText (string status message), url (string final URL after redirects), webSocket (WebSocket? present in successful WebSocket handshake responses).

Response instance methods: clone, json, redirect

Response provides three instance methods: clone() returns a cloned Response object, json() creates a new response with a JSON-serialized payload, redirect() creates a new response with a different URL.

Response Body mixin methods: arrayBuffer, formData, json, text

Response implements the Fetch API Body mixin, providing: arrayBuffer() returns Promise<ArrayBuffer>, formData() returns Promise<FormData>, json() returns Promise<JSON>, text() returns Promise<USVString>. Each method reads the response stream to completion.

FixedLengthStream for controlling Content-Length

FixedLengthStream is an identity TransformStream that permits only a fixed number of bytes to be written to it. It is used to specify an exact Content-Length header value for a Response.

FixedLengthStream example usage

Example of using FixedLengthStream: ```js const { writable, readable } = new FixedLengthStream(11); const enc = new TextEncoder(); const writer = writable.getWriter(); writer.write(enc.encode("hello world")); writer.end(); return new Response(readable); ```

Workers Response extensions to web standard

Workers adds three extensions to the standard Response API: the cf property (optional, for Cloudflare-specific information), the webSocket property (for WebSocket connections), and the encodeBody option (to control response body compression).

cf property in Response

The cf property is a Workers-specific optional property in Response that can be set in ResponseInit options. It contains Cloudflare-specific information for informational purposes only and does not affect Workers behavior.

encodeBody option in Response

The encodeBody option in ResponseInit controls how the response body is compressed. Set to 'manual' when serving pre-compressed data to prevent automatic compression by Workers.

WebSocket property in Response

The webSocket property in Response is present in successful WebSocket handshake responses. It establishes a WebSocket connection proxied through a Worker. Data flowing over a WebSocket connection cannot be intercepted.

Request constructor parameters

The Request constructor takes two parameters: `input` (either a string URL or an existing Request object) and optional `options` object. The options parameter is optional.

Request options: cache

The cache option in RequestInit accepts undefined, 'no-store', or 'no-cache'. Only these values are supported; any other cache header will result in a TypeError with message 'Unsupported cache mode: <attempted-cache-mode>'.

Request options: method

The method option is an optional string representing the HTTP request method. The default is GET. All HTTP request methods are supported in Workers except for CONNECT.

Request options: body

The body option is optional and can be a string, ReadableStream, FormData, or URLSearchParams. A request using GET or HEAD method cannot have a body.

Request options: redirect

The redirect option accepts 'follow', 'error', or 'manual'. The default for a new Request object is 'follow'. However, the incoming Request property of a FetchEvent will have redirect mode 'manual'.

Request options: signal

The signal option accepts an AbortSignal. If provided, the request can be canceled by triggering an abort on the corresponding AbortController.

RequestInitCfProperties: apps

The apps property is a boolean that controls whether Cloudflare Apps should be enabled for this request. It is optional and defaults to true.

RequestInitCfProperties: cacheEverything

The cacheEverything property is a boolean that treats all content as static and caches all file types beyond Cloudflare default cached content, respecting cache headers from origin. It is equivalent to setting Page Rule Cache Level to Cache Everything. It is optional, defaults to false, and only applies to GET and HEAD request methods.

RequestInitCfProperties: cacheKey

The cacheKey property is an optional string that determines if two requests are the same for caching purposes. If a request has the same cache key as a previous request, Cloudflare can serve the same cached response for both.

RequestInitCfProperties: cacheTags

The cacheTags property is an optional array of strings that appends additional Cache-Tag headers to the response from the origin server. This allows purges of cached content based on tags provided by the Worker without modifications to the origin server, using the Purge by Tag feature.

RequestInitCfProperties: cacheTtl

The cacheTtl property is an optional number that forces Cloudflare to cache the response for this request regardless of response headers. The value must be zero or a positive number. A value of 0 indicates the cache asset expires immediately. This option only applies to GET and HEAD request methods.

RequestInitCfProperties: cacheTtlByStatus

The cacheTtlByStatus property is an optional object with string keys and number values. It is a version of cacheTtl that chooses a TTL based on response status code. For example: { '200-299': 86400, '404': 1, '500-599': 0 }. Values can be any integer, including zero and negative integers. A value of 0 indicates immediate expiration. Any negative value instructs Cloudflare not to cache at all. This option only applies to GET and HEAD request methods.

RequestInitCfProperties: vary

The vary property is an optional RequestInitCfPropertiesVary object that controls how Cloudflare caches origin responses with a Vary header for a single fetch() request. If both cf.vary and Cache Rules Vary apply, cf.vary takes precedence for this subrequest.

RequestInitCfProperties: image

The image property is an optional object or null that enables Image Resizing for this request. The possible values are described in the Transform images via Workers documentation.

RequestInitCfProperties: polish

The polish property is an optional string that sets Polish mode. The possible values are 'lossy', 'lossless', or 'off'.

RequestInitCfProperties: resolveOverride

The resolveOverride property is an optional string that directs the request to an alternate origin server by overriding the DNS lookup. The value specifies an alternate hostname to use for determining the origin IP address instead of the hostname in the URL. The Host header will still match the URL. Both the URL host and resolveOverride host must be within your zone for this to take effect. If resolveOverride points to a host outside your zone, create a CNAME record within your zone pointing to the outside host, then set resolveOverride to point at the CNAME record.

ReadableStream body uses Chunked-Encoding

Using any other type of ReadableStream as the body of a request will result in Chunked-Encoding being used instead of Content-Length.

RequestInitCfProperties: scrapeShield

The scrapeShield property is a boolean that controls whether ScrapeShield should be enabled for this request if otherwise configured for the zone. It is optional and defaults to true.

Give your agent this brain