Skip to main content
doc0blade47/honodocumentation home
Sign in

Utilities and Encoding

Last updated Oct 12, 2026
Relevant source files

The following files were used as context for generating this wiki page:

Overview

The Hono framework provides a comprehensive set of low-level utilities and encoding helpers to support core operations, HTTP protocol management, templating, and request handling across diverse JavaScript runtimes. These modular helpers provide efficient mechanisms for cookie parsing, cryptographic signature verification, URI decoding, HTML escaping, Base64 and Base64Url data transformations, asynchronous task pooling, and status-code typing.

Sources: src/utils/cookie.ts:1-165, src/utils/url.ts:1-204, src/utils/html.ts:1-182, src/utils/encode.ts:1-34, src/utils/concurrent.ts:1-55, src/utils/http-status.ts:1-72

Cookie parsing and retrieval are orchestrated through helper functions exposed in src/helper/cookie/index.ts backed by core algorithms in src/utils/cookie.ts. When a cookie is deleted or retrieved, request headers are inspected and processed through a deterministic execution flow.

  1. deleteCookie initiates removal by calling getCookie with the target context, cookie name, and optional prefix constraints. Sources: src/helper/cookie/index.ts:141-144
  2. getCookie extracts the raw Cookie header from c.req.raw.headers, resolves cookie prefixes (__Secure- or __Host-), and invokes parse. Sources: src/helper/cookie/index.ts:27-41
  3. parse splits the raw cookie string by semicolons and iterates over individual pairs, using trimCookieWhitespace to strip leading and trailing spaces or tab characters from both names and values. Sources: src/utils/cookie.ts:79-115
  4. tryDecode handles percent-encoded cookie values by attempting standard decoding and gracefully falling back on malformed or partially encoded byte sequences. Sources: src/utils/cookie.ts:128-130, src/utils/url.ts:80-93

Sources: src/helper/cookie/index.ts:27-144, src/utils/cookie.ts:79-130, src/utils/url.ts:80-93

Cryptographic Signature Validation

Signed cookies are parsed and verified using Web Crypto HMAC-SHA-256 operations via parseSigned. The implementation imports secrets into CryptoKey instances and validates base64-encoded signatures attached to cookie values.

const algorithm = { name: 'HMAC', hash: 'SHA-256' }
 
const getCryptoKey = async (secret: string | BufferSource): Promise<CryptoKey> => {
  const secretBuf = typeof secret === 'string' ? new TextEncoder().encode(secret) : secret
  return await crypto.subtle.importKey('raw', secretBuf, algorithm, false, ['sign', 'verify'])
}

Sources: src/utils/cookie.ts:37-42

Note

parseSigned verifies that extracted signatures are exactly 44 characters long and terminate with an equals sign before invoking crypto.subtle.verify. If validation fails or throws an exception, the function assigns false to that cookie key in the returned record. Sources: src/utils/cookie.ts:140-165

Cookie names and values are validated against strict regular expressions adhering to RFC 6265 specifications, with allowances for common real-world characters.

