UNPKG

whistle

Version:

HTTP, HTTP2, HTTPS, Websocket debugging proxy

212 lines (178 loc) 4.57 kB
var parseUrl = require('url').parse; var CONTROL_RE = /^[\n\r\t\x00-\x20\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/; var PROTOCOL_RE = /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i; var WIN_DRIVE_RE = /^[a-zA-Z]:/; var PORT_RE = /:(\d*)$/; function formatHost(host) { if (host[0] === '[') { var end = host.length - 1; if (host[end] === ']') { host = host.substring(1, end); } } return host; } function needPort(port, protocol) { protocol = protocol.split(':')[0]; port = +port; if (!port) { return false; } switch (protocol) { case 'http': case 'ws': return port !== 80; case 'https': case 'wss': return port !== 443; case 'ftp': return port !== 21; case 'gopher': return port !== 70; case 'file': return false; } return port !== 0; } function getProtocol(addr) { var match = PROTOCOL_RE.exec(addr); var protocol = match[1] ? match[1].toLowerCase() : ''; var forwardSlashes = match[2] || ''; var otherSlashes = match[3] || ''; var slashesCount = forwardSlashes.length + otherSlashes.length; var rest = forwardSlashes + otherSlashes + match[4]; if (protocol === 'file:') { if (slashesCount >= 2) { rest = rest.slice(2); } } else if (protocol && forwardSlashes) { rest = rest.slice(2); } return { protocol: protocol, slashes: !!forwardSlashes, slashesCount: slashesCount, rest: rest }; } function encode(str) { try { return encodeURIComponent(decodeURIComponent(str)); } catch (e) { return ''; } } function formatPath(url) { if (url.pathname.charAt(0) !== '/') { url.pathname = '/' + url.pathname; } } function formatPort(url) { if (!needPort(url.port, url.protocol)) { url.host = url.hostname; url.port = ''; } } function parseAuth(url) { url.username = url.password = ''; if (url.auth) { var index = url.auth.indexOf(':'); if (index !== -1) { url.username = url.auth.slice(0, index); url.username = encode(url.username); url.password = url.auth.slice(index + 1); url.password = encode(url.password); } else { url.username = encode(url.auth); } url.auth = url.password ? url.username + ':' + url.password : url.username; } } function formatOrigin(url) { var protocol = url.protocol; if (protocol !== 'file:' && url.host) { url.origin = protocol +'//'+ url.host; } else { url.origin = 'null'; } } function formatUrl(url) { var host = url.host; var protocol = url.protocol; var result = protocol + (protocol && url.slashes ? '//' : ''); if (url.username) { result += url.username; if (url.password) { result += ':' + url.password; } result += '@'; } else if (url.password) { result += ':' + url.password + '@'; } result += host + url.pathname; if (url.search) { result += url.search; } if (url.hash) { result += url.hash; } url.href = result; } module.exports = function(addr) { try { return parseUrl(addr); } catch (e) {} addr = String(addr || '').replace(CONTROL_RE, ''); var url = {}; var result = getProtocol(addr); var protocol = result.protocol; url.slashes = result.slashes; url.protocol = protocol; addr = result.rest; var index = addr.indexOf('#'); if (index !== -1) { url.hash = addr.substring(index); addr = addr.substring(0, index); } index = addr.indexOf('?'); if (index !== -1) { url.search = addr.substring(index); url.query = addr.substring(index + 1); addr = addr.substring(0, index); } if ( (protocol === 'file:' && (result.slashesCount !== 2 || WIN_DRIVE_RE.test(addr))) || (!result.slashes && (protocol || result.slashesCount < 2)) ) { url.pathname = addr; url.host = url.hostname = ''; } else { index = addr.indexOf('/'); if (index !== -1) { url.pathname = addr.substring(index); addr = addr.substring(0, index); } else { url.pathname = '/'; } url.path = url.pathname + (url.search || ''); index = addr.lastIndexOf('@'); if (index !== -1) { url.auth = addr.substring(0, index); addr = addr.substring(index + 1); } url.host = addr; index = PORT_RE.exec(addr); if (index) { url.port = index[1]; addr = addr.substring(0, index.index); } url.hostname = formatHost(addr); } formatPath(url); formatPort(url); parseAuth(url); formatOrigin(url); formatUrl(url); return url; }; module.exports.formatHost = formatHost;