Skip to content

Commit d312b6d

Browse files
yorkiechrisdickinson
authored andcommitted
url: support path for url.format
this adds support for a "path" field that overrides "query", "search", and "pathname" if given. Fixes: nodejs/node-v0.x-archive#8722 PR-URL: nodejs/node-v0.x-archive#8755 Reviewed-by: Chris Dickinson <[email protected]>
1 parent c131c1f commit d312b6d

File tree

3 files changed

+104
-13
lines changed

3 files changed

+104
-13
lines changed

doc/api/url.markdown

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,12 @@ Take a parsed URL object, and return a formatted URL string.
9595
* `hostname` will only be used if `host` is absent.
9696
* `port` will only be used if `host` is absent.
9797
* `host` will be used in place of `hostname` and `port`
98-
* `pathname` is treated the same with or without the leading `/` (slash)
99-
* `search` will be used in place of `query`
98+
* `pathname` is treated the same with or without the leading `/` (slash).
99+
* `path` is treated the same with `pathname` but able to contain `query` as well.
100+
* `search` will be used in place of `query`.
100101
* `query` (object; see `querystring`) will only be used if `search` is absent.
101-
* `search` is treated the same with or without the leading `?` (question mark)
102-
* `hash` is treated the same with or without the leading `#` (pound sign, anchor)
102+
* `search` is treated the same with or without the leading `?` (question mark).
103+
* `hash` is treated the same with or without the leading `#` (pound sign, anchor).
103104

104105
## url.resolve(from, to)
105106

lib/url.js

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
360360
}
361361

362362
// finally, reconstruct the href based on what has been validated.
363-
this.href = this.format();
363+
this.href = this.format(parseQueryString);
364364
return this;
365365
};
366366

@@ -375,7 +375,7 @@ function urlFormat(obj) {
375375
return obj.format();
376376
}
377377

