[PR #5041] [MERGED] fix(common): url and param encoding #5030

Closed
opened 2026-03-17 02:30:50 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/hoppscotch/hoppscotch/pull/5041
Author: @CuriousCorrelation
Created: 5/2/2025
Status: Merged
Merged: 5/8/2025
Merged by: @jamesgeorge007

Base: patchHead: common-fix-path-encoding


📝 Commits (2)

  • a09ec44 fix(common): url and param encoding
  • 4eba8cb fix(common): convert params type regardless

📊 Changes

1 file changed (+29 additions, -6 deletions)

View changed files

📝 packages/hoppscotch-common/src/helpers/functional/process-request.ts (+29 -6)

📄 Description

These changes fix URL parameter encoding behavior based on how parameter values are encoded, those based on the ENCODE_MODE setting.

Closes HFE-833
Closes #4971

Context: We encode query parameter values according to RFC 3986 Section 3.4, query components should be encoded, which is controlled by ENCODE_MODE setting.

When the encoding mode was set to "enable", a parameter value like {second-testing} would be encoded to %257Bsecond-testing%257D instead of %7Bsecond-testing%7D.

This occurred because of a combination of the custom encoding logic and the browser's native searchParams.append() method.

As in RFC 3986#2.4, percent-encoding is non-idempotent. When processing a URL like http://localhost:8080/%7Bfoo%7D, the decodeURIComponent call applied to the URL would revert the encoded path back to http://localhost:8080/{foo}.

This fix addresses all issues by modifying the impl to maintain compliance with URL standards:

The processParams function now only encodes values:

const encodedValue = isEncodingRequired ? encodeParam(value) : value
return [key, encodedValue]

The updateUrl function now manually constructs query parameters:

if (processedParams.length > 0) {
  const searchParts = processedParams.map(([k, v]) => {
    return `${encodeURIComponent(k)}=${v}`
  })

  const existingSearch = u.search ? u.search.substring(1) + '&' : ''
  u.search = existingSearch + searchParts.join('&')
}

The URL string generation doesn't apply decodeURIComponent to the entire URL:

return u.toString()

Notes to reviewers

Test by making requests with special characters in parameters using different ENCODE_MODE settings ("enable", "disable", and "auto"), then look for URLs with already encoded segments like %7Bfoo%7D which should remain encoded throughout the process.

Demo

Below are the actual logs from testing this fix with different ENCODE_MODE settings and URL formats:

With unencoded URL path and ENCODE_MODE="disable":

Input Request:
{
  url: "http://localhost:8080/{foo}",
  params: [
    ["first", "firstVal"],
    ["second", "{second-val}"],
    ["{third}", "%third_val}"]
  ]
}

Output URL (Before Fix):
http://localhost:8080/{foo}?first=firstVal&second={second-val}&{third}=%third_val}

Output URL (After Fix):
http://localhost:8080/{foo}?first=firstVal&second={second-val}&%7Bthird%7D=%third_val}

With unencoded URL path and ENCODE_MODE="enable":

Input Request:
{
  url: "http://localhost:8080/{foo}",
  params: [
    ["first", "firstVal"],
    ["second", "{second-val}"],
    ["{third}", "%third_val}"]
  ]
}

Output URL (Before Fix):
http://localhost:8080/{foo}?first=firstVal&second=%257Bsecond-val%257D&
%257Bthird%257D=%25third_val%257D

Output URL (After Fix):
http://localhost:8080/{foo}?first=firstVal&second=%7Bsecond-val%7D&
%7Bthird%7D=%25third_val%7D

With already encoded URL path and ENCODE_MODE="enable":

Input Request:
{
  url: "http://localhost:8080/%7Bfoo%7D",
  params: [
    ["first", "firstVal"],
    ["second", "{second-val}"],
    ["{third}", "%third_val}"]
  ]
}

Output URL (Before Fix):
http://localhost:8080/{foo}?first=firstVal&second=%257Bsecond-val%257D&
%257Bthird%257D=%25third_val%257D

Output URL (After Fix):
http://localhost:8080/%7Bfoo%7D?first=firstVal&second=%7Bsecond-val%7D&
%7Bthird%7D=%25third_val%7D

With already encoded URL path and ENCODE_MODE="disable":

Input Request:
{
  url: "http://localhost:8080/%7Bfoo%7D",
  params: [
    ["first", "firstVal"],
    ["second", "{second-val}"],
    ["{third}", "%third_val}"]
  ]
}

Output URL (Before Fix):
http://localhost:8080/{foo}?first=firstVal&second={second-val}&
{third}=%third_val}

