Skip to content

Commit

Permalink
Backport PR #6581 to 4.4
Browse files Browse the repository at this point in the history
[Commit 1]
short url: ensure absolute path isn't persisted

Original sha: a8c1305
Authored by Jonathan Budzenski <jbudz@users.noreply.github.com> on 2016-03-18T20:02:53Z
Committed by Jonathan Budzenski <jbudz@users.noreply.github.com> on 2016-03-21T15:57:16Z

[Commit 2]
[short url] use url.format when creating /goto link

Original sha: 2a71673
Authored by Jonathan Budzenski <jbudz@users.noreply.github.com> on 2016-03-21T14:09:04Z
Committed by Jonathan Budzenski <jbudz@users.noreply.github.com> on 2016-03-21T15:57:16Z

[Commit 3]
[short url] Add tests for query strings, no hashes

Original sha: 690a140
Authored by Jonathan Budzenski <jbudz@users.noreply.github.com> on 2016-03-21T14:42:10Z
Committed by Jonathan Budzenski <jbudz@users.noreply.github.com> on 2016-03-21T15:57:16Z

[Commit 4]
[short url] Cleanup

Original sha: 49d297f
Authored by Jonathan Budzenski <jbudz@users.noreply.github.com> on 2016-03-21T15:09:35Z
Committed by Jonathan Budzenski <jbudz@users.noreply.github.com> on 2016-03-21T15:57:16Z

[Commit 5]
[short url] Add server tests

Original sha: a612a0e
Authored by Jonathan Budzenski <jbudz@users.noreply.github.com> on 2016-03-21T15:30:12Z
Committed by Jonathan Budzenski <jbudz@users.noreply.github.com> on 2016-03-21T18:12:25Z
  • Loading branch information
epixa authored and jbudz committed Mar 22, 2016
1 parent bc3326e commit 5621e25
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 33 deletions.
97 changes: 76 additions & 21 deletions src/server/http/__tests__/index.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,96 @@
import expect from 'expect.js';
import KbnServer from '../../KbnServer';
import requirefrom from 'requirefrom';