378-
Url.prototype.format = function() {
378+
Url.prototype.format = function(parseQueryString) {
379379
var auth = this.auth || '';
380380
if (auth) {
381381
auth = encodeURIComponent(auth);
@@ -387,7 +387,26 @@ Url.prototype.format = function() {
387387
pathname = this.pathname || '',
388388
hash = this.hash || '',
389389
host = false,
390-
query = '';
390+
query = '',
391+
search = '';
392+
393+
if (this.path) {
394+
var qm = this.path.indexOf('?');
395+
if (qm !== -1) {
396+
query = this.path.slice(qm + 1);
397+
search = '?' + query;
398+
pathname = this.path.slice(0, qm);
399+
} else {
400+
if (parseQueryString) {
401+
this.query = {};
402+
this.search = '';
403+
} else {
404+
this.query = null;
405+
this.search = null;
406+
}
407+
pathname = this.path;
408+
}
409+
}
391410

392411
if (this.host) {
393412
host = auth + this.host;
@@ -400,13 +419,15 @@ Url.prototype.format = function() {
400419
}
401420
}
402421

403-
if (this.query &&
422+
if (!query &&
423+
this.query &&
404424
util.isObject(this.query) &&
405425
Object.keys(this.query).length) {
406426
query = querystring.stringify(this.query);
407427
}
408428

409-
var search = this.search || (query && ('?' + query)) || '';
429+
if (!search)
430+
search = this.search || (query && ('?' + query)) || '';
410431

411432
if (protocol && protocol.substr(-1) !== ':') protocol += ':';
412433

test/simple/test-url.js

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,7 @@ var formatTests = {
10851085

10861086
// `#`,`?` in path
10871087
'/path/to/%%23%3F+=&.txt?foo=theA1#bar' : {
1088-
href : '/path/to/%%23%3F+=&.txt?foo=theA1#bar',
1088+
href: '/path/to/%%23%3F+=&.txt?foo=theA1#bar',
10891089
pathname: '/path/to/%#?+=&.txt',
10901090
query: {
10911091
foo: 'theA1'
@@ -1095,7 +1095,7 @@ var formatTests = {
10951095

10961096
// `#`,`?` in path + `#` in query
10971097
'/path/to/%%23%3F+=&.txt?foo=the%231#bar' : {
1098-
href : '/path/to/%%23%3F+=&.txt?foo=the%231#bar',
1098+
href: '/path/to/%%23%3F+=&.txt?foo=the%231#bar',
10991099
pathname: '/path/to/%#?+=&.txt',
11001100
query: {
11011101
foo: 'the#1'
@@ -1110,7 +1110,7 @@ var formatTests = {
11101110
hostname: 'ex.com',
11111111
hash: '#frag',
11121112
search: '?abc=the#1?&foo=bar',
1113-
pathname: '/foo?100%m#r',
1113+
pathname: '/foo?100%m#r'
11141114
},
11151115

11161116
// `?` and `#` in search only
@@ -1120,8 +1120,77 @@ var formatTests = {
11201120
hostname: 'ex.com',
11211121
hash: '#frag',
11221122
search: '?abc=the#1?&foo=bar',
1123-
pathname: '/fooA100%mBr',
1123+
pathname: '/fooA100%mBr'
1124+
},
1125+
1126+
// path
1127+
'http://github.com/joyent/node#js1': {
1128+
href: 'http://github.com/joyent/node#js1',
1129+
protocol: 'http:',
1130+
hostname: 'github.com',
1131+
hash: '#js1',
1132+
path: '/joyent/node'
1133+
},
1134+
1135+
// pathname vs. path, path wins
1136+
'http://github.com/joyent/node2#js1': {
1137+
href: 'http://github.com/joyent/node2#js1',
1138+
protocol: 'http:',
1139+
hostname: 'github.com',
1140+
hash: '#js1',
1141+
path: '/joyent/node2',
1142+
pathname: '/joyent/node'
1143+
},
1144+
1145+
// pathname with query/search
1146+
'http://github.com/joyent/node?foo=bar#js2': {
1147+
href: 'http://github.com/joyent/node?foo=bar#js2',
1148+
protocol: 'http:',
1149+
hostname: 'github.com',
1150+
hash: '#js2',
1151+
path: '/joyent/node?foo=bar'
1152+
},
1153+
1154+
// path vs. query, path wins
1155+
'http://github.com/joyent/node?foo=bar2#js3': {
1156+
href: 'http://github.com/joyent/node?foo=bar2#js3',
1157+
protocol: 'http:',
1158+
hostname: 'github.com',
1159+
hash: '#js3',
1160+
path: '/joyent/node?foo=bar2',
1161+
query: {foo: 'bar'}
1162+
},
1163+
1164+
// path vs. search, path wins
1165+
'http://github.com/joyent/node?foo=bar3#js4': {
1166+
href: 'http://github.com/joyent/node?foo=bar3#js4',
1167+
protocol: 'http:',
1168+
hostname: 'github.com',
1169+
hash: '#js4',
1170+
path: '/joyent/node?foo=bar3',
1171+
search: '?foo=bar'
1172+
},
1173+
1174+
// path is present without ? vs. query given
1175+
'http://github.com/joyent/node#js5': {
1176+
href: 'http://github.com/joyent/node#js5',
1177+
protocol: 'http:',
1178+
hostname: 'github.com',
1179+
hash: '#js5',
1180+
path: '/joyent/node',
1181+
query: {foo: 'bar'}
1182+
},
1183+
1184+
// path is present without ? vs. search given
1185+
'http://github.com/joyent/node#js6': {
1186+
href: 'http://github.com/joyent/node#js6',
1187+
protocol: 'http:',
1188+
hostname: 'github.com',
1189+
hash: '#js6',
1190+
path: '/joyent/node',
1191+
search: '?foo=bar'
11241192
}
1193+
11251194
};
11261195
for (var u in formatTests) {
11271196
var expect = formatTests[u].href;

0 commit comments

Comments
 (0)