[ui/url] add modifyUrl() helper

This commit is contained in:
spalger 2017-01-03 13:40:20 -06:00
parent f38e7dc428
commit d4b9849fe5
4 changed files with 108 additions and 3 deletions

View file

@ -0,0 +1,44 @@
import { parse as parseUrl } from 'url';
import expect from 'expect.js';
import { modifyUrl } from '../modify_url';
describe('modifyUrl()', () => {
it('throws an error with invalid input', () => {
expect(() => modifyUrl(1, () => {})).to.throwError();
expect(() => modifyUrl(undefined, () => {})).to.throwError();
expect(() => modifyUrl('http://localhost')).to.throwError(); // no block
});
it('supports returning a new url spec', () => {
expect(modifyUrl('http://localhost', () => ({}))).to.eql('');
});
it('supports modifying the passed object', () => {
expect(modifyUrl('http://localhost', parsed => {
parsed.port = 9999;
parsed.auth = 'foo:bar';
})).to.eql('http://foo:bar@localhost:9999/');
});
it('supports changing pathname', () => {
expect(modifyUrl('http://localhost/some/path', parsed => {
parsed.pathname += '/subpath';
})).to.eql('http://localhost/some/path/subpath');
});
it('supports changing port', () => {
expect(modifyUrl('http://localhost:5601', parsed => {
parsed.port = (parsed.port * 1) + 1;
})).to.eql('http://localhost:5602/');
});
it('supports changing protocol', () => {
expect(modifyUrl('http://localhost', parsed => {
parsed.protocol = 'mail';
parsed.slashes = false;
parsed.pathname = null;
})).to.eql('mail:localhost');
});
});

View file

@ -0,0 +1,2 @@
export { KbnUrlProvider as default } from './url';
export { modifyUrl } from './modify_url';

View file

@ -0,0 +1,61 @@
import { parse as parseUrl, format as formatUrl } from 'url';
/**
* Takes a URL and a function that takes the meaningful parts
* of the URL as a key-value object, modifies some or all of
* the parts, and returns the modified parts formatted again
* as a url.
*
* Url Parts sent:
* - protocol
* - slashes (does the url have the //)
* - auth
* - hostname (just the name of the host, no port or auth information)
* - port
* - pathmame (the path after the hostname, no query or hash, starts
* with a slash if there was a path)
* - query (always an object, even when no query on original url)
* - hash
*
* Why?
* - The default url library in node produces several conflicting
* properties on the "parsed" output. Modifying any of these might
* lead to the modifications being ignored (depending on which
* property was modified)
* - It's not always clear wither to use path/pathname, host/hostname,
* so this trys to add helpful constraints
*
* @param {String} url - the url to parse
* @param {Function<Object|undefined>} block - a function that will modify the parsed url, or return a new one
* @return {String} the modified and reformatted url
*/
export function modifyUrl(url, block) {
if (typeof block !== 'function') {
throw new TypeError('You must pass a block to define the modifications desired');
}
const parsed = parseUrl(url, true);
// copy over the most specific version of each
// property. By default, the parsed url includes
// several conflicting properties (like path and
// pathname + search, or search and query) and keeping
// track of which property is actually used when they
// are formatted is harder than necessary
const meaningfulParts = {
protocol: parsed.protocol,
slashes: parsed.slashes,
auth: parsed.auth,
hostname: parsed.hostname,
port: parsed.port,
pathname: parsed.pathname,
query: parsed.query || {},
hash: parsed.hash,
};
// the block modifies the meaningfulParts object, or returns a new one
const modifications = block(meaningfulParts) || meaningfulParts;
// format the modified/replaced meaningfulParts back into a url
return formatUrl(modifications);
}

View file

@ -8,7 +8,7 @@ import AppStateProvider from 'ui/state_management/app_state';
uiModules.get('kibana/url')
.service('kbnUrl', function (Private) { return Private(KbnUrlProvider); });
function KbnUrlProvider($injector, $location, $rootScope, $parse, Private) {
export function KbnUrlProvider($injector, $location, $rootScope, $parse, Private) {
const self = this;
/**
@ -207,5 +207,3 @@ function KbnUrlProvider($injector, $location, $rootScope, $parse, Private) {
return (reloadOnSearch && searchSame) || !reloadOnSearch;
};
}
export default KbnUrlProvider;