UNPKG

mockttp

Version:

Mock HTTP server for testing HTTP clients and stubbing webservices

154 lines 5.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.normalizeUrl = exports.normalizeHost = exports.getDestination = exports.getEffectivePort = exports.getDefaultPort = exports.getPathFromAbsoluteUrl = exports.getHostFromAbsoluteUrl = exports.getUrlWithoutProtocol = exports.isAbsoluteProtocollessUrl = exports.isRelativeUrl = exports.isAbsoluteUrl = void 0; const url = require("url"); const _ = require("lodash"); const util_1 = require("./util"); // Is this URL fully qualified? // Note that this supports only HTTP - no websockets or anything else. const isAbsoluteUrl = (url) => url.toLowerCase().startsWith('http://') || url.toLowerCase().startsWith('https://'); exports.isAbsoluteUrl = isAbsoluteUrl; const isRelativeUrl = (url) => url.startsWith('/'); exports.isRelativeUrl = isRelativeUrl; const isAbsoluteProtocollessUrl = (url) => !(0, exports.isAbsoluteUrl)(url) && !(0, exports.isRelativeUrl)(url); exports.isAbsoluteProtocollessUrl = isAbsoluteProtocollessUrl; const getUrlWithoutProtocol = (url) => { return url.split('://', 2).slice(-1).join(''); }; exports.getUrlWithoutProtocol = getUrlWithoutProtocol; const getHostFromAbsoluteUrl = (url) => { const hostIndex = (0, util_1.nthIndexOf)(url, '/', 2); const pathIndex = (0, util_1.nthIndexOf)(url, '/', 3); if (pathIndex !== -1) { return url.slice(hostIndex + 1, pathIndex); } else { return url.slice(hostIndex + 1); } }; exports.getHostFromAbsoluteUrl = getHostFromAbsoluteUrl; const getPathFromAbsoluteUrl = (url) => { const pathIndex = (0, util_1.nthIndexOf)(url, '/', 3); if (pathIndex !== -1) { return url.slice(pathIndex); } else { return '/'; } }; exports.getPathFromAbsoluteUrl = getPathFromAbsoluteUrl; const getDefaultPort = (protocol) => { if (protocol[protocol.length - 1] === ':') { protocol = protocol.slice(0, -1); } if (protocol === 'https' || protocol === 'wss') { return 443; } else if (protocol === 'http' || protocol === 'ws') { return 80; } else { throw new Error(`Unknown protocol: ${protocol}`); } }; exports.getDefaultPort = getDefaultPort; const getEffectivePort = (url) => { if (url.port) { return parseInt(url.port, 10); } else { return (0, exports.getDefaultPort)(url.protocol || 'http'); } }; exports.getEffectivePort = getEffectivePort; const getDestination = (protocol, host) => { let hostname; let portString; const lastColonIndex = host.lastIndexOf(':'); if (lastColonIndex !== -1) { hostname = host.slice(0, lastColonIndex); portString = host.slice(lastColonIndex + 1); } else { hostname = host; portString = undefined; } if (hostname[0] === '[' && hostname[hostname.length - 1] === ']') { // Bracketed IPv6 address, drop the brackets: hostname = hostname.slice(1, -1); } const port = portString ? parseInt(portString, 10) : (0, exports.getDefaultPort)(protocol); if (isNaN(port)) { throw new Error(`Invalid port: ${portString}`); } return { hostname, port }; }; exports.getDestination = getDestination; const normalizeHost = (protocol, host) => { const { hostname, port } = (0, exports.getDestination)(protocol, host); if (port === (0, exports.getDefaultPort)(protocol)) { return hostname; } else { return `${hostname}:${port}`; } }; exports.normalizeHost = normalizeHost; /** * Normalizes URLs to the form used when matching them. * * This accepts URLs in all three formats: relative, absolute, and protocolless-absolute, * and returns them in the same format but normalized. */ exports.normalizeUrl = _.memoize((urlInput) => { let parsedUrl; let isProtocolless = false; try { // Strip the query and anything following it const queryIndex = urlInput.indexOf('?'); if (queryIndex !== -1) { urlInput = urlInput.slice(0, queryIndex); } if ((0, exports.isAbsoluteProtocollessUrl)(urlInput)) { parsedUrl = url.parse('http://' + urlInput); isProtocolless = true; } else { parsedUrl = url.parse(urlInput); } // Trim out lots of the bits we don't like: delete parsedUrl.host; delete parsedUrl.query; delete parsedUrl.search; delete parsedUrl.hash; if (parsedUrl.pathname) { parsedUrl.pathname = parsedUrl.pathname.replace(/\%[A-Fa-z0-9]{2}/g, (encoded) => encoded.toUpperCase()).replace(/[^\u0000-\u007F]+/g, (unicodeChar) => encodeURIComponent(unicodeChar)); } if (parsedUrl.hostname?.endsWith('.')) { parsedUrl.hostname = parsedUrl.hostname.slice(0, -1); } if ((parsedUrl.protocol === 'https:' && parsedUrl.port === '443') || (parsedUrl.protocol === 'http:' && parsedUrl.port === '80')) { delete parsedUrl.port; } } catch (e) { console.log(`Failed to normalize URL ${urlInput}`); console.log(e); if (!parsedUrl) return urlInput; // Totally unparseble: use as-is // If we've successfully parsed it, we format what we managed // and leave it at that: } let normalizedUrl = url.format(parsedUrl); // If the URL came in with no protocol, it should leave with // no protocol (protocol added temporarily above to allow parsing) if (isProtocolless) { normalizedUrl = normalizedUrl.slice('http://'.length); } return normalizedUrl; }); //# sourceMappingURL=url.js.map