Skip to content

fix(http): keep = encoded in HttpParams keys#69884

Open
arshsmith1 wants to merge 1 commit into
angular:mainfrom
arshsmith1:http-params-key-equals
Open

fix(http): keep = encoded in HttpParams keys#69884
arshsmith1 wants to merge 1 commit into
angular:mainfrom
arshsmith1:http-params-key-equals

Conversation

@arshsmith1

@arshsmith1 arshsmith1 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.dev application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

Issue Number: #11058

HttpUrlEncodingCodec.encodeKey and encodeValue in packages/common/http/src/params.ts share standardEncoding, which runs encodeURIComponent and then restores the characters listed in STANDARD_ENCODING_REPLACEMENTS. That list includes =, but paramParser splits every pair at its first =, so a parameter name containing one is written out unencoded and reads back as a different name. new HttpParams().set('filter=admin', 'true').toString() gives filter=admin=true, which reparses as key filter with value admin=true, so HttpParams does not round-trip through its own parser. The gap matters wherever the name is not a literal, for example params.set(facetNameFromApi, value) or params rebuilt from location.search: the request then carries a parameter the caller never asked for. & is already left encoded, so this shifts the key/value boundary rather than adding a whole pair.

What is the new behavior?

= is restored only when encoding a value, where the pair has already been delimited and the character is unambiguous. Keys keep it percent-encoded, so the example above serializes as filter%3Dadmin=true and reparses to the key it started from. Value encoding is unchanged, including the existing d=eq=1 expectation.

Does this PR introduce a breaking change?

  • Yes
  • No

The serialized output changes for any key that contains =: filter=admin=true becomes filter%3Dadmin=true. A backend that was reading the old, ambiguous output will see a different query string, so this needs to ride a major. The commit message carries a BREAKING CHANGE: footer describing it.

Other information

A custom HttpParameterCodec is unaffected; only the default codec changes, and applications that want the old output can supply their own codec.

@pullapprove
pullapprove Bot requested a review from JeanMeche July 22, 2026 07:35
@angular-robot angular-robot Bot added the area: common/http Issues related to HTTP and HTTP Client label Jul 22, 2026
@ngbot ngbot Bot added this to the Backlog milestone Jul 22, 2026
@JeanMeche

Copy link
Copy Markdown
Member

That would be a fix for #11058. But it is known to be a breaking change.

A parameter name containing `=` was emitted unencoded, so the pair re-read as a
different name. Restore `=` only when encoding a value, where the first `=` has
already delimited the pair.

Fixes angular#11058

BREAKING CHANGE: The default `HttpUrlEncodingCodec` now percent-encodes `=` in
parameter keys instead of leaving it literal. A key containing `=` serializes as
`filter%3Dadmin=true` rather than `filter=admin=true`, so a backend that relied on
the old, ambiguous output will see a different query string. Value encoding is
unchanged. Applications that need the previous behaviour can supply a custom
`HttpParameterCodec`.
@arshsmith1
arshsmith1 force-pushed the http-params-key-equals branch from 519e29c to 2e3a089 Compare July 22, 2026 13:01
@angular-robot angular-robot Bot added the detected: breaking change PR contains a commit with a breaking change label Jul 22, 2026
@arshsmith1

Copy link
Copy Markdown
Contributor Author

You're right, and I had it mislabelled. I've re-marked the PR as breaking and amended the commit with a BREAKING CHANGE: footer plus Fixes #11058, so it can ride a major rather than land quietly.

The blast radius is narrow: only keys that actually contain = serialize differently (filter=admin=true -> filter%3Dadmin=true), value encoding is untouched, and anyone depending on the old output can keep it with a custom HttpParameterCodec. Happy to park it against whatever the next major branch is, or close it if you'd rather track the fix on the issue instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: common/http Issues related to HTTP and HTTP Client detected: breaking change PR contains a commit with a breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants