From 2b6da56c3cfa9d070b50f57c5730e5ab6d8f6c16 Mon Sep 17 00:00:00 2001 From: "Siddharth Gelera (reaper)" Date: Fri, 12 Sep 2025 19:08:53 +0530 Subject: [PATCH] fix(electron): avoid double encoding urls params. Fixes #5380. (#5507) * fix(common): avoid double encoding urls params --- .../src/ipc/network/interpolate-vars.js | 9 +- .../tests/network/interpolate-vars.spec.js | 102 ++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/packages/bruno-electron/src/ipc/network/interpolate-vars.js b/packages/bruno-electron/src/ipc/network/interpolate-vars.js index 4aef1e73f..0aff18f19 100644 --- a/packages/bruno-electron/src/ipc/network/interpolate-vars.js +++ b/packages/bruno-electron/src/ipc/network/interpolate-vars.js @@ -13,6 +13,11 @@ const getContentType = (headers = {}) => { return contentType; }; +const getRawQueryString = (url) => { + const queryIndex = url.indexOf('?'); + return queryIndex !== -1 ? url.slice(queryIndex) : ''; +}; + const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, processEnvVars = {}) => { const globalEnvironmentVariables = request?.globalEnvironmentVariables || {}; const oauth2CredentialVariables = request?.oauth2CredentialVariables || {}; @@ -126,7 +131,7 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc if (request?.pathParams?.length) { let url = request.url; - + const urlSearchRaw = getRawQueryString(request.url) if (!url.startsWith('http://') && !url.startsWith('https://')) { url = `http://${url}`; } @@ -152,7 +157,7 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc .join(''); const trailingSlash = url.pathname.endsWith('/') ? '/' : ''; - request.url = url.origin + urlPathnameInterpolatedWithPathParams + trailingSlash + url.search; + request.url = url.origin + urlPathnameInterpolatedWithPathParams + trailingSlash + urlSearchRaw; } if (request.proxy) { diff --git a/packages/bruno-electron/tests/network/interpolate-vars.spec.js b/packages/bruno-electron/tests/network/interpolate-vars.spec.js index c288db77f..88abdd811 100644 --- a/packages/bruno-electron/tests/network/interpolate-vars.spec.js +++ b/packages/bruno-electron/tests/network/interpolate-vars.spec.js @@ -54,6 +54,108 @@ describe('interpolate-vars: interpolateVars', () => { }); }); + describe('With path params', () => { + it('keeps the original url search params as is', async () => { + const request = { + method: 'GET', + url: 'http://example.com/:param/?search=hello world', + pathParams: [ + { + type: 'path', + name: 'param', + value: 'foobar' + } + ] + }; + + const result = interpolateVars(request, null, null, null); + expect(result.url).toBe('http://example.com/foobar/?search=hello world'); + }); + + it('keeps the original url search params as is even when url might not have protocl ', async () => { + const request = { + method: 'GET', + url: 'example.com/:param/?search=hello world', + pathParams: [ + { + type: 'path', + name: 'param', + value: 'foobar' + } + ] + }; + + const result = interpolateVars(request, null, null, null); + expect(result.url).toBe('http://example.com/foobar/?search=hello world'); + }); + + it('keeps the original url search params as is even when encoded', async () => { + const request = { + method: 'GET', + url: 'http://example.com/:param?search=hello%20world', + pathParams: [ + { + type: 'path', + name: 'param', + value: 'foobar' + } + ] + }; + + const result = interpolateVars(request, null, null, null); + expect(result.url).toBe('http://example.com/foobar?search=hello%20world'); + }); + + it('keeps the original url search params as is with edge cases', async () => { + const requestOne = { + method: 'GET', + url: 'https://example.com/:param?x=1#section', + pathParams: [ + { + type: 'path', + name: 'param', + value: 'foobar' + } + ] + }; + + const requestTwo = { + method: 'GET', + url: 'https://example.com/:param?x?y=2', + pathParams: [ + { + type: 'path', + name: 'param', + value: 'foobar' + } + ] + }; + + const resultOne = interpolateVars(requestOne, null, null, null); + expect(resultOne.url).toBe('https://example.com/foobar?x=1#section'); + + const resultTwo = interpolateVars(requestTwo, null, null, null); + expect(resultTwo.url).toBe('https://example.com/foobar?x?y=2'); + }); + + it('keeps the original url even without search', async () => { + const request = { + method: 'GET', + url: 'http://example.com/:param', + pathParams: [ + { + type: 'path', + name: 'param', + value: 'foobar' + } + ] + }; + + const result = interpolateVars(request, null, null, null); + expect(result.url).toBe('http://example.com/foobar'); + }); + }); + describe('With process environment variables', () => { /* * It should NOT turn process env vars into literal segments.