在JavaScript中是否有一种方法来检查字符串是否是URL?

regex被排除在外,因为URL很可能写成stackoverflow;也就是说,它可能没有。com, WWW或http。


当前回答

如果你可以改变输入类型,我认为这个解决方案会更容易:

你可以简单地在输入中使用type="url",并在js中使用checkValidity()检查它

E.g:

your.html

<input id="foo" type="url">

your.js

// The selector is JQuery, but the function is plain JS
$("#foo").on("keyup", function() {
    if (this.checkValidity()) {
        // The url is valid
    } else {
        // The url is invalid
    }
});

其他回答

这似乎是CS中最难的问题之一;)

这是另一个不完整的解决方案,它对我来说足够好,比我在这里看到的其他解决方案更好。为了支持IE11,我使用了一个输入[type=url],否则使用window会简单得多。URL来执行验证:

const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/; function isValidIpv4(ip) { if (!ipv4Regex.test(ip)) return false; return !ip.split('.').find(n => n > 255); } const domainRegex = /(?:[a-z0-9-]{1,63}\.){1,125}[a-z]{2,63}$/i; function isValidDomain(domain) { return isValidIpv4(domain) || domainRegex.test(domain); } let input; function validateUrl(url) { if (! /^https?:\/\//.test(url)) url = `http://${url}`; // assuming Babel is used // to support IE11 we'll resort to input[type=url] instead of window.URL: // try { return isValidDomain(new URL(url).host) && url; } catch(e) { return false; } if (!input) { input = document.createElement('input'); input.type = 'url'; } input.value = url; if (! input.validity.valid) return false; const domain = url.split(/^https?:\/\//)[1].split('/')[0].split('@').pop(); return isValidDomain(domain) && url; } console.log(validateUrl('google'), // false validateUrl('user:pw@mydomain.com'), validateUrl('https://google.com'), validateUrl('100.100.100.100/abc'), validateUrl('100.100.100.256/abc')); // false

为了接受不完整的输入,例如“www.mydomain.com”,它还将使其有效,假设在这些情况下协议是“http”,如果地址有效,则返回有效的URL。无效时返回false。

它还支持IPv4域,但不支持IPv6域。

我建议使用锚元素,而不是使用正则表达式。

当你设置一个锚的href属性时,其他各种属性也会被设置。

var parser = document.createElement('a');
parser.href = "http://example.com:3000/pathname/?search=test#hash";

parser.protocol; // => "http:"
parser.hostname; // => "example.com"
parser.port;     // => "3000"
parser.pathname; // => "/pathname/"
parser.search;   // => "?search=test"
parser.hash;     // => "#hash"
parser.host;     // => "example.com:3000"

但是,如果href绑定的值不是一个有效的url,那么这些辅助属性的值将是空字符串。

编辑:正如评论中指出的:如果使用了无效的url,则可以替换当前url的属性。

所以,只要你没有传递当前页面的URL,你可以这样做:

function isValidURL(str) {
   var a  = document.createElement('a');
   a.href = str;
   return (a.host && a.host != window.location.host);
}

这显然不是最有效的方法,但它是可读的,并且很容易形成您需要的任何形式。从这里添加regex/complexity更容易。这是一个非常实用的方法

const validFirstBits = ["ftp://", "http://", "https://", "www."];
const invalidPatterns = [" ", "//.", ".."];

export function isUrl(word) {
// less than www.1.dk
if (!word || word.length < 8) return false;

// Let's check and see, if our candidate starts with some of our valid first bits
const firstBitIsValid = validFirstBits.some(bit => word.indexOf(bit) === 0);
if (!firstBitIsValid) return false;

const hasInvalidPatterns = invalidPatterns.some(
    pattern => word.indexOf(pattern) !== -1,
);

if (hasInvalidPatterns) return false;

const dotSplit = word.split(".");
if (dotSplit.length > 1) {
    const lastBit = dotSplit.pop(); // string or undefined
    if (!lastBit) return false;
    const length = lastBit.length;
    const lastBitIsValid =
        length > 1 || (length === 1 && !isNaN(parseInt(lastBit)));
    return !!lastBitIsValid;
}

    return false;
}

测试:

import { isUrl } from "./foo";

describe("Foo", () => {
    test("should validate correct urls correctly", function() {
        const validUrls = [
            "http://example.com",
            "http://example.com/blah",
            "http://127.0.0.1",
            "http://127.0.0.1/wow",
            "https://example.com",
            "https://example.com/blah",
            "https://127.0.0.1:1234",
            "ftp://example.com",
            "ftp://example.com/blah",
            "ftp://127.0.0.1",
            "www.example.com",
            "www.example.com/blah",
        ];

        validUrls.forEach(url => {
            expect(isUrl(url) && url).toEqual(url);
        });
    });

    test("should validate invalid urls correctly", function() {
        const inValidUrls = [
            "http:// foo.com",
            "http:/foo.com",
            "http://.foo.com",
            "http://foo..com",
            "http://.com",
            "http://foo",
            "http://foo.c",
        ];

        inValidUrls.forEach(url => {
            expect(!isUrl(url) && url).toEqual(url);
        });
    });
});

使用纯正则表达式很难做到这一点,因为url有很多“不方便”的地方。

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 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. 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) Then there are magnet urls, ftp addresses etc. These all have different requirements.

然而,这里有一个函数可以处理几乎所有的事情,除了:

案例1。c 接受任何1-5位数的端口号 接受任何扩展2-13个字符 不接受ftp,磁铁等…

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] + ']'); }

如果你想检查一个字符串是否是有效的HTTP URL,你可以使用URL构造函数(它会抛出一个畸形的字符串):

函数isValidHttpUrl(string) { 让url; 尝试{ url =新的url(字符串); } catch (_) { 返回错误; } 返回的url。Protocol === "http:" || url。协议=== "https:"; } console.log (" http://example.com " + isValidHttpUrl (" https://example.com ")); console.log (" example.com " + isValidHttpUrl (" example.com "));

注意:根据RFC 3886, URL必须以一个方案开头(不限于http/https),例如:

www.example.com不是有效的URL(缺少方案) void(0)是有效的URL,但不是HTTP URL http://.。是有效的URL,主机是..(是否解析取决于你的DNS) https://example..com是有效的URL,与上面相同