1 import type { SanitizedUrl } from './types';
2 import { MAX_HOSTNAME_LENGTH, RegexURL, isValidScheme } from './utils';
4 /* Will first try to validate against the URL constructor.
5 * If it fails, try to append https:// scheme and revalidate
6 * Final step is to test against a URL regex (https://urlregex.com/) */
7 export const sanitizeURL = (maybeUrl: string, scheme?: string): SanitizedUrl => {
9 if (!maybeUrl) return { valid: false, protocol: null, port: null, hostname: null, url: maybeUrl };
11 const url = (scheme ? `${scheme}//${maybeUrl}` : maybeUrl).trim();
12 /* invalidate if contains white-space after sanitization */
13 if (/\s/.test(url)) return { valid: false, protocol: null, port: null, hostname: null, url };
15 /* will throw a TypeError on invalid URL */
16 const urlObj = new URL(url);
18 /* if scheme is unsupported for our use-case */
19 if (!isValidScheme(urlObj)) return { valid: false, hostname: null, protocol: null, port: null, url };
21 const { protocol, hostname, href, port } = urlObj;
22 const valid = hostname.length <= MAX_HOSTNAME_LENGTH && Boolean(RegexURL.test(urlObj.href));
23 return { valid, hostname, protocol, port: port || null, url: href };
25 const startsWithHttpProtocol = /^https?:\/\//.test(maybeUrl);
26 return scheme === undefined && !startsWithHttpProtocol
27 ? sanitizeURL(maybeUrl, 'https:')
28 : { valid: false, hostname: null, protocol: null, port: null, url: maybeUrl };