1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
Description: Handle the case where the port is specified but empty
Author: Luigi Pinca <luigipinca@gmail.com>
Origin: upstream, https://github.com/unshiftio/url-parse/commit/d5c64791
Bug: https://huntr.dev/bounties/55fd06cd-9054-4d80-83be-eb5a454be78c
Forwarded: not-needed
Reviewed-By: Yadd <yadd@debian.org>
Last-Update: 2022-03-23
--- a/index.js
+++ b/index.js
@@ -3,6 +3,7 @@
var required = require('requires-port')
, qs = require('querystringify')
, slashes = /^[A-Za-z][A-Za-z0-9+-.]*:\/\//
+ , port = /:\d+$/
, protocolre = /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i
, windowsDriveLetter = /^[a-zA-Z]:/
, whitespace = '[\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF]'
@@ -39,7 +40,7 @@
['/', 'pathname'], // Extract from the back.
['@', 'auth', 1], // Extract from the front.
[NaN, 'host', undefined, 1, 1], // Set left over value.
- [/:(\d+)$/, 'port', undefined, 1], // RegExp the back.
+ [/:(\d*)$/, 'port', undefined, 1], // RegExp the back.
[NaN, 'hostname', undefined, 1, 1] // Set left over.
];
@@ -433,7 +434,7 @@
case 'host':
url[part] = value;
- if (/:\d+$/.test(value)) {
+ if (port.test(value)) {
value = value.split(':');
url.port = value.pop();
url.hostname = value.join(':');
@@ -490,6 +491,7 @@
var query
, url = this
+ , host = url.host
, protocol = url.protocol;
if (protocol && protocol.charAt(protocol.length - 1) !== ':') protocol += ':';
@@ -502,7 +504,15 @@
result += '@';
}
- result += url.host + url.pathname;
+ //
+ // Trailing colon is removed from `url.host` when it is parsed. If it still
+ // ends with a colon, then add back the trailing colon that was removed. This
+ // prevents an invalid URL from being transformed into a valid one.
+ //
+ if (host[host.length - 1] === ':' || (port.test(url.hostname) && !url.port)) {
+ host += ':';
+ }
+ result += host + url.pathname;
query = 'object' === typeof url.query ? stringify(url.query) : url.query;
if (query) result += '?' !== query.charAt(0) ? '?'+ query : query;
--- a/test/test.js
+++ b/test/test.js
@@ -401,6 +401,28 @@
assume(parsed.slashes).is.true();
});
+ it('handles the case where the port is specified but empty', function () {
+ var parsed = parse('http://example.com:');
+
+ assume(parsed.protocol).equals('http:');
+ assume(parsed.port).equals('');
+ assume(parsed.host).equals('example.com');
+ assume(parsed.hostname).equals('example.com');
+ assume(parsed.pathname).equals('/');
+ assume(parsed.origin).equals('http://example.com');
+ assume(parsed.href).equals('http://example.com/');
+
+ parsed = parse('http://example.com::');
+
+ assume(parsed.protocol).equals('http:');
+ assume(parsed.port).equals('');
+ assume(parsed.host).equals('example.com:');
+ assume(parsed.hostname).equals('example.com:');
+ assume(parsed.pathname).equals('/');
+ assume(parsed.origin).equals('http://example.com:');
+ assume(parsed.href).equals('http://example.com::/');
+ });
+
describe('origin', function () {
it('generates an origin property', function () {
var url = 'http://google.com:80/pathname'
|