diff --git a/packages/grafana-data/src/utils/location.test.ts b/packages/grafana-data/src/utils/location.test.ts index 05d33e333ef..c06dc8588f1 100644 --- a/packages/grafana-data/src/utils/location.test.ts +++ b/packages/grafana-data/src/utils/location.test.ts @@ -1,18 +1,65 @@ import { locationUtil } from './location'; describe('locationUtil', () => { + const { location } = window; + beforeAll(() => { - locationUtil.initialize({ - config: { appSubUrl: '/subUrl' } as any, - getVariablesUrlParams: (() => {}) as any, - getTimeRangeForUrl: (() => {}) as any, - }); + // @ts-ignore + delete window.location; + + window.location = { + ...location, + hash: '#hash', + host: 'www.domain.com:9877', + hostname: 'www.domain.com', + href: 'http://www.domain.com:9877/path/b?search=a&b=c&d#hash', + origin: 'http://www.domain.com:9877', + pathname: '/path/b', + port: '9877', + protocol: 'http:', + search: '?search=a&b=c&d', + }; }); - describe('With /subUrl as appSubUrl', () => { - it('/subUrl should be stripped', () => { + afterAll(() => { + window.location = location; + }); + + describe('strip base when appSubUrl configured', () => { + beforeEach(() => { + locationUtil.initialize({ + config: { appSubUrl: '/subUrl' } as any, + getVariablesUrlParams: (() => {}) as any, + getTimeRangeForUrl: (() => {}) as any, + }); + }); + test('relative url', () => { const urlWithoutMaster = locationUtil.stripBaseFromUrl('/subUrl/grafana/'); expect(urlWithoutMaster).toBe('/grafana/'); }); + test('absolute url url', () => { + const urlWithoutMaster = locationUtil.stripBaseFromUrl('http://www.domain.com:9877/subUrl/grafana/'); + expect(urlWithoutMaster).toBe('/grafana/'); + }); + }); + + describe('strip base when appSubUrl not configured', () => { + beforeEach(() => { + locationUtil.initialize({ + config: {} as any, + getVariablesUrlParams: (() => {}) as any, + getTimeRangeForUrl: (() => {}) as any, + }); + }); + + test('relative url', () => { + const urlWithoutMaster = locationUtil.stripBaseFromUrl('/subUrl/grafana/'); + expect(urlWithoutMaster).toBe('/subUrl/grafana/'); + }); + + test('absolute url', () => { + const urlWithoutMaster = locationUtil.stripBaseFromUrl('http://www.domain.com:9877/subUrl/grafana/'); + expect(urlWithoutMaster).toBe('/subUrl/grafana/'); + }); }); }); diff --git a/packages/grafana-data/src/utils/location.ts b/packages/grafana-data/src/utils/location.ts index 29e982646e8..9d3d61048d0 100644 --- a/packages/grafana-data/src/utils/location.ts +++ b/packages/grafana-data/src/utils/location.ts @@ -14,10 +14,16 @@ let getVariablesUrlParams: (scopedVars?: ScopedVars) => UrlQueryMap; const stripBaseFromUrl = (url: string): string => { const appSubUrl = grafanaConfig.appSubUrl ?? ''; const stripExtraChars = appSubUrl.endsWith('/') ? 1 : 0; - const urlWithoutBase = - url.length > 0 && url.indexOf(appSubUrl) === 0 ? url.slice(appSubUrl.length - stripExtraChars) : url; + const isAbsoluteUrl = url.startsWith('http'); + let segmentToStrip = appSubUrl; - return urlWithoutBase; + if (isAbsoluteUrl || !url.startsWith('/')) { + segmentToStrip = `${window.location.origin}${appSubUrl}`; + } + + return url.length > 0 && url.indexOf(segmentToStrip) !== -1 + ? url.slice(segmentToStrip.length - stripExtraChars) + : url; }; /** diff --git a/public/app/core/navigation/patch/interceptLinkClicks.ts b/public/app/core/navigation/patch/interceptLinkClicks.ts index 164084763a6..bbb509df3f3 100644 --- a/public/app/core/navigation/patch/interceptLinkClicks.ts +++ b/public/app/core/navigation/patch/interceptLinkClicks.ts @@ -19,11 +19,20 @@ export function interceptLinkClicks(e: MouseEvent) { href = locationUtil.stripBaseFromUrl(href); // Ensure old angular urls with no starting '/' are handled the same as before + // Make sure external links are handled correctly // That is they where seen as being absolute from app root if (href[0] !== '/') { + try { + const external = new URL(href); + if (external.origin !== window.location.origin) { + window.location.href = external.toString(); + return; + } + } catch (e) { + console.warn(e); + } href = `/${href}`; } - locationService.push(href); } }