Rearranged urlFormat #3291

Closed
wants to merge 2 commits into
from
+81 −37
Split
View
@@ -0,0 +1,22 @@
+var url = require('url'),
+ urls = [
+ 'http://nodejs.org/docs/latest/api/url.html#url_url_format_urlobj',
+ 'http://blog.nodejs.org/',
+ 'https://encrypted.google.com/search?q=url&q=site:npmjs.org&hl=en',
+ 'javascript:alert("node is awesome");',
+ 'some.ran/dom/url.thing?oh=yes#whoo'
+ ],
+ paths = [
+ '../foo/bar?baz=boom',
+ 'foo/bar',
+ 'http://nodejs.org',
+ './foo/bar?baz'
+ ];
+
+urls.forEach(url.parse);
+urls.forEach(url.format);
+urls.forEach(function(u){
+ paths.forEach(function(p){
+ url.resolve(u, p);
+ });
+});
View
@@ -317,55 +317,77 @@ function urlFormat(obj) {
// If it's an obj, this is a no-op.
// this way, you can call url_format() on strings
// to clean up potentially wonky urls.
- if (typeof(obj) === 'string') obj = urlParse(obj);
+ if (typeof obj === 'string') obj = urlParse(obj);
- var auth = obj.auth || '';
- if (auth) {
- auth = encodeURIComponent(auth);
- auth = auth.replace(/%3A/i, ':');
- auth += '@';
- }
+ var url = '';
- var protocol = obj.protocol || '',
- pathname = obj.pathname || '',
- hash = obj.hash || '',
- host = false,
- query = '';
-
- if (obj.host !== undefined) {
- host = auth + obj.host;
- } else if (obj.hostname !== undefined) {
- host = auth + (obj.hostname.indexOf(':') === -1 ?
- obj.hostname :
- '[' + obj.hostname + ']');
- if (obj.port) {
- host += ':' + obj.port;
+ if (obj.protocol) {
+ url += obj.protocol;
+ if (obj.protocol.substr(-1) !== ':') {
+ url += ':';
}
}
- if (obj.query && typeof obj.query === 'object' &&
- Object.keys(obj.query).length) {
- query = querystring.stringify(obj.query);
+ var hasHost = obj.host !== undefined || obj.hostname !== undefined;
+ var addSlashes = obj.slashes ||
+ (!obj.protocol || obj.slashedProtocol[obj.protocol]) && hasHost;
+
+ // only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
+ // unless they had them to begin with.
+ if (addSlashes) {
+ url += '//';
}
- var search = obj.search || (query && ('?' + query)) || '';
+ if (hasHost) {
+ if (obj.auth) {
+ url += encodeURIComponent(obj.auth).replace(/%3A/i, ':');
+ url += '@';
+ }
+ if (obj.host !== undefined) {
+ url += obj.host;
+ }
+ else { //obj.hostname !== undefined
+ if (obj.hostname.indexOf(':') >= 0) {
+ url += '[' + obj.hostname + ']';
+ }
+ else {
+ url += obj.hostname;
+ }
+ if (obj.port) {
+ url += ':' + obj.port;
+ }
+ }
+ }
- if (protocol && protocol.substr(-1) !== ':') protocol += ':';
+ if (obj.pathname) {
+ if (addSlashes && obj.pathname.charAt(0) !== '/') {
+ url += '/';
+ }
+ url += obj.pathname;
+ }
- // only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
- // unless they had them to begin with.
- if (obj.slashes ||
- (!protocol || slashedProtocol[protocol]) && host !== false) {
- host = '//' + (host || '');
- if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
- } else if (!host) {
- host = '';
+ if (obj.search) {
+ if (obj.search.charAt(0) !== '?') {
+ url += '?';
+ }
+ url += obj.search;
+ } else if (obj.query && typeof obj.query === 'object') {
+ for (var key in obj.query) {
+ if (Object.prototype.hasOwnProperty.call(obj.query, key)) {
+ url += '?' + querystring.stringify(obj.query);
+ break;
+ }
+ }
}
- if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
- if (search && search.charAt(0) !== '?') search = '?' + search;
+ if (obj.hash) {
+ if (obj.hash.charAt(0) !== '#') {
+ url += '#';
+ }
+ url += obj.hash;
+ }
- return protocol + host + pathname + search + hash;
+ return url;
}
function urlResolve(source, relative) {