Skip to content

feat: add decodeName option to parse()#90

Open
wadefletch wants to merge 2 commits intounjs:mainfrom
wadefletch:feat/decode-name-option
Open

feat: add decodeName option to parse()#90
wadefletch wants to merge 2 commits intounjs:mainfrom
wadefletch:feat/decode-name-option

Conversation

@wadefletch
Copy link
Copy Markdown

@wadefletch wadefletch commented Mar 26, 2026

Description

Adds an optional decodeName function to CookieParseOptions that decodes cookie names during parsing.

The existing decode option only applies to cookie values. Cookie names are returned as raw strings from the Cookie header. Browsers may URL-encode special characters in cookie names (e.g. @%40), but server-side consumers often look up cookies by the decoded name — causing silent lookup failures.

Example

import { parse } from 'cookie-es'

// Before: name stays encoded, lookup by decoded name fails
parse('user%40host=token')
// → { 'user%40host': 'token' }

// After: names are decoded
parse('user%40host=token', { decodeName: decodeURIComponent })
// → { 'user@host': 'token' }

Motivation

AWS Amplify stores auth tokens in cookies keyed by username — e.g. CognitoIdentityServiceProvider.<clientId>.user@test.local.idToken. Browsers URL-encode the @ as %40 when sending the Cookie header.

Server-side, Amplify's TokenStore constructs the lookup key with the raw (decoded) username, then reads it via createKeyValueStorageFromCookieStorageAdapter, which delegates to the framework's cookie getter. In h3/Nitro apps, that getter uses cookie-es's parse() — which doesn't decode names, so the lookup silently returns undefined and the user appears unauthenticated.

Changes

  • src/cookie/types.tsdecodeName option on CookieParseOptions, note on filter interaction
  • src/cookie/parse.ts — Apply decodeName to raw key before filter (2-line change)
  • test/cookie-parse.test.ts — 5 tests: decode, no-op, independent from value decode, error propagation, filter interaction

Design decisions

  • decodeName is applied before filter, so filter receives the decoded name
  • Errors propagate (not caught) — same contract as a user-provided decode per the existing JSDoc: "If you provide your own encode/decode scheme you must ensure errors are appropriately handled"
  • Fully backward compatible — no behavior change when decodeName is not set

Browsers may URL-encode special characters in cookie names (e.g. `@`
becomes `%40`). The existing `decode` option only applies to cookie
values, leaving names as raw strings from the `Cookie` header.

This adds an optional `decodeName` function to `CookieParseOptions`
that is applied to cookie names during parsing, before `filter`.

Motivating use case: AWS Amplify writes auth cookies with usernames
in the cookie name (e.g. `CognitoIdentityServiceProvider.<id>.user@test.local.idToken`).
Browsers encode the `@` as `%40`, but server-side token providers
look up the cookie by the decoded name. Without `decodeName`, the
lookup fails silently.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 26, 2026

📝 Walkthrough

Walkthrough

Adds an optional decodeName?: (str: string) => string to cookie parse options; parse now applies it to each raw cookie name (falling back to the raw name if decoding throws) before filtering, lookup, or storing results, including in allowMultiple handling.

Changes

Cohort / File(s) Summary
Cookie parsing implementation
src/cookie/parse.ts, src/cookie/types.ts
Introduce optional decodeName in CookieParseOptions. Parser applies decodeName to rawKey, falls back on exceptions, uses decoded key for filter evaluation and as the property key (including allowMultiple branch lookups).
Tests
test/cookie-parse.test.ts
Add tests for decodeName: URL-decoding names, leaving unencoded names unchanged, independence from value decoding, fallback when decoding throws, and confirming filter receives the decoded key.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • pi0

Poem

🐇 Hop, nibble, decode the name,

Percent signs tamed into fame.
If decoding trips, I still impart —
The raw name stays close to heart.
Cookies lined up, decoded or plain. 🍪

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a new decodeName option to the parse() function, which directly matches the primary objective of the pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/cookie/parse.ts`:
- Around line 48-49: The call to options.decodeName(rawKey) is unguarded and can
throw (e.g., malformed percent-encodings), so wrap the invocation used to set
key in a try/catch and fall back to rawKey on error; specifically, in the
parsing flow where rawKey is produced by valueSlice and assigned to key, replace
the direct options.decodeName(rawKey) call with a guarded call that catches any
exception and returns rawKey if decoding fails (mirroring the existing try/catch
used for value decoding).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2f45713d-653e-40fa-a3b9-34a48c1e8539

📥 Commits

Reviewing files that changed from the base of the PR and between 26ea164 and a6bdeb2.

📒 Files selected for processing (3)
  • src/cookie/parse.ts
  • src/cookie/types.ts
  • test/cookie-parse.test.ts

@wadefletch wadefletch force-pushed the feat/decode-name-option branch from 377b467 to b4bcea9 Compare March 26, 2026 15:00
Add optional `decodeName` function to `CookieParseOptions` that
decodes cookie names during parsing. The existing `decode` option
only applies to values — names are returned as raw strings from
the `Cookie` header.

Browsers may URL-encode special characters in cookie names (e.g.
`@` → `%40`), but server-side consumers often look up cookies by
the decoded name. Without `decodeName`, lookups fail silently.

Example:
  parse('user%40host=token', { decodeName: decodeURIComponent })
  // → { 'user@host': 'token' }

When used with `filter`, the filter receives the decoded name.
Errors from `decodeName` are not caught (same contract as a
user-provided `decode`).
@wadefletch wadefletch force-pushed the feat/decode-name-option branch from b4bcea9 to 67659af Compare March 26, 2026 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant