JavaScript中是否可以检查字符串是否为URL?
RegExes被排除在外,因为URL的写法很可能像stackoverflow
;也就是说,它可能没有.com
,www
或者http
。
href
时起作用,在锚元素中解析为,在调用时起作用window.open(url)
,指向确实存在的东西,在浏览器位置中起作用酒吧,还是以上的组合?根据您关心的答案,您将获得截然不同的答案。
JavaScript中是否可以检查字符串是否为URL?
RegExes被排除在外,因为URL的写法很可能像stackoverflow
;也就是说,它可能没有.com
,www
或者http
。
href
时起作用,在锚元素中解析为,在调用时起作用window.open(url)
,指向确实存在的东西,在浏览器位置中起作用酒吧,还是以上的组合?根据您关心的答案,您将获得截然不同的答案。
Answers:
一个与答案相关的问题:
或者来自Devshed的 Regexp :
function validURL(str) {
var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
'(\\#[-a-z\\d_]*)?$','i'); // fragment locator
return !!pattern.test(str);
}
{ title: "Stackoverflow", uri: "http://stackoverflow.com" }
Update:的确,请参见code.google.com/chrome/extensions/bookmarks.html
invalid quantifier
。任何想法?
SyntaxError: Invalid regular expression: /^(https?://)?((([a-zd]([a-zd-]*[a-zd])*).)+[a-z]{2,}|((d{1,3}.){3}d{1,3}))(:d+)?(/[-a-zd%_.~+]*)*(?[;&a-zd%_.~+=-]*)?(#[-a-zd_]*)?$/: Invalid group
Google Chrome(版本30.0.1599.101)(Mac OS X:10.8.5)
RegExp
必须加倍转义反斜杠-否则会出现诸如无效组之类的错误。
function isURL(str) {
var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|'+ // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
'(\\#[-a-z\\d_]*)?$','i'); // fragment locator
return pattern.test(str);
}
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
start = new Date(); isURL("http://michalstefanow.com"); end = new Date(); diff = end - start; console.log(diff)
我放上水壶,上了厕所,叫我妈妈,事情很快就完成了……
true
了aaa
。
isURL('12345678901234567890123')
添加更多字符,甚至更糟。
您可以尝试使用URL
构造函数:如果不抛出,则该字符串是有效的URL:
function isValidUrl(string) {
try {
new URL(string);
} catch (_) {
return false;
}
return true;
}
术语“ URL”在RFC 3886中定义为URI。它必须以方案名称开头,并且方案名称不限于http / https。
著名的例子:
www.google.com
网址无效(丢失方案)javascript:void(0)
是有效的网址,尽管不是HTTP网址http://..
是有效的URL,主机为..
; 是否解析取决于您的DNShttps://google..com
是有效的网址,与上面相同如果要检查字符串是否为有效的HTTP URL:
function isValidHttpUrl(string) {
let url;
try {
url = new URL(string);
} catch (_) {
return false;
}
return url.protocol === "http:" || url.protocol === "https:";
}
isValidUrl("javascript:void(0)")
http://..
或http:///a
建议不要使用正则表达式,而建议使用锚元素。
设置的href
属性时,还会设置anchor
其他各种属性。
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);
}
a.href
无效,则parser.host
返回您当前所在页面的主机名,而不是预期的false
。
<a href="invalidurl">
,则该链接会转到您的域。它被添加到当前URL的末尾。因此,Chrome通过为您提供来自“解析器”元素的当前主机名,从而可以正确地完成工作。
function isValidURL(str)
:比使用正则表达式好得多!谢谢!
我正在使用以下功能来验证带有或不带有URL http/https
:
function isValidURL(string) {
var res = string.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g);
return (res !== null)
};
var testCase1 = "http://en.wikipedia.org/wiki/Procter_&_Gamble";
console.log(isValidURL(testCase1)); // return true
var testCase2 = "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";
console.log(isValidURL(testCase2)); // return true
var testCase3 = "https://sdfasd";
console.log(isValidURL(testCase3)); // return false
var testCase4 = "dfdsfdsfdfdsfsdfs";
console.log(isValidURL(testCase4)); // return false
var testCase5 = "magnet:?xt=urn:btih:123";
console.log(isValidURL(testCase5)); // return false
var testCase6 = "https://stackoverflow.com/";
console.log(isValidURL(testCase6)); // return true
var testCase7 = "https://w";
console.log(isValidURL(testCase7)); // return false
var testCase8 = "https://sdfasdp.ppppppppppp";
console.log(isValidURL(testCase8)); // return false
https://sdfasdp.ppppppppppp
返回,true
但是false
我认为这是我的返回。
sadf@gmail.com
……应该吗?我猜应该不会
使用JavaScript验证网址如下所示
function ValidURL(str) {
var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
if(!regex .test(str)) {
alert("Please enter valid URL.");
return false;
} else {
return true;
}
}
(http|https)
到(?:https?)
; B):{0,1}
到:?
; c)[0-9]
至\d
依赖库:https : //www.npmjs.com/package/valid-url
import { isWebUri } from 'valid-url';
// ...
if (!isWebUri(url)) {
return "Not a valid url.";
}
{
在URL中输入
改进已接受答案...
在路径中允许@符号,例如https://medium.com/@techytimo
isURL(str) {
var pattern = new RegExp('^((ft|htt)ps?:\\/\\/)?'+ // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name and extension
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
'(\\:\\d+)?'+ // port
'(\\/[-a-z\\d%@_.~+&:]*)*'+ // path
'(\\?[;&a-z\\d%@_.,~+&:=-]*)?'+ // query string
'(\\#[-a-z\\d_]*)?$','i'); // fragment locator
return pattern.test(str);
}
这是另一种方法。
var elm;
function isValidURL(u){
if(!elm){
elm = document.createElement('input');
elm.setAttribute('type', 'url');
}
elm.value = u;
return elm.validity.valid;
}
console.log(isValidURL('http://www.google.com/'));
console.log(isValidURL('//google.com'));
console.log(isValidURL('google.com'));
console.log(isValidURL('localhost:8000'));
new URL(string)
Pavlo代码中的工作方式相同。在我测试的所有边缘情况下,两种测试的结果均相同。我喜欢他的代码,因为它更简单并且不涉及创建元素,但是您的代码却快了好几倍(可能是因为它在第一次使用后没有创建el)。
(我没有代表对ValidURL示例发表评论;因此请将此作为答复。)
虽然不鼓励使用协议相对URL(相对于协议URL),但有时确实会使用它们。为了使用正则表达式验证此类URL,协议部分可以是可选的,例如:
function isValidURL(str) {
var pattern = new RegExp('^((https?:)?\\/\\/)?'+ // protocol
'(?:\\S+(?::\\S*)?@)?' + // authentication
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
'(\\#[-a-z\\d_]*)?$','i'); // fragment locater
if (!pattern.test(str)) {
return false;
} else {
return true;
}
}
正如其他人指出的那样,正则表达式似乎并不是最适合验证URL的方法。
isValidURL("https://d1f4470da51b49289906b3d6cbd65074@app.getsentry.com/13176")
@
。它没有挂在我的浏览器中。
如前所述,完美的正则表达式是难以捉摸的,但似乎仍然是一种合理的方法(替代方案是服务器端测试或新的实验性URL API)。但是,对于通用网址,排名靠前的答案通常会返回false,但更糟糕的是,即使是像这样的简单字符串,它也会冻结您的应用程序/页面几分钟isURL('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
。一些评论中已经指出了这一点,但是很可能并没有看到不好的输入。这样的挂起使该代码无法在任何严肃的应用程序中使用。我认为这是由于代码中重复出现的不区分大小写的集合所致((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' ...
。取出“ i”,它不会挂起,但是当然不能按预期工作。但是,即使使用了忽略大小写标志,那些测试也会拒绝允许的高unicode值。
已经提到的最好的是:
function isURL(str) {
return /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(str);
}
这来自Github segmentio / is-url。关于代码存储库的好处是,您可以看到测试和任何问题,以及贯穿其中的测试字符串。有一个分支允许字符串缺少协议,例如google.com
,尽管您当时可能做过多的假设。存储库已更新,我不打算尝试在此处保留镜像。为了避免RegEx 重做可被DOS攻击利用,已将其分为多个测试(我不必担心客户端js会担心这一点,但是您确实需要担心页面挂了这么长时间以至于访客离开您的网站)。
我见过另外一个存储库,它可能在dperini / regex-weburl.js上对isURL可能更好,但是它非常复杂。它具有更大的有效和无效URL测试列表。上面简单的一个仍然可以传递所有正数,并且只能阻止一些奇数负数http://a.b--c.de/
以及特殊ip。
无论您选择哪种方式,都可以使用浏览器的“开发人员工具”检查器,通过我根据dperini / regex-weburl.js上的测试改编的此功能来运行它。
function testIsURL() {
//should match
console.assert(isURL("http://foo.com/blah_blah"));
console.assert(isURL("http://foo.com/blah_blah/"));
console.assert(isURL("http://foo.com/blah_blah_(wikipedia)"));
console.assert(isURL("http://foo.com/blah_blah_(wikipedia)_(again)"));
console.assert(isURL("http://www.example.com/wpstyle/?p=364"));
console.assert(isURL("https://www.example.com/foo/?bar=baz&inga=42&quux"));
console.assert(isURL("http://✪df.ws/123"));
console.assert(isURL("http://userid:password@example.com:8080"));
console.assert(isURL("http://userid:password@example.com:8080/"));
console.assert(isURL("http://userid@example.com"));
console.assert(isURL("http://userid@example.com/"));
console.assert(isURL("http://userid@example.com:8080"));
console.assert(isURL("http://userid@example.com:8080/"));
console.assert(isURL("http://userid:password@example.com"));
console.assert(isURL("http://userid:password@example.com/"));
console.assert(isURL("http://142.42.1.1/"));
console.assert(isURL("http://142.42.1.1:8080/"));
console.assert(isURL("http://➡.ws/䨹"));
console.assert(isURL("http://⌘.ws"));
console.assert(isURL("http://⌘.ws/"));
console.assert(isURL("http://foo.com/blah_(wikipedia)#cite-1"));
console.assert(isURL("http://foo.com/blah_(wikipedia)_blah#cite-1"));
console.assert(isURL("http://foo.com/unicode_(✪)_in_parens"));
console.assert(isURL("http://foo.com/(something)?after=parens"));
console.assert(isURL("http://☺.damowmow.com/"));
console.assert(isURL("http://code.google.com/events/#&product=browser"));
console.assert(isURL("http://j.mp"));
console.assert(isURL("ftp://foo.bar/baz"));
console.assert(isURL("http://foo.bar/?q=Test%20URL-encoded%20stuff"));
console.assert(isURL("http://مثال.إختبار"));
console.assert(isURL("http://例子.测试"));
console.assert(isURL("http://उदाहरण.परीक्षा"));
console.assert(isURL("http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com"));
console.assert(isURL("http://1337.net"));
console.assert(isURL("http://a.b-c.de"));
console.assert(isURL("http://223.255.255.254"));
console.assert(isURL("postgres://u:p@example.com:5702/db"));
console.assert(isURL("https://d1f4470da51b49289906b3d6cbd65074@app.getsentry.com/13176"));
//SHOULD NOT MATCH:
console.assert(!isURL("http://"));
console.assert(!isURL("http://."));
console.assert(!isURL("http://.."));
console.assert(!isURL("http://../"));
console.assert(!isURL("http://?"));
console.assert(!isURL("http://??"));
console.assert(!isURL("http://??/"));
console.assert(!isURL("http://#"));
console.assert(!isURL("http://##"));
console.assert(!isURL("http://##/"));
console.assert(!isURL("http://foo.bar?q=Spaces should be encoded"));
console.assert(!isURL("//"));
console.assert(!isURL("//a"));
console.assert(!isURL("///a"));
console.assert(!isURL("///"));
console.assert(!isURL("http:///a"));
console.assert(!isURL("foo.com"));
console.assert(!isURL("rdar://1234"));
console.assert(!isURL("h://test"));
console.assert(!isURL("http:// shouldfail.com"));
console.assert(!isURL(":// should fail"));
console.assert(!isURL("http://foo.bar/foo(bar)baz quux"));
console.assert(!isURL("ftps://foo.bar/"));
console.assert(!isURL("http://-error-.invalid/"));
console.assert(!isURL("http://a.b--c.de/"));
console.assert(!isURL("http://-a.b.co"));
console.assert(!isURL("http://a.b-.co"));
console.assert(!isURL("http://0.0.0.0"));
console.assert(!isURL("http://10.1.1.0"));
console.assert(!isURL("http://10.1.1.255"));
console.assert(!isURL("http://224.1.1.1"));
console.assert(!isURL("http://1.1.1.1.1"));
console.assert(!isURL("http://123.123.123"));
console.assert(!isURL("http://3628126748"));
console.assert(!isURL("http://.www.foo.bar/"));
console.assert(!isURL("http://www.foo.bar./"));
console.assert(!isURL("http://.www.foo.bar./"));
console.assert(!isURL("http://10.1.1.1"));}
然后测试“ a”的字符串。
在发布看似很棒的正则表达式之前,请参阅Mathias Bynens对isURL regex进行的比较,以获取更多信息。
isURL('a'.repeat(100))
数百万次/秒(来自dperini的更复杂的速度实际上更快)。([a-zA-Z] +)*形式的某些高阶答案将需要几个小时才能完成一次。查找RegEx重做以获取更多信息。
我无法评论离#5717133最近的帖子,但是下面是我弄清楚如何使@ tom-gullen regex工作的方式。
/^(https?:\/\/)?((([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3}))(\:\d+)?(\/[-a-z\d%_.~+]*)*(\?[;&a-z\d%_.~+=-]*)?(\#[-a-z\d_]*)?$/i
var pattern = new RegExp('(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$', 'i');
ES6
import isURL from 'validator/lib/isURL'
isURL(string)
没有ES6
var validator = require('validator');
validator.isURL(string)
您还可以通过传递可选options
对象作为的第二个参数来微调此函数的行为。isURL
这是默认options
对象:
let options = {
protocols: [
'http',
'https',
'ftp'
],
require_tld: true,
require_protocol: false,
require_host: true,
require_valid_protocol: true,
allow_underscores: false,
host_whitelist: false,
host_blacklist: false,
allow_trailing_dot: false,
allow_protocol_relative_urls: false,
disallow_auth: false
}
isURL(string, options)
host_whitelist
并且host_blacklist
可以是主机数组。它们还支持正则表达式。
let options = {
host_blacklist: ['foo.com', 'bar.com'],
}
isURL('http://foobar.com', options) // => true
isURL('http://foo.bar.com/', options) // => true
isURL('http://qux.com', options) // => true
isURL('http://bar.com/', options) // => false
isURL('http://foo.com/', options) // => false
options = {
host_blacklist: ['bar.com', 'foo.com', /\.foo\.com$/],
}
isURL('http://foobar.com', options) // => true
isURL('http://foo.bar.com/', options) // => true
isURL('http://qux.com', options) // => true
isURL('http://bar.com/', options) // => false
isURL('http://foo.com/', options) // => false
isURL('http://images.foo.com/', options) // => false
isURL('http://cdn.foo.com/', options) // => false
isURL('http://a.b.c.foo.com/', options) // => false
我用来验证URL“字符串”的一个函数是:
var matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;
function isUrl(string){
return matcher.test(string);
}
该函数将返回一个布尔值,无论字符串是否是URL。
例子:
isUrl("https://google.com"); // true
isUrl("http://google.com"); // true
isUrl("http://google.de"); // true
isUrl("//google.de"); // true
isUrl("google.de"); // false
isUrl("http://google.com"); // true
isUrl("http://localhost"); // true
isUrl("https://sdfasd"); // false
使用纯正则表达式很难做到这一点,因为URL有很多“不便”。
例如,域名对连字符有复杂的限制:
一个。中间可以有许多连续的连字符。
b。但是域名的第一个字符和最后一个字符不能为连字符
C。第三个和第四个字符不能都是连字符
同样,端口号只能在1-65535范围内。如果您提取端口部分并将其转换为,这很容易检查,int
但是使用正则表达式很难检查。
也没有简单的方法来检查有效的域扩展名。一些国家/地区具有二级域名(例如'co.uk'),或者扩展名可以是一个长词,例如'.international'。并定期添加新的TLD。此类内容只能通过硬编码列表进行检查。(请参阅https://en.wikipedia.org/wiki/Top-level_domain)
然后是磁铁URL,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] + ']');
}
我认为使用本地URL API优于@pavlo建议的复杂正则表达式模式。它有一些缺点,但是我们可以通过一些额外的代码来解决。对于以下有效网址,此方法将失败。
//cdn.google.com/script.js
我们可以预先添加缺少的协议以避免这种情况。它还无法检测到以下无效的URL。
http://w
http://..
那么,为什么要检查整个网址?我们可以只检查域。我借用了正则表达式从这里验证域。
function isValidUrl(string) {
if (string && string.length > 1 && string.slice(0, 2) == '//') {
string = 'http:' + string; //dummy protocol so that URL works
}
try {
var url = new URL(string);
return url.hostname && url.hostname.match(/^([a-z0-9])(([a-z0-9-]{1,61})?[a-z0-9]{1})?(\.[a-z0-9](([a-z0-9-]{1,61})?[a-z0-9]{1})?)?(\.[a-zA-Z]{2,4})+$/) ? true : false;
} catch (_) {
return false;
}
}
该hostname
属性是的空字符串javascript:void(0)
,因此也适用于此,您也可以添加IP地址验证程序。我最想坚持使用本机API,并希望它会在不久的将来开始支持所有功能。
new URL
在我完成的测试中没有。这是在调用:http://142.42.1.1 //false
并阻止高unicode字符串。
该问题要求一种验证方法来查询url之类的网址stackoverflow
,而该协议中没有协议或主机名中没有任何点。因此,验证URL sintax不是问题,而是通过实际调用来检查它是否为有效URL。
我尝试了几种方法来了解url是否存在并且可以从浏览器中调用,但是没有找到任何方法来使用javascript测试调用的响应标头:
click()
方法。'GET'
是可以的,但是由于CORS
策略的缘故,它具有各种限制,而不是使用的情况ajax
,因为url可能是服务器域之外的任何URL。https
协议之下,并且在调用非安全网址时会引发异常。因此,我能想到的最好的解决方案是CURL
使用javascript尝试一些工具来执行某些工具curl -I <url>
。不幸的是,我没有找到任何东西,而且看起来不可能。我对此表示感谢。
但是,最后,我运行了一个服务器PHP
,由于几乎所有请求都使用Ajax,因此我在服务器端编写了一个函数,以在其中执行curl请求并返回浏览器。
关于“ stackoverflow”问题上的单个网址,它将带我到https://daniserver.com.ar/stackoverflow
,daniserver.com.ar是我自己的域。
foo
并假设它是http或https或.com或.es或不计其数的后缀吗?您是否一直向厨房扔水槽,直到得到正确的结果?
这似乎是CS中最困难的问题之一;)
这是另一个不完整的解决方案,对我来说效果很好,并且比我在这里看到的其他解决方案更好。我为此使用input [type = url]来支持IE11,否则使用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。
这和我一起工作
function isURL(str) {
var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
var pattern = new RegExp(regex);
return pattern.test(str);
}
如果您可以更改输入类型,我认为此解决方案会容易得多:
您可以type="url"
在输入中简单使用,并checkValidity()
在js中进行检查
例如:
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
}
});
显然,这不是最有效的方法,但是它易于阅读,并且易于形成您所需的任何内容。从这里添加正则表达式/复杂性会更容易。所以这是一个非常务实的方法
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);
});
});
});
Mathias Bynens已编译了包含测试URL 的知名URL正则表达式列表。没有什么理由写一个新的正则表达式。只需选择一个最适合您的现有。
但是,这些正则表达式的比较表还显示,几乎不可能使用单个正则表达式进行URL验证。Bynens列表中的所有正则表达式都会产生误报和误报。
我建议您使用现有的URL解析器(例如,new URL('http://www.example.com/')
在JavaScript中),然后对要解析的URL解析形式和规范化形式应用要执行的检查。它的组件。使用JavaScript URL
界面的另一个好处是,它将仅接受浏览器真正接受的此类URL。
您还应该记住,技术上不正确的URL仍然可以使用。例如http://w_w_w.example.com/
,http://www..example.com/
,http://123.example.com/
都有一个无效的主机名的一部分,但每次我都知道浏览器将尝试打开它们无投诉,当你在这些无效名称指定IP地址/etc/hosts/
等的URL,甚至会工作,但只在您的计算机上。
因此,问题不仅仅在于URL是否有效,而在于在特定上下文中哪些URL有效并且应该被允许。
如果您想进行URL验证,那么有很多细节和边缘情况很容易忽略:
http://user:password@www.example.com/
。http://www.stackoverflow.com.
)。[-0-9a-zA-z]
肯定不再足够。co.uk
和许多其他名称空间)。这些限制和规则中的哪个适用于项目要求和口味。
我最近为Web应用程序编写了URL验证器,该验证器适用于论坛,社交网络等中用户提供的URL。随意将其用作自己的基础:
我还写了一篇博客文章《 URL验证的血腥细节》,其中包含更深入的信息。
我将函数更改为Match +,并在此处使用斜杠及其工作进行更改:(http://和https)
function isValidUrl(userInput) {
var res = userInput.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g);
if(res == null)
return false;
else
return true;
}
这只是一个非常简单的检查,以确保存在有效的协议,并且域扩展名必须是两个或更多字符。
is_valid_url = ( $url ) => {
let $url_object = null;
try {
$url_object = new URL( $url );
} catch ( $error ) {
return false;
}
const $protocol = $url_object.protocol;
const $protocol_position = $url.lastIndexOf( $protocol );
const $domain_extension_position = $url.lastIndexOf( '.' );
return (
$protocol_position === 0 &&
[ 'http:', 'https:' ].indexOf( $protocol ) !== - 1 &&
$domain_extension_position > 2 && $url.length - $domain_extension_position > 2
);
};
如果您还需要支持,请https://localhost:3000
使用此[Devshed] regex的修改版本。
function isURL(url) {
if(!url) return false;
var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))|' + // OR ip (v4) address
'localhost' + // OR localhost
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
'(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
return pattern.test(url);
}
有一些使用URL构造函数的测试,它们不能描述输入是字符串还是URL对象。
// Testing whether something is a URL
function isURL(url) {
return toString.call(url) === "[object URL]";
}
// Testing whether the input is both a string and valid url:
function isUrl(url) {
try {
return toString.call(url) === "[object String]" && !!(new URL(url));
} catch (_) {
return false;
}
}
2020更新。为了扩展@iamnewton和@Fernando Chavez Herrera的出色回答,我开始看到@
URL路径中使用了它。
因此,更新后的正则表达式为:
RegExp('(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+@]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$', 'i');
如果要在查询字符串和哈希中允许它,请使用:
RegExp('(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+@]*)*(\\?[;&a-z\\d%_.~+=-@]*)?(\\#[-a-z\\d_@]*)?$', 'i');
就是说,我不确定@
查询字符串或哈希中是否有禁止使用的白皮书规则。
http
,则默认情况下没有网址。