parent
26bfb6bea4
commit
a94ffdaec5
75
lib/url.js
75
lib/url.js
@ -35,7 +35,7 @@ var protocolPattern = /^([a-z0-9.+-]+:)/i,
|
||||
// RFC 2396: characters reserved for delimiting URLs.
|
||||
delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
|
||||
// RFC 2396: characters not allowed for various reasons.
|
||||
unwise = ['{', '}', '|', '\\', '^', '~', '[', ']', '`'].concat(delims),
|
||||
unwise = ['{', '}', '|', '\\', '^', '~', '`'].concat(delims),
|
||||
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
|
||||
autoEscape = ['\''],
|
||||
// Characters that are never ever allowed in a hostname.
|
||||
@ -179,10 +179,15 @@ function urlParse(url, parseQueryString, slashesDenoteHost) {
|
||||
// so even if it's empty, it has to be present.
|
||||
out.hostname = out.hostname || '';
|
||||
|
||||
// if hostname begins with [ and ends with ]
|
||||
// assume that it's an IPv6 address.
|
||||
var ipv6Hostname = out.hostname[0] === '[' &&
|
||||
out.hostname[out.hostname.length - 1] === ']';
|
||||
|
||||
// validate a little.
|
||||
if (out.hostname.length > hostnameMaxLen) {
|
||||
out.hostname = '';
|
||||
} else {
|
||||
} else if (!ipv6Hostname) {
|
||||
var hostparts = out.hostname.split(/\./);
|
||||
for (var i = 0, l = hostparts.length; i < l; i++) {
|
||||
var part = hostparts[i];
|
||||
@ -221,22 +226,32 @@ function urlParse(url, parseQueryString, slashesDenoteHost) {
|
||||
// hostnames are always lower case.
|
||||
out.hostname = out.hostname.toLowerCase();
|
||||
|
||||
// IDNA Support: Returns a puny coded representation of "domain".
|
||||
// It only converts the part of the domain name that
|
||||
// has non ASCII characters. I.e. it dosent matter if
|
||||
// you call it with a domain that already is in ASCII.
|
||||
var domainArray = out.hostname.split('.');
|
||||
var newOut = [];
|
||||
for (var i = 0; i < domainArray.length; ++i) {
|
||||
var s = domainArray[i];
|
||||
newOut.push(s.match(/[^A-Za-z0-9_-]/) ?
|
||||
'xn--' + punycode.encode(s) : s);
|
||||
if (!ipv6Hostname) {
|
||||
// IDNA Support: Returns a puny coded representation of "domain".
|
||||
// It only converts the part of the domain name that
|
||||
// has non ASCII characters. I.e. it dosent matter if
|
||||
// you call it with a domain that already is in ASCII.
|
||||
var domainArray = out.hostname.split('.');
|
||||
var newOut = [];
|
||||
for (var i = 0; i < domainArray.length; ++i) {
|
||||
var s = domainArray[i];
|
||||
newOut.push(s.match(/[^A-Za-z0-9_-]/) ?
|
||||
'xn--' + punycode.encode(s) : s);
|
||||
}
|
||||
out.hostname = newOut.join('.');
|
||||
}
|
||||
out.hostname = newOut.join('.');
|
||||
|
||||
out.host = (out.hostname || '') +
|
||||
((out.port) ? ':' + out.port : '');
|
||||
out.href += out.host;
|
||||
|
||||
// strip [ and ] from the hostname
|
||||
if (ipv6Hostname) {
|
||||
out.hostname = out.hostname.substr(1, out.hostname.length - 2);
|
||||
if (rest[0] !== '/') {
|
||||
rest = '/' + rest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now rest is set to the post-host stuff.
|
||||
@ -323,20 +338,28 @@ function urlFormat(obj) {
|
||||
}
|
||||
|
||||
var protocol = obj.protocol || '',
|
||||
host = (obj.host !== undefined) ? auth + obj.host :
|
||||
obj.hostname !== undefined ? (
|
||||
auth + obj.hostname +
|
||||
(obj.port ? ':' + obj.port : '')
|
||||
) :
|
||||
false,
|
||||
pathname = obj.pathname || '',
|
||||
query = obj.query &&
|
||||
((typeof obj.query === 'object' &&
|
||||
Object.keys(obj.query).length) ?
|
||||
querystring.stringify(obj.query) :
|
||||
'') || '',
|
||||
search = obj.search || (query && ('?' + query)) || '',
|
||||
hash = obj.hash || '';
|
||||
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.query && typeof obj.query === 'object' &&
|
||||
Object.keys(obj.query).length) {
|
||||
query = querystring.stringify(obj.query);
|
||||
}
|
||||
|
||||
var search = obj.search || (query && ('?' + query)) || '';
|
||||
|
||||
if (protocol && protocol.substr(-1) !== ':') protocol += ':';
|
||||
|
||||
|
@ -476,6 +476,55 @@ var parseTests = {
|
||||
'href': 'www.example.com',
|
||||
'pathname': 'www.example.com',
|
||||
'path': 'www.example.com'
|
||||
},
|
||||
// ipv6 support
|
||||
'[fe80::1]': {
|
||||
'href': '[fe80::1]',
|
||||
'pathname': '[fe80::1]',
|
||||
'path': '[fe80::1]'
|
||||
},
|
||||
'coap://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]': {
|
||||
'protocol': 'coap:',
|
||||
'slashes': true,
|
||||
'host': '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]',
|
||||
'hostname': 'fedc:ba98:7654:3210:fedc:ba98:7654:3210',
|
||||
'href': 'coap://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/',
|
||||
'pathname': '/',
|
||||
'path': '/'
|
||||
},
|
||||
'coap://[1080:0:0:0:8:800:200C:417A]:61616/': {
|
||||
'protocol': 'coap:',
|
||||
'slashes': true,
|
||||
'host': '[1080:0:0:0:8:800:200c:417a]:61616',
|
||||
'port': '61616',
|
||||
'hostname': '1080:0:0:0:8:800:200c:417a',
|
||||
'href': 'coap://[1080:0:0:0:8:800:200c:417a]:61616/',
|
||||
'pathname': '/',
|
||||
'path': '/'
|
||||
},
|
||||
'http://user:password@[3ffe:2a00:100:7031::1]:8080': {
|
||||
'protocol': 'http:',
|
||||
'slashes': true,
|
||||
'auth': 'user:password',
|
||||
'host': '[3ffe:2a00:100:7031::1]:8080',
|
||||
'port': '8080',
|
||||
'hostname': '3ffe:2a00:100:7031::1',
|
||||
'href': 'http://user:password@[3ffe:2a00:100:7031::1]:8080/',
|
||||
'pathname': '/',
|
||||
'path': '/'
|
||||
},
|
||||
'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature': {
|
||||
'protocol': 'coap:',
|
||||
'slashes': true,
|
||||
'auth': 'u:p',
|
||||
'host': '[::192.9.5.5]:61616',
|
||||
'port': '61616',
|
||||
'hostname': '::192.9.5.5',
|
||||
'href': 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature',
|
||||
'search': '?n=Temperature',
|
||||
'query': 'n=Temperature',
|
||||
'pathname': '/.well-known/r',
|
||||
'path': '/.well-known/r?n=Temperature'
|
||||
}
|
||||
};
|
||||
|
||||
@ -650,6 +699,22 @@ var formatTests = {
|
||||
'hostname': 'foo',
|
||||
'protocol': 'dot.test:',
|
||||
'pathname': '/bar'
|
||||
},
|
||||
// ipv6 support
|
||||
'coap:u:p@[::1]:61616/.well-known/r?n=Temperature': {
|
||||
'href': 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature',
|
||||
'protocol': 'coap:',
|
||||
'auth': 'u:p',
|
||||
'hostname': '::1',
|
||||
'port': '61616',
|
||||
'pathname': '/.well-known/r',
|
||||
'search': 'n=Temperature'
|
||||
},
|
||||
'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton': {
|
||||
'href': 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton',
|
||||
'protocol': 'coap',
|
||||
'host': '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616',
|
||||
'pathname': '/s/stopButton'
|
||||
}
|
||||
};
|
||||
for (var u in formatTests) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user