From 45f60bc0a4cd4007e5d3fde84422416ef8624c4a Mon Sep 17 00:00:00 2001 From: Yazhong Liu Date: Thu, 20 Nov 2014 23:46:38 +0800 Subject: [PATCH 1/4] url: support `path` for url.format --- lib/url.js | 12 ++++++++++++ test/simple/test-url.js | 17 +++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/url.js b/lib/url.js index e01343a5069..77663a5e779 100644 --- a/lib/url.js +++ b/lib/url.js @@ -389,6 +389,18 @@ Url.prototype.format = function() { host = false, query = ''; + if (this.path) { + var qm = this.path.indexOf('?'); + pathname = pathname || (function(idx, path) { + if (idx !== -1) { + query = path.slice(qm); + return path.slice(0, qm); + } else { + return path; + } + })(qm, this.path); + } + if (this.host) { host = auth + this.host; } else if (this.hostname) { diff --git a/test/simple/test-url.js b/test/simple/test-url.js index 8bfedcdf3d6..08753da436d 100644 --- a/test/simple/test-url.js +++ b/test/simple/test-url.js @@ -1085,7 +1085,7 @@ var formatTests = { // `#`,`?` in path '/path/to/%%23%3F+=&.txt?foo=theA1#bar' : { - href : '/path/to/%%23%3F+=&.txt?foo=theA1#bar', + href: '/path/to/%%23%3F+=&.txt?foo=theA1#bar', pathname: '/path/to/%#?+=&.txt', query: { foo: 'theA1' @@ -1095,7 +1095,7 @@ var formatTests = { // `#`,`?` in path + `#` in query '/path/to/%%23%3F+=&.txt?foo=the%231#bar' : { - href : '/path/to/%%23%3F+=&.txt?foo=the%231#bar', + href: '/path/to/%%23%3F+=&.txt?foo=the%231#bar', pathname: '/path/to/%#?+=&.txt', query: { foo: 'the#1' @@ -1110,7 +1110,7 @@ var formatTests = { hostname: 'ex.com', hash: '#frag', search: '?abc=the#1?&foo=bar', - pathname: '/foo?100%m#r', + pathname: '/foo?100%m#r' }, // `?` and `#` in search only @@ -1120,7 +1120,16 @@ var formatTests = { hostname: 'ex.com', hash: '#frag', search: '?abc=the#1?&foo=bar', - pathname: '/fooA100%mBr', + pathname: '/fooA100%mBr' + }, + + // only for path rather than pathname + 'http://github.com/joyent/node#js': { + href: 'http://github.com/joyent/node#js', + protocol: 'http:', + hostname: 'github.com', + hash: '#js', + path: '/joyent/node' } }; for (var u in formatTests) { From cd5b060e154610f77d9dbceb2249d4457013d547 Mon Sep 17 00:00:00 2001 From: Yazhong Liu Date: Thu, 20 Nov 2014 23:52:22 +0800 Subject: [PATCH 2/4] doc: update for url.format with path --- doc/api/url.markdown | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/api/url.markdown b/doc/api/url.markdown index 6b8ff9d5076..3ace6995794 100644 --- a/doc/api/url.markdown +++ b/doc/api/url.markdown @@ -95,11 +95,12 @@ Take a parsed URL object, and return a formatted URL string. * `hostname` will only be used if `host` is absent. * `port` will only be used if `host` is absent. * `host` will be used in place of `hostname` and `port` -* `pathname` is treated the same with or without the leading `/` (slash) -* `search` will be used in place of `query` +* `pathname` is treated the same with or without the leading `/` (slash). +* `path` is treated the same with `pathname` but able to contain `query` as well. +* `search` will be used in place of `query`. * `query` (object; see `querystring`) will only be used if `search` is absent. -* `search` is treated the same with or without the leading `?` (question mark) -* `hash` is treated the same with or without the leading `#` (pound sign, anchor) +* `search` is treated the same with or without the leading `?` (question mark). +* `hash` is treated the same with or without the leading `#` (pound sign, anchor). ## url.resolve(from, to) From 38e9deaa28046d2518973a573c966e53424f0c8a Mon Sep 17 00:00:00 2001 From: Yazhong Liu Date: Fri, 21 Nov 2014 00:27:17 +0800 Subject: [PATCH 3/4] url: remove closure --- lib/url.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/url.js b/lib/url.js index 77663a5e779..048289a6b95 100644 --- a/lib/url.js +++ b/lib/url.js @@ -391,14 +391,12 @@ Url.prototype.format = function() { if (this.path) { var qm = this.path.indexOf('?'); - pathname = pathname || (function(idx, path) { - if (idx !== -1) { - query = path.slice(qm); - return path.slice(0, qm); - } else { - return path; - } - })(qm, this.path); + if (qm !== -1) { + query = this.path.slice(qm); + pathname = pathname || this.path.slice(0, qm); + } else { + pathname = pathname || this.path; + } } if (this.host) { From da8c66366f7e273ccaa107fa8fa17214a6f2e76f Mon Sep 17 00:00:00 2001 From: Yazhong Liu Date: Sat, 22 Nov 2014 19:05:09 +0800 Subject: [PATCH 4/4] url: add more tests for url.format with path field - pathname vs. path, pathname wins - pathname with query/search - path vs. query, query wins - path vs. search, search wins --- lib/url.js | 27 +++++++++++----- test/simple/test-url.js | 68 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/lib/url.js b/lib/url.js index 048289a6b95..f5e7ec0a9f7 100644 --- a/lib/url.js +++ b/lib/url.js @@ -360,7 +360,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { } // finally, reconstruct the href based on what has been validated. - this.href = this.format(); + this.href = this.format(parseQueryString); return this; }; @@ -375,7 +375,7 @@ function urlFormat(obj) { return obj.format(); } -Url.prototype.format = function() { +Url.prototype.format = function(parseQueryString) { var auth = this.auth || ''; if (auth) { auth = encodeURIComponent(auth); @@ -387,15 +387,24 @@ Url.prototype.format = function() { pathname = this.pathname || '', hash = this.hash || '', host = false, - query = ''; + query = '', + search = ''; if (this.path) { var qm = this.path.indexOf('?'); if (qm !== -1) { - query = this.path.slice(qm); - pathname = pathname || this.path.slice(0, qm); + query = this.path.slice(qm + 1); + search = '?' + query; + pathname = this.path.slice(0, qm); } else { - pathname = pathname || this.path; + if (parseQueryString) { + this.query = {}; + this.search = ''; + } else { + this.query = null; + this.search = null; + } + pathname = this.path; } } @@ -410,13 +419,15 @@ Url.prototype.format = function() { } } - if (this.query && + if (!query && + this.query && util.isObject(this.query) && Object.keys(this.query).length) { query = querystring.stringify(this.query); } - var search = this.search || (query && ('?' + query)) || ''; + if (!search) + search = this.search || (query && ('?' + query)) || ''; if (protocol && protocol.substr(-1) !== ':') protocol += ':'; diff --git a/test/simple/test-url.js b/test/simple/test-url.js index 08753da436d..df72cc6f4e6 100644 --- a/test/simple/test-url.js +++ b/test/simple/test-url.js @@ -1123,14 +1123,74 @@ var formatTests = { pathname: '/fooA100%mBr' }, - // only for path rather than pathname - 'http://github.com/joyent/node#js': { - href: 'http://github.com/joyent/node#js', + // path + 'http://github.com/joyent/node#js1': { + href: 'http://github.com/joyent/node#js1', protocol: 'http:', hostname: 'github.com', - hash: '#js', + hash: '#js1', path: '/joyent/node' + }, + + // pathname vs. path, path wins + 'http://github.com/joyent/node2#js1': { + href: 'http://github.com/joyent/node2#js1', + protocol: 'http:', + hostname: 'github.com', + hash: '#js1', + path: '/joyent/node2', + pathname: '/joyent/node' + }, + + // pathname with query/search + 'http://github.com/joyent/node?foo=bar#js2': { + href: 'http://github.com/joyent/node?foo=bar#js2', + protocol: 'http:', + hostname: 'github.com', + hash: '#js2', + path: '/joyent/node?foo=bar' + }, + + // path vs. query, path wins + 'http://github.com/joyent/node?foo=bar2#js3': { + href: 'http://github.com/joyent/node?foo=bar2#js3', + protocol: 'http:', + hostname: 'github.com', + hash: '#js3', + path: '/joyent/node?foo=bar2', + query: {foo: 'bar'} + }, + + // path vs. search, path wins + 'http://github.com/joyent/node?foo=bar3#js4': { + href: 'http://github.com/joyent/node?foo=bar3#js4', + protocol: 'http:', + hostname: 'github.com', + hash: '#js4', + path: '/joyent/node?foo=bar3', + search: '?foo=bar' + }, + + // path is present without ? vs. query given + 'http://github.com/joyent/node#js5': { + href: 'http://github.com/joyent/node#js5', + protocol: 'http:', + hostname: 'github.com', + hash: '#js5', + path: '/joyent/node', + query: {foo: 'bar'} + }, + + // path is present without ? vs. search given + 'http://github.com/joyent/node#js6': { + href: 'http://github.com/joyent/node#js6', + protocol: 'http:', + hostname: 'github.com', + hash: '#js6', + path: '/joyent/node', + search: '?foo=bar' } + }; for (var u in formatTests) { var expect = formatTests[u].href;