Output URL (After Fix):
http://localhost:8080/%7Bfoo%7D?first=firstVal&second={second-val}&
%7Bthird%7D=%third_val}

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/hoppscotch/hoppscotch/pull/5041 **Author:** [@CuriousCorrelation](https://github.com/CuriousCorrelation) **Created:** 5/2/2025 **Status:** ✅ Merged **Merged:** 5/8/2025 **Merged by:** [@jamesgeorge007](https://github.com/jamesgeorge007) **Base:** `patch` ← **Head:** `common-fix-path-encoding` --- ### 📝 Commits (2) - [`a09ec44`](https://github.com/hoppscotch/hoppscotch/commit/a09ec443656fcc8b895b8671989e949eabcf9ac2) fix(common): url and param encoding - [`4eba8cb`](https://github.com/hoppscotch/hoppscotch/commit/4eba8cb5d0acfc4bb05ddb16c8e71fe488356023) fix(common): convert `params` type regardless ### 📊 Changes **1 file changed** (+29 additions, -6 deletions) <details> <summary>View changed files</summary> 📝 `packages/hoppscotch-common/src/helpers/functional/process-request.ts` (+29 -6) </details> ### 📄 Description These changes fix URL parameter encoding behavior based on how parameter values are encoded, those based on the `ENCODE_MODE` setting. Closes HFE-833 Closes #4971 Context: We encode query parameter values according to [RFC 3986 Section 3.4](https://datatracker.ietf.org/doc/html/rfc3986#section-3.4), query components should be encoded, which is controlled by `ENCODE_MODE` setting. When the encoding mode was set to "enable", a parameter value like `{second-testing}` would be encoded to `%257Bsecond-testing%257D` instead of `%7Bsecond-testing%7D`. This occurred because of a combination of the custom encoding logic and the browser's native `searchParams.append()` method. As in [RFC 3986#2.4](https://datatracker.ietf.org/doc/html/rfc3986#section-2.4), percent-encoding is non-idempotent. When processing a URL like `http://localhost:8080/%7Bfoo%7D`, the `decodeURIComponent` call applied to the URL would revert the encoded path back to `http://localhost:8080/{foo}`. This fix addresses all issues by modifying the impl to maintain compliance with URL standards: The `processParams` function now only encodes values: ```javascript const encodedValue = isEncodingRequired ? encodeParam(value) : value return [key, encodedValue] ``` The `updateUrl` function now manually constructs query parameters: ```javascript if (processedParams.length > 0) { const searchParts = processedParams.map(([k, v]) => { return `${encodeURIComponent(k)}=${v}` }) const existingSearch = u.search ? u.search.substring(1) + '&' : '' u.search = existingSearch + searchParts.join('&') } ``` The URL string generation doesn't apply `decodeURIComponent` to the entire URL: ```javascript return u.toString() ``` ### Notes to reviewers Test by making requests with special characters in parameters using different `ENCODE_MODE` settings ("enable", "disable", and "auto"), then look for URLs with already encoded segments like `%7Bfoo%7D` which should remain encoded throughout the process. ### Demo Below are the actual logs from testing this fix with different `ENCODE_MODE` settings and URL formats: **With unencoded URL path and ENCODE_MODE="disable"**: ``` Input Request: { url: "http://localhost:8080/{foo}", params: [ ["first", "firstVal"], ["second", "{second-val}"], ["{third}", "%third_val}"] ] } Output URL (Before Fix): http://localhost:8080/{foo}?first=firstVal&second={second-val}&{third}=%third_val} Output URL (After Fix): http://localhost:8080/{foo}?first=firstVal&second={second-val}&%7Bthird%7D=%third_val} ``` **With unencoded URL path and ENCODE_MODE="enable"**: ``` Input Request: { url: "http://localhost:8080/{foo}", params: [ ["first", "firstVal"], ["second", "{second-val}"], ["{third}", "%third_val}"] ] } Output URL (Before Fix): http://localhost:8080/{foo}?first=firstVal&second=%257Bsecond-val%257D& %257Bthird%257D=%25third_val%257D Output URL (After Fix): http://localhost:8080/{foo}?first=firstVal&second=%7Bsecond-val%7D& %7Bthird%7D=%25third_val%7D ``` **With already encoded URL path and ENCODE_MODE="enable"**: ``` Input Request: { url: "http://localhost:8080/%7Bfoo%7D", params: [ ["first", "firstVal"], ["second", "{second-val}"], ["{third}", "%third_val}"] ] } Output URL (Before Fix): http://localhost:8080/{foo}?first=firstVal&second=%257Bsecond-val%257D& %257Bthird%257D=%25third_val%257D Output URL (After Fix): http://localhost:8080/%7Bfoo%7D?first=firstVal&second=%7Bsecond-val%7D& %7Bthird%7D=%25third_val%7D ``` **With already encoded URL path and ENCODE_MODE="disable"**: ``` Input Request: { url: "http://localhost:8080/%7Bfoo%7D", params: [ ["first", "firstVal"], ["second", "{second-val}"], ["{third}", "%third_val}"] ] } Output URL (Before Fix): http://localhost:8080/{foo}?first=firstVal&second={second-val}& {third}=%third_val} Output URL (After Fix): http://localhost:8080/%7Bfoo%7D?first=firstVal&second={second-val}& %7Bthird%7D=%third_val} ``` --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-03-17 02:30:50 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hoppscotch#5030
No description provided.