docs: function knMakeSource(str)
  {
  	var protocol, host, portstr, port, uri, c, matched;
  
  	if (mod_jsprim.startsWith(str, 'https://')) {
  		protocol = 'https';
  		port = 443;
  		str = str.substr('https://'.length);
  	} else {
  		protocol = 'http';
  		port = 80;
  
  		if (mod_jsprim.startsWith(str, 'http://'))
  			str = str.substr('http://'.length);
  	}
  
  	c = str.indexOf('/');
  	if (c == -1) {
  		uri = knDefaultUri;
  	} else {
  		uri = str.substr(c);
  		str = str.substr(0, c);
  	}
  
  	if ((matched = IPV4_HOST.exec(str)) !== null) {
  		host = matched[1];
  		portstr = matched[2];
  		if (!mod_net.isIPv4(host)) {
  			throw new Error('bad IPv4 address: ' +
  			    JSON.stringify(host));
  		}
  	} else if ((matched = IPV6_HOST.exec(str)) !== null) {
  		host = matched[1];
  		portstr = matched[2];
  		if (!mod_net.isIPv6(host)) {
  			throw new Error('bad IPv6 address: ' +
  			    JSON.stringify(host));
  		}
  	} else if ((matched = DOMAIN_HOST.exec(str)) !== null) {
  		host = matched[1];
  		portstr = matched[2];
  	} else {
  		throw (new Error('no host specified'));
  	}
  
  	if (portstr !== undefined) {
  		mod_assert.equal(portstr[0], ':');
  		portstr = portstr.slice(1);
  		port = mod_jsprim.parseInteger(portstr, { allowSign: false });
  
  		if (port instanceof Error) {
  			throw (new VError(port, 'invalid port'));
  		}
  
  		if (port < 1 || port > 65535) {
  			throw (new Error('invalid port: ' +
  			    portstr + ' (must be in range 1-65535)'));
  		}
  	}
  
  	return ({
  		protocol: protocol,
  		host: host,
  		port: port,
  		path: uri
  	});
  }