DataLinks: Ensure window origin to be stripped from url when using absolute urls (#32634)

* Ensure window origin to be stripped from url when using absolute urls

* Update test

* Make sure link interception works for external links

* Apply suggestions from code review

* Review
This commit is contained in:
Dominik Prokop 2021-04-08 17:38:56 +02:00 committed by GitHub
parent d6c824fe18
commit deccc97985
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 11 deletions

View File

@ -1,18 +1,65 @@
import { locationUtil } from './location'; import { locationUtil } from './location';
describe('locationUtil', () => { describe('locationUtil', () => {
const { location } = window;
beforeAll(() => { beforeAll(() => {
locationUtil.initialize({ // @ts-ignore
config: { appSubUrl: '/subUrl' } as any, delete window.location;
getVariablesUrlParams: (() => {}) as any,
getTimeRangeForUrl: (() => {}) as any, 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', () => { afterAll(() => {
it('/subUrl should be stripped', () => { 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/'); const urlWithoutMaster = locationUtil.stripBaseFromUrl('/subUrl/grafana/');
expect(urlWithoutMaster).toBe('/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/');
});
}); });
}); });

View File

@ -14,10 +14,16 @@ let getVariablesUrlParams: (scopedVars?: ScopedVars) => UrlQueryMap;
const stripBaseFromUrl = (url: string): string => { const stripBaseFromUrl = (url: string): string => {
const appSubUrl = grafanaConfig.appSubUrl ?? ''; const appSubUrl = grafanaConfig.appSubUrl ?? '';
const stripExtraChars = appSubUrl.endsWith('/') ? 1 : 0; const stripExtraChars = appSubUrl.endsWith('/') ? 1 : 0;
const urlWithoutBase = const isAbsoluteUrl = url.startsWith('http');
url.length > 0 && url.indexOf(appSubUrl) === 0 ? url.slice(appSubUrl.length - stripExtraChars) : url; 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;
}; };
/** /**

View File

@ -19,11 +19,20 @@ export function interceptLinkClicks(e: MouseEvent) {
href = locationUtil.stripBaseFromUrl(href); href = locationUtil.stripBaseFromUrl(href);
// Ensure old angular urls with no starting '/' are handled the same as before // 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 // That is they where seen as being absolute from app root
if (href[0] !== '/') { 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}`; href = `/${href}`;
} }
locationService.push(href); locationService.push(href);
} }
} }