describe('cookie validation', function () {
describe('routes', function () {
this.slow(10000);
this.timeout(60000);

const fromRoot = requirefrom('src/utils')('fromRoot');
let kbnServer;

beforeEach(function () {
kbnServer = new KbnServer({
server: { autoListen: false }
server: {
autoListen: false,
xsrf: {
disableProtection: true
}
},
plugins: { scanDirs: [ fromRoot('src/plugins') ] },
logging: { quiet: true },
optimize: { enabled: false },
elasticsearch: {
url: 'http://localhost:9210'
}
});
return kbnServer.ready();
});
afterEach(function () {
return kbnServer.close();
});

it('allows non-strict cookies', function (done) {
kbnServer.server.inject({
method: 'GET',
url: '/',
headers: {
cookie: 'test:80=value;test_80=value'
}
}, (res) => {
expect(res.payload).not.to.contain('Invalid cookie header');
done();
describe('cookie validation', function () {
it('allows non-strict cookies', function (done) {
const options = {
method: 'GET',
url: '/',
headers: {
cookie: 'test:80=value;test_80=value'
}
};
kbnServer.server.inject(options, (res) => {
expect(res.payload).not.to.contain('Invalid cookie header');
done();
});
});

it('returns an error if the cookie can\'t be parsed', function (done) {
const options = {
method: 'GET',
url: '/',
headers: {
cookie: 'a'
}
};
kbnServer.server.inject(options, (res) => {
expect(res.payload).to.contain('Invalid cookie header');
done();
});
});
});

it('returns an error if the cookie can\'t be parsed', function (done) {
kbnServer.server.inject({
method: 'GET',
url: '/',
headers: {
cookie: 'a'
describe('url shortener', () => {
const shortenOptions = {
method: 'POST',
url: '/shorten',
payload: {
url: '/app/kibana#/visualize/create'
}
}, (res) => {
expect(res.payload).to.contain('Invalid cookie header');
done();
};

it('generates shortened urls', (done) => {
kbnServer.server.inject(shortenOptions, (res) => {
expect(typeof res.payload).to.be('string');
expect(res.payload.length > 0).to.be(true);
done();
});
});

it('redirects shortened urls', (done) => {
kbnServer.server.inject(shortenOptions, (res) => {
const gotoOptions = {
method: 'GET',
url: '/goto/' + res.payload
};
kbnServer.server.inject(gotoOptions, (res) => {
expect(res.statusCode).to.be(302);
expect(res.headers.location).to.be(shortenOptions.payload.url);
done();
});
});
});

});

});
124 changes: 124 additions & 0 deletions src/ui/public/share/__tests__/url_shortener.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import _ from 'lodash';
import sinon from 'sinon';
import expect from 'expect.js';
import ngMock from 'ngMock';
import chrome from 'ui/chrome';
import LibUrlShortenerProvider from 'ui/share/lib/url_shortener';

describe('Url shortener', () => {
let $rootScope;
let $location;
let $http;
let urlShortener;
let $httpBackend;
const shareId = 'id123';

beforeEach(ngMock.module('kibana'));
beforeEach(ngMock.inject(function (_$rootScope_, _$location_, _$httpBackend_, Private) {
$location = _$location_;
$rootScope = _$rootScope_;
$httpBackend = _$httpBackend_;
urlShortener = Private(LibUrlShortenerProvider);
}));

describe('Shorten without base path', () => {
it('should shorten urls with a port', function (done) {
$httpBackend.when('POST', '/shorten').respond(function (type, route, data) {
expect(JSON.parse(data).url).to.be('/app/kibana#123');
return [200, shareId];
});
urlShortener.shortenUrl('http://localhost:5601/app/kibana#123').then(function (url) {
expect(url).to.be(`http://localhost:5601/goto/${shareId}`);
done();
});
$httpBackend.flush();
});

it('should shorten urls without a port', function (done) {
$httpBackend.when('POST', '/shorten').respond(function (type, route, data) {
expect(JSON.parse(data).url).to.be('/app/kibana#123');
return [200, shareId];
});
urlShortener.shortenUrl('http://localhost/app/kibana#123').then(function (url) {
expect(url).to.be(`http://localhost/goto/${shareId}`);
done();
});
$httpBackend.flush();
});
});

describe('Shorten with base path', () => {
const basePath = '/foo';

let getBasePath;
beforeEach(ngMock.inject((Private) => {
getBasePath = sinon.stub(chrome, 'getBasePath', () => basePath);
urlShortener = Private(LibUrlShortenerProvider);
}));

it('should shorten urls with a port', (done) => {
$httpBackend.when('POST', `${basePath}/shorten`).respond((type, route, data) => {
expect(JSON.parse(data).url).to.be('/app/kibana#123');
return [200, shareId];
});
urlShortener.shortenUrl(`http://localhost:5601${basePath}/app/kibana#123`).then((url) => {
expect(url).to.be(`http://localhost:5601${basePath}/goto/${shareId}`);
done();
});
$httpBackend.flush();
});

it('should shorten urls without a port', (done) => {
$httpBackend.when('POST', `${basePath}/shorten`).respond((type, route, data) => {
expect(JSON.parse(data).url).to.be('/app/kibana#123');
return [200, shareId];
});
urlShortener.shortenUrl(`http://localhost${basePath}/app/kibana#123`).then((url) => {
expect(url).to.be(`http://localhost${basePath}/goto/${shareId}`);
done();
});
$httpBackend.flush();
});

it('should shorten urls with a query string', (done) => {
$httpBackend.when('POST', `${basePath}/shorten`).respond((type, route, data) => {
expect(JSON.parse(data).url).to.be('/app/kibana?foo#123');
return [200, shareId];
});
urlShortener.shortenUrl(`http://localhost${basePath}/app/kibana?foo#123`).then((url) => {
expect(url).to.be(`http://localhost${basePath}/goto/${shareId}`);
done();
});
$httpBackend.flush();
});

it('should shorten urls without a hash', (done) => {
$httpBackend.when('POST', `${basePath}/shorten`).respond((type, route, data) => {
expect(JSON.parse(data).url).to.be('/app/kibana');
return [200, shareId];
});
urlShortener.shortenUrl(`http://localhost${basePath}/app/kibana`).then((url) => {
expect(url).to.be(`http://localhost${basePath}/goto/${shareId}`);
done();
});
$httpBackend.flush();
});

it('should shorten urls with a query string in the hash', (done) => {
const relativeUrl = "/app/kibana#/discover?_g=(refreshInterval:(display:Off,pause:!f,value:0),time:(from:now-15m,mode:quick,to:now))&_a=(columns:!(_source),index:%27logstash-*%27,interval:auto,query:(query_string:(analyze_wildcard:!t,query:%27*%27)),sort:!(%27@timestamp%27,desc))"; //eslint-disable-line max-len, quotes
$httpBackend.when('POST', `${basePath}/shorten`).respond((type, route, data) => {
expect(JSON.parse(data).url).to.be(relativeUrl);
return [200, shareId];
});
urlShortener.shortenUrl(`http://localhost${basePath}${relativeUrl}`).then((url) => {
expect(url).to.be(`http://localhost${basePath}/goto/${shareId}`);
done();
});
$httpBackend.flush();
});

afterEach(() => {
getBasePath.restore();
});
});
});
30 changes: 18 additions & 12 deletions src/ui/public/share/lib/url_shortener.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import chrome from 'ui/chrome';
import url from 'url';

export default function createUrlShortener(Notifier, $http, $location) {
const notify = new Notifier({
location: 'Url Shortener'
});
const basePath = chrome.getBasePath();
const baseUrl = `${$location.protocol()}://${$location.host()}:${$location.port()}${basePath}`;

async function shortenUrl(url) {
const relativeUrl = url.replace(baseUrl, '');
const formData = { url: relativeUrl };
function shortenUrl(absoluteUrl) {
const basePath = chrome.getBasePath();

const parsedUrl = url.parse(absoluteUrl);
const path = parsedUrl.path.replace(basePath, '');
const hash = parsedUrl.hash ? parsedUrl.hash : '';
const relativeUrl = path + hash;

try {
const result = await $http.post(`${basePath}/shorten`, formData);
const formData = { url: relativeUrl };

return `${baseUrl}/goto/${result.data}`;
} catch (err) {
notify.error(err);
throw err;
}
return $http.post(`${basePath}/shorten`, formData).then((result) => {
return url.format({
protocol: parsedUrl.protocol,
host: parsedUrl.host,
pathname: `${basePath}/goto/${result.data}`
});
}).catch((response) => {
notify.error(response);
});
}

return {
Expand Down

0 comments on commit 5621e25

Please sign in to comment.