Skip to content

Commit ba687f6

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 d24b7b8 commit ba687f6

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
@@ -362,7 +362,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
362362
}
363363

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

@@ -377,7 +377,7 @@ function urlFormat(obj) {
377377
return obj.format();
378378
}
379379

380-
Url.prototype.format = function() {
380+
Url.prototype.format = function(parseQueryString) {
381381
var auth = this.auth || '';
382382
if (auth) {
383383
auth = encodeURIComponent(auth);
@@ -389,7 +389,26 @@ Url.prototype.format = function() {
389389
pathname = this.pathname || '',
390390
hash = this.hash || '',
391391
host = false,
392-
query = '';
392+
query = '',
393+
search = '';
394+
395+
if (this.path) {
396+
var qm = this.path.indexOf('?');
397+
if (qm !== -1) {
398+
query = this.path.slice(qm + 1);
399+
search = '?' + query;
400+
pathname = this.path.slice(0, qm);
401+
} else {
402+
if (parseQueryString) {
403+
this.query = {};
404+
this.search = '';
405+
} else {
406+
this.query = null;
407+
this.search = null;
408+
}
409+
pathname = this.path;
410+
}
411+
}
393412

394413
if (this.host) {
395414
host = auth + this.host;
@@ -402,13 +421,15 @@ Url.prototype.format = function() {
402421
}
403422
}
404423

405-
if (this.query &&
424+
if (!query &&
425+
this.query &&
406426
util.isObject(this.query) &&
407427
Object.keys(this.query).length) {
408428
query = querystring.stringify(this.query);
409429
}
410430

411-
var search = this.search || (query && ('?' + query)) || '';
431+
if (!search)
432+
search = this.search || (query && ('?' + query)) || '';
412433

413434
if (protocol && protocol.substr(-1) !== ':') protocol += ':';
414435

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)