Regex ConstantTargetValue / PatternDescription
validCookieNameRegExCookie Name/^[\w!#$%&'*.^|~+-]+$/`Matches all alphanumeric characters and allowed punctuation symbols.
validCookieValueRegExCookie Value/^[ !#-:<-[\]-~]*$/Matches ASCII characters 32 to 126, excluding double quotes, semicolons, and backslashes.

Sources: src/utils/cookie.ts:70-77

Warning

While the cookie specification prohibits spaces and commas in values, validCookieValueRegEx explicitly permits them because they occur frequently in real-world deployments. Sources: src/utils/cookie.ts:72-76

Execution Walkthrough and Sequence

Cookie serialization converts key-value pairs and attribute options into well-formed Set-Cookie header strings. The serialization helpers enforce security constraints based on cookie prefixes and append options like domain, path, max-age, and same-site policies.

The generation and dispatch of cookie headers follow a strict sequence across helper and utility modules.

  1. deleteCookie initiates removal by capturing the current cookie value via getCookie and delegating to setCookie with an empty string and a maxAge of zero. Sources: src/helper/cookie/index.ts:141-144
  2. setCookie passes the cookie name, value, and options to generateCookie to format the complete attribute string. Sources: src/helper/cookie/index.ts:99-102
  3. generateCookie evaluates prefix options (secure or host), enforces strict path and domain requirements, and invokes serialize. Sources: src/helper/cookie/index.ts:78-97

Sources: src/helper/cookie/index.ts:78-144

Caution

Cookie names prefixed with __Secure- require the secure attribute to be enabled, while those prefixed with __Host- require secure: true, a path of /, and an undefined domain attribute. Sources: src/helper/cookie/index.ts:79-82, src/utils/cookie.ts:174-179

URL path manipulation and decoding

Path Normalization and Segment Splitting

URL paths are split into array segments and merged through dedicated utilities that handle trailing slashes, root prefixes, and subpath concatenation. splitPath splits a path string by forward slashes and shifts off any leading empty element created by a leading slash. mergePath accepts multiple path arguments, recursively resolves nested inputs, normalizes leading forward slashes on subpaths, and preserves trailing slashes only when explicitly designated at the end of the base or subpath. Sources: src/utils/url.ts:8-14, src/utils/url.ts:158-169

export const splitPath = (path: string): string[] => {
  const paths = path.split('/')
  if (paths[0] === '') {
    paths.shift()
  }
  return paths
}

Sources: src/utils/url.ts:8-14

Note

getPathNoStrict wraps getPath to enforce lenient routing rules; if strict routing is disabled, it strips any trailing slash from paths longer than one character so that paths like /hello/hey/ and /hello/hey resolve identically. Sources: src/utils/url.ts:141-146

Group Mark Replacement and Parameter Extraction

Routing paths containing parameter blocks or braces are normalized via group extraction and replacement routines. extractGroupsFromPath scans path strings for bracketed expressions, extracts them into key-value group pairs, and substitutes temporary placeholder marks formatted as @${index}. splitRoutingPath combines this extraction step with segment splitting and replaceGroupMarks to reconstruct the original segments with their group placeholders intact. Sources: src/utils/url.ts:16-21, src/utils/url.ts:23-33, src/utils/url.ts:35-48

Function NameInput SignatureDescription
splitPathpath: stringSplits path by / and removes leading empty segments.
extractGroupsFromPathpath: stringReplaces {...} groups with @index markers and collects pairs.
replaceGroupMarkspaths: string[], groups: [string, string][]Re-inserts original group values into path segment arrays.
checkOptionalParameterpath: stringEvaluates trailing question marks on path parameters and returns generated base route variants or null.

Sources: src/utils/url.ts:8-14, src/utils/url.ts:23-48, src/utils/url.ts:171-203

Warning

checkOptionalParameter returns null if the path does not end with a question mark character code (63) or lacks a colon parameter marker. Sources: src/utils/url.ts:178-180

Fault-Tolerant URI Decoding

URI decoding utilities wrap native decoding functions with recovery logic to handle malformed percent-encoded strings and invalid UTF-8 sequences without throwing uncaught exceptions. tryDecode attempts to execute a provided decoder function, falling back to a regex-based matcher that isolates percent-encoded byte sequences and decodes valid sub-segments individually. tryDecodeURI applies this fault-tolerant behavior directly to decodeURI. Sources: src/utils/url.ts:80-104

export const tryDecode = (str: string, decoder: Decoder): string => {
  try {
    return decoder(str)
  } catch {
    return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match) => {
      try {
        return decoder(match)
      } catch {
        return match
      }
    })
  }
}

Sources: src/utils/url.ts:81-93

Tip

When getPath encounters a percent character (37) in a request URL, it locates query strings and hash boundaries using indexOf, slices out the path substring, and replaces %25 with %2525 prior to passing the result to tryDecodeURI. Sources: src/utils/url.ts:110-127

HTML escaping and template rendering

Escaped String Wrappers and Buffer Escape Mechanics

