(options?: URLValidateFnOptions)
| 101 | |
| 102 | const allowedHTTPHosts = ['localhost', '127.0.0.1'] |
| 103 | export const urlValidateFn = (options?: URLValidateFnOptions): ValidateFunction<string> => { |
| 104 | return (input: string): true | string => { |
| 105 | try { |
| 106 | const url = new URL(input) |
| 107 | // Invalid URLs with only a single `/` get parsed fine by `new URL` but of course are not |
| 108 | // accepted by APIs so we test specifically for that here. |
| 109 | if (!input.match(/^\w+:\/\//)) { |
| 110 | throw { code: 'ERR_INVALID_URL' } |
| 111 | } |
| 112 | if (url.port) { |
| 113 | const minPort = options?.minPort ?? 1 |
| 114 | const maxPort = options?.maxPort ?? 65535 |
| 115 | const portNum = parseInt(url.port) |
| 116 | if (portNum < minPort || portNum > maxPort) { |
| 117 | return `Port must be between ${minPort} and ${maxPort} inclusive.` |
| 118 | } |
| 119 | } |
| 120 | if (options?.httpsRequired) { |
| 121 | if (options.allowLocalhostHTTP) { |
| 122 | return url.protocol === 'https:' || |
| 123 | url.protocol === 'http:' && allowedHTTPHosts.includes(url.hostname) || |
| 124 | 'https is required except for localhost' |
| 125 | } |
| 126 | return url.protocol === 'https:' || 'https protocol is required' |
| 127 | } |
| 128 | return url.protocol === 'https:' || url.protocol === 'http:' || 'http(s) protocol is required' |
| 129 | } catch (error) { |
| 130 | if (error.code === 'ERR_INVALID_URL') { |
| 131 | return `must be a valid URL${options?.httpsRequired ? ' with https protocol' : ''}` |
| 132 | } else { |
| 133 | throw error |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | // Email regex found on Stack Overflow: |
| 140 | // https://stackoverflow.com/questions/201323/how-can-i-validate-an-email-address-using-a-regular-expression |
no outgoing calls
no test coverage detected