`x-cache-key` header crashes when cache key contains non-ASCII characters

Open Beginner friendly
#69 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Quiet
Tech stack
node.js, typescript
Domain
backend

Research direction

Start in shared-cache.js at createSharedCacheFetch and follow setCacheKey through setResponseHeader to the Headers.set call. Reproduce with debugCacheKey enabled and a URL such as /templates/海报设计, then ensure the response succeeds and x-cache-key is ByteString-safe while preserving a documented way to recover the original key.

Written by the indexing model from the issue text.

Description

Package: @web-widget/shared-cache
Version: 1.8.0
Environment: Node.js (undici Headers.set)

Summary

When debugCacheKey is enabled, createSharedCacheFetch writes the computed cache key to the x-cache-key response header. If the cache key contains Unicode characters (e.g. from url.pathname or query values), Headers.set throws because HTTP header values must be a ByteString (code points ≤ 255).

Steps to reproduce

  1. Enable debugCacheKey: true on the cache middleware or fetch wrapper.
  2. Use default cache key rules with pathname: true (and/or search: true).
  3. Request a URL whose pathname or search params contain non-ASCII characters after URL decoding, e.g. /templates/海报设计.

Actual behavior

TypeError: Cannot convert argument to a ByteString because the character at index 46 has a value of 21830 which is greater than 255.
    at webidl.converters.ByteString (node:internal/deps/undici/undici:3889:17)
    at _Headers.set (node:internal/deps/undici/undici:8921:35)
    at setResponseHeader (shared-cache.js)
    at setCacheKey (shared-cache.js)
    at fetch (shared-cache.js)

The request fails instead of returning a cached or fresh response.

Expected behavior

debugCacheKey should not crash when the cache key contains Unicode. The header value should be encoded to a ByteString-safe form before calling Headers.set.

Root cause

Cache keys are built from raw url.pathname / search values, which JavaScript decodes to Unicode. setCacheKey passes the string directly to headers.set('x-cache-key', cacheKey) without encoding.

Relevant code path:

  • createSharedCacheFetchsetCacheKeysetResponseHeaderheaders.set(CACHE_KEY_HEADER_NAME, cacheKey)

Suggested fix

Encode the header value when it contains non-Latin-1 characters, for example:

function toCacheKeyHeaderValue(cacheKey) {
  for (let i = 0; i < cacheKey.length; i++) {
    if (cacheKey.charCodeAt(i) > 255) {
      return encodeURIComponent(cacheKey);
    }
  }
  return cacheKey;
}

function setCacheKey(response, cacheKey) {
  if (cacheKey) {
    return setResponseHeader(
      response,
      CACHE_KEY_HEADER_NAME,
      toCacheKeyHeaderValue(cacheKey),
    );
  }
  return response;
}

Consider documenting in README that x-cache-key may be encodeURIComponent-encoded when the raw key is not ByteString-safe. Consumers can recover the original key with decodeURIComponent.

Alternative: always use Base64URL encoding with a prefix (e.g. b64:) for a more explicit contract.

Dominant language
TypeScript
Stars
7
Forks
0
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.