diff --git a/src/utils/__tests__/matchAndRewriteRoute.test.ts b/src/utils/__tests__/matchAndRewriteRoute.test.ts index 815f83b3..d92811cf 100644 --- a/src/utils/__tests__/matchAndRewriteRoute.test.ts +++ b/src/utils/__tests__/matchAndRewriteRoute.test.ts @@ -232,6 +232,22 @@ describe('matchAndRewriteURL', () => { expect(url4.toString()).toEqual('https://localhost/googleapis/foo/v1/test:url?key=abc123'); }); + it('Matches port parameters and remaps them properly', () => { + const url = attemptRemap({ + url: new URL('https://foo.domain.com:4567/'), + mappings: [{prefix: '/domain/{subdomain}/{port}', target: '{subdomain}.domain.com:{port}'}], + }); + expect(url.toString()).toEqual('https://localhost/domain/foo/4567/'); + }); + + it('Does not remove port when url is not matched', () => { + const url = attemptRemap({ + url: new URL('https://foo.domain.com:4567/'), + mappings: [], + }); + expect(url.toString()).toEqual('https://foo.domain.com:4567/'); + }); + it('Applies the /.proxy/ mapping without any mappings', () => { const url = attemptRemap({ url: new URL('https://1234567890.discordsays.com/api/token'), diff --git a/src/utils/url.ts b/src/utils/url.ts index f67f4ed2..809e0a67 100644 --- a/src/utils/url.ts +++ b/src/utils/url.ts @@ -15,6 +15,10 @@ function regexFromTarget(target: string): RegExp { return new RegExp(`${regexString}(/|$)`); } +function removePortParameterFromTarget(url: string): string { + return url.replace(/:\{[^}]+\}/g, ''); +} + export interface MatchAndRewriteURLInputs { originalURL: URL; prefixHost: string; @@ -32,15 +36,17 @@ export interface MatchAndRewriteURLInputs { * @returns null if URL doesn't match prefix, otherwise return rewritten URL */ export function matchAndRewriteURL({originalURL, prefix, prefixHost, target}: MatchAndRewriteURLInputs): URL | null { - // coerce url with filler https protocol so we can retrieve host and pathname from target - const targetURL = new URL(`https://${target}`); + // Remove port parameter from target and coerce url with filler https protocol so we can retrieve host and pathname from target + const targetURL = new URL(`https://${removePortParameterFromTarget(target)}`); // Depending on the environment, the URL constructor may turn `{` and `}` into `%7B` and `%7D`, respectively - const targetRegEx = regexFromTarget(targetURL.host.replace(/%7B/g, '{').replace(/%7D/g, '}')); + const targetRegEx = regexFromTarget(target.replace(/%7B/g, '{').replace(/%7D/g, '}')); const match = originalURL.toString().match(targetRegEx); // Null match indicates that this target is not relevant if (match == null) return originalURL; const newURL = new URL(originalURL.toString()); newURL.host = prefixHost; + // Remove port from new url (discord activities proxy doesn't listen on custom ports) + newURL.port = ''; newURL.pathname = prefix.replace(SUBSTITUTION_REGEX, (_, matchName) => { const replaceValue = match.groups?.[matchName]; if (replaceValue == null) throw new Error('Misconfigured route.');