The HTML helper system relies on branded string types and buffer utilities to manage template tags src/utils/html.ts:17-21, src/helper/html/index.ts:11-14. The raw function constructs an HtmlEscapedString object wrapping an underlying value, setting its isEscaped flag to true and attaching optional callbacks src/utils/html.ts:40-46. Text escaping is handled by escapeToBuffer, which scans strings for characters matching the regular expression /[&<>'\"]/ and appends entity codes to a StringBuffer src/utils/html.ts:51-51, src/utils/html.ts:90-127.

Character CodeCharacterEscaped Entity
34""
39'&#39;
38&&
60<<
62>>

Sources: src/utils/html.ts:102-117

Note

escapeToBuffer exits immediately if str.search(escapeRe) returns -1, appending the raw string directly to buffer[0] without iteration. Sources: src/utils/html.ts:91-95

Template Tag Processing and StringBuffer Resolution

The html tagged template function iterates over template strings and interpolated values, flattening array children and handling strings, numbers, booleans, null, undefined, escaped objects, and promises src/helper/html/index.ts:11-48. Interpolated items containing active callbacks or asynchronous promises cause the buffer to prepend items via buffer.unshift('', child), alternating strings and promises src/helper/html/index.ts:33-44. stringBufferToString processes these buffers from tail to head, resolving promises and collecting embedded callbacks src/utils/html.ts:53-88.

* StringBuffer contains string and Promise<string> alternately
* The length of the array will be odd, the odd numbered element will be a string,
* and the even numbered element will be a Promise<string>.
* When concatenating into a single string, it must be processed from the tail.
* @example
* [
*   'framework.',
*   Promise.resolve('ultra fast'),
*   'a ',
*   Promise.resolve('is '),
*   'Hono',
* ]
*/

Sources: src/utils/html.ts:24-36

Warning

A StringBuffer must always have an odd length where odd-numbered elements are strings and even-numbered elements are promises; concatenation must proceed strictly from the tail. Sources: src/utils/html.ts:24-27

Synchronous and Asynchronous Callback Resolution

Callback resolution supports distinct execution phases defined by HtmlEscapedCallbackPhase src/utils/html.ts:6-10. resolveCallbackSync evaluates stringification callbacks synchronously when no asynchronous promises or streams are present src/utils/html.ts:129-140. For asynchronous rendering flows, resolveCallback awaits promises, maps over callback functions with specific execution phases, filters truthy results, and recursively resolves nested values src/utils/html.ts:142-182.

Phase NameNumeric ValueDescription
Stringify1Phase triggered during string conversion of template components.
BeforeStream2Phase executed immediately preceding stream rendering.
Stream3Phase active during chunked stream transmission.

Sources: src/utils/html.ts:6-10

Tip

When preserveCallbacks is enabled in resolveCallback, the resulting string retains its callback array wrapped via raw(), whereas setting it to false strips the callbacks from the final output src/utils/html.ts:145-145, src/utils/html.ts:177-181.

Binary and Base64 encoding helpers

Base64 and Base64Url Operations

Encoding and decoding binary buffers and URL-safe strings rely on standard Base64 transformations combined with custom character substitutions. encodeBase64 converts any ArrayBufferLike into a Base64 string by iterating over its bytes via Uint8Array, converting each character code to a binary string, and passing the result to btoa src/utils/encode.ts:15-22. Conversely, decodeBase64 decodes a Base64 string using atob and populates a Uint8Array from both ends simultaneously src/utils/encode.ts:25-33. For URL-safe representations, encodeBase64Url replaces forward slashes with underscores and plus signs with hyphens, while decodeBase64Url reverses these substitutions prior to decoding src/utils/encode.ts:6-11. UTF-8 text encoding and decoding utilities are exposed directly through utf8Encoder and utf8Decoder instances src/utils/jwt/utf8.ts:6-7.

Sources: src/utils/encode.ts:6-33, src/utils/jwt/utf8.ts:6-7

Warning

decodeBase64 iterates from both ends toward the middle (i and j) to populate the Uint8Array buffer in a single pass over half the binary length. Sources: src/utils/encode.ts:28-32

Cryptographic Hashing Wrappers

Cryptographic hashing utilities generate message digests using the Web Crypto API's crypto.subtle.digest interface src/utils/crypto.ts:45-56. The createHash function accepts data in various formats, stringifying JSON objects and encoding plain strings with TextEncoder when the input is not already an ArrayBuffer or ArrayBufferView [src/utils/crypto.ts:33-43]. The resulting digest buffer is converted into a hexadecimal string by mapping each byte to a zero-padded hex representation src/utils/crypto.ts:52-55. Specific algorithm wrappers provide pre-configured parameters for standard hash functions.

Function NameAlgorithm NameAlgorithm AliasReturn TypeSources
sha256SHA-256sha256Promise<string | null>src/utils/crypto.ts:15-19
sha1SHA-1sha1Promise<string | null>src/utils/crypto.ts:21-25
md5MD5md5Promise<string | null>src/utils/crypto.ts:27-31

Sources: src/utils/crypto.ts:15-31

Note

If crypto or crypto.subtle is unavailable in the current runtime environment, createHash returns null rather than throwing an error src/utils/crypto.ts:45-57. Sources: src/utils/crypto.ts:45-57

Concurrency control and task pools

Task Throttling and Execution Pools

Managing concurrent asynchronous execution pools is handled via the createPool helper, which limits simultaneous task execution during batch operations src/utils/concurrent.ts:12-18. By default, pools enforce a maximum concurrency limit of 1024 active tasks when no options are provided src/utils/concurrent.ts:6, src/utils/concurrent.ts:19. The returned Pool interface exposes a single run method that accepts a task function returning a value or a promise src/utils/concurrent.ts:8-10.

export const createPool = ({
  concurrency,
  interval,
}: {
  concurrency?: number
  interval?: number
} = {}): Pool => {
  concurrency ||= DEFAULT_CONCURRENCY
 
  if (concurrency === Infinity) {
    // unlimited
    return {
      run: async (fn) => fn(),
    }
  }
 
  const pool: Set<{}> = new Set()
  const run = async <T>(
    fn: () => T,
    promise?: Promise<T>,
    resolve?: (result: T) => void
  ): Promise<T> => {
    if (pool.size >= (concurrency as number)) {
      promise ||= new Promise<T>((r) => (resolve = r))
      setTimeout(() => run(fn, promise, resolve))
      return promise
    }
    const marker = {}
    pool.add(marker)
    const result = await fn()
    if (interval) {
      setTimeout(() => pool.delete(marker), interval)
    } else {
      pool.delete(marker)
    }
    if (resolve) {
      resolve(result)
      return promise as Promise<T>
    } else {
      return result
    }
  }
  return { run }

Sources: src/utils/concurrent.ts:12-54

When the pool's active set size reaches the configured concurrency threshold, incoming execution requests queue up by returning a deferred promise that re-evaluates via setTimeout src/utils/concurrent.ts:34-38. If concurrency is explicitly set to Infinity, throttling is disabled entirely, executing tasks immediately without tracking or queuing src/utils/concurrent.ts:21-26.

Warning

Setting concurrency to Infinity bypasses all pool tracking and marker allocations, causing run to invoke the task function directly without backpressure src/utils/concurrent.ts:21-26. Sources: src/utils/concurrent.ts:21-26

Pool Configuration Options

The createPool function accepts a configuration object defining concurrency limits and release intervals src/utils/concurrent.ts:12-18.

Option NameTypeDefaultDescriptionSources
concurrencynumber1024Maximum number of concurrent tasks allowed in the execution poolsrc/utils/concurrent.ts:6, src/utils/concurrent.ts:16, src/utils/concurrent.ts:19
intervalnumberundefinedDelay in milliseconds before removing a completed task marker from the active pool setsrc/utils/concurrent.ts:17, src/utils/concurrent.ts:42-43

Sources: src/utils/concurrent.ts:6, src/utils/concurrent.ts:16-17, src/utils/concurrent.ts:19, src/utils/concurrent.ts:42-43

Tip

Specifying an interval delays the deletion of task markers from the internal Set, enforcing a cool-down period between task completions and slot availability src/utils/concurrent.ts:42-46. Sources: src/utils/concurrent.ts:42-46

HTTP headers and status codes

HTTP Status Code Mappings

Hono provides comprehensive TypeScript type definitions categorizing standard HTTP status codes by their functional classification src/utils/http-status.ts:6-40. These types include informatory responses, successful operations, redirects, client errors, and server errors src/utils/http-status.ts:6-40. Unofficial or custom status codes can be cast using UnofficialStatusCode (-1) when interacting with non-standard server extensions src/utils/http-status.ts:43-52.

Status CategoryStatus CodesSources
InfoStatusCode100, 101, 102, 103src/utils/http-status.ts:6
SuccessStatusCode200, 201, 202, 203, 204, 205, 206, 207, 208, 226src/utils/http-status.ts:7
DeprecatedStatusCode305, 306src/utils/http-status.ts:8
RedirectStatusCode300, 301, 302, 303, 304, 305, 306, 307, 308src/utils/http-status.ts:9
ClientErrorStatusCode400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 421, 422, 423, 424, 425, 426, 428, 429, 431, 451src/utils/http-status.ts:10-39
ServerErrorStatusCode500, 501, 502, 503, 504, 505, 506, 507, 508, 510, 511src/utils/http-status.ts:40

Sources: src/utils/http-status.ts:6-40

Note

ContentlessStatusCode aggregates specific response codes (101, 204, 205, 304) that typically omit a response body, while ContentfulStatusCode excludes them from the broader StatusCode union src/utils/http-status.ts:71-72. Sources: src/utils/http-status.ts:71-72

Header Utilities and Proxy Management

Typed utilities define strict unions for request and response headers in src/utils/headers.ts, covering standard IANA HTTP field names src/utils/headers.ts:8-322. Additionally, proxy helpers process hop-by-hop headers such as connection, keep-alive, proxy-authenticate, proxy-authorization, te, trailer, transfer-encoding, and upgrade src/helper/proxy/index.ts:10-19. When strictConnectionProcessing is enabled, connection header values are validated against ALLOWED_TOKEN_PATTERN (/^[!#$%&'*+\-.0-9A-Z^_a-z|~]+$/`) before stripping listed headers src/helper/proxy/index.ts:22-22, src/helper/proxy/index.ts:63-76.

Warning

By default, strictConnectionProcessing is set to false, completely ignoring incoming connection headers to prevent potential Hop-by-Hop Header Injection attacks src/helper/proxy/index.ts:33-43. Sources: src/helper/proxy/index.ts:33-43

Was this page helpful?