Check if a JavaScript string is a URL

前端 未结 30 3387
野趣味
野趣味 2020-11-22 15:41

Is there a way in JavaScript to check if a string is a URL?

RegExes are excluded because the URL is most likely written like stackoverflow; that is to s

30条回答
  •  自闭症患者
    2020-11-22 16:36

    This is quite difficult to do with pure regex because URLs have many 'inconveniences'.

    1. For example domain names have complicated restrictions on hyphens:

      a. It is allowed to have many consecutive hyphens in the middle.

      b. but the first character and last character of the domain name cannot be a hyphen

      c. The 3rd and 4th character cannot be both hyphen

    2. Similarly port number can only be in the range 1-65535. This is easy to check if you extract the port part and convert to int but quite difficult to check with a regular expression.

    3. There is also no easy way to check valid domain extensions. Some countries have second-level domains(such as 'co.uk'), or the extension can be a long word such as '.international'. And new TLDs are added regularly. This type of things can only be checked against a hard-coded list. (see https://en.wikipedia.org/wiki/Top-level_domain)

    4. Then there are magnet urls, ftp addresses etc. These all have different requirements.

    Nevertheless, here is a function that handles pretty much everything except:

    • Case 1. c
    • Accepts any 1-5 digit port number
    • Accepts any extension 2-13 chars
    • Does not accept ftp, magnet, etc...

    function isValidURL(input) {
        pattern = '^(https?:\\/\\/)?' + // protocol
            '((([a-zA-Z\\d]([a-zA-Z\\d-]{0,61}[a-zA-Z\\d])*\\.)+' + // sub-domain + domain name
            '[a-zA-Z]{2,13})' + // extension
            '|((\\d{1,3}\\.){3}\\d{1,3})' + // OR ip (v4) address
            '|localhost)' + // OR localhost
            '(\\:\\d{1,5})?' + // port
            '(\\/[a-zA-Z\\&\\d%_.~+-:@]*)*' + // path
            '(\\?[a-zA-Z\\&\\d%_.,~+-:@=;&]*)?' + // query string
            '(\\#[-a-zA-Z&\\d_]*)?$'; // fragment locator
        regex = new RegExp(pattern);
        return regex.test(input);
    }
    
    let tests = [];
    tests.push(['', false]);
    tests.push(['http://en.wikipedia.org/wiki/Procter_&_Gamble', true]);
    tests.push(['https://sdfasd', false]);
    tests.push(['http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&docid=nIv5rk2GyP3hXM&tbnid=isiOkMe3nCtexM:&ved=0CAUQjRw&url=http%3A%2F%2Fanimalcrossing.wikia.com%2Fwiki%2FLion&ei=ygZXU_2fGKbMsQTf4YLgAQ&bvm=bv.65177938,d.aWc&psig=AFQjCNEpBfKnal9kU7Zu4n7RnEt2nerN4g&ust=1398298682009707', true]);
    tests.push(['https://stackoverflow.com/', true]);
    tests.push(['https://w', false]);
    tests.push(['aaa', false]);
    tests.push(['aaaa', false]);
    tests.push(['oh.my', true]);
    tests.push(['dfdsfdsfdfdsfsdfs', false]);
    tests.push(['google.co.uk', true]);
    tests.push(['test-domain.MUSEUM', true]);
    tests.push(['-hyphen-start.gov.tr', false]);
    tests.push(['hyphen-end-.com', false]);
    tests.push(['https://sdfasdp.international', true]);
    tests.push(['https://sdfasdp.pppppppp', false]);
    tests.push(['https://sdfasdp.ppppppppppppppppppp', false]);
    tests.push(['https://sdfasd', false]);
    tests.push(['https://sub1.1234.sub3.sub4.sub5.co.uk/?', true]);
    tests.push(['http://www.google-com.123', false]);
    tests.push(['http://my--testdomain.com', false]);
    tests.push(['http://my2nd--testdomain.com', true]);
    tests.push(['http://thingiverse.com/download:1894343', true]);
    tests.push(['https://medium.com/@techytimo', true]);
    tests.push(['http://localhost', true]);
    tests.push(['localhost', true]);
    tests.push(['localhost:8080', true]);
    tests.push(['localhost:65536', true]);
    tests.push(['localhost:80000', false]);
    tests.push(['magnet:?xt=urn:btih:123', true]);
    
    for (let i = 0; i < tests.length; i++) {
        console.log('Test #' + i + (isValidURL(tests[i][0]) == tests[i][1] ? ' passed' : ' failed') + ' on ["' + tests[i][0] + '", ' + tests[i][1] + ']');
    }

提交回复
热议问题