在JavaScript中是否有一种方法来检查字符串是否是URL?
regex被排除在外,因为URL很可能写成stackoverflow;也就是说,它可能没有。com, WWW或http。
在JavaScript中是否有一种方法来检查字符串是否是URL?
regex被排除在外,因为URL很可能写成stackoverflow;也就是说,它可能没有。com, WWW或http。
当前回答
这里还有另一种方法。
// ***note***: if the incoming value is empty(""), the function returns true var elm; function isValidURL(u){ //A precaution/solution for the problem written in the ***note*** if(u!==""){ if(!elm){ elm = document.createElement('input'); elm.setAttribute('type', 'url'); } elm.value = u; return elm.validity.valid; } else{ return false } } console.log(isValidURL('')); console.log(isValidURL('http://www.google.com/')); console.log(isValidURL('//google.com')); console.log(isValidURL('google.com')); console.log(isValidURL('localhost:8000'));
其他回答
我建议使用锚元素,而不是使用正则表达式。
当你设置一个锚的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);
}
该问题询问一个url(如stackoverflow)的验证方法,而没有协议或主机名中的任何点。因此,这不是验证url sintax的问题,而是通过实际调用它来检查它是否是一个有效的url。
我尝试了几种方法来知道url是否真实存在,并且可以从浏览器中调用,但没有找到任何方法来测试javascript调用的响应头:
添加一个锚元素可以触发click()方法。 使用'GET'对具有挑战性的url进行ajax调用是可以的,但由于CORS政策,它有各种限制,并且不是使用ajax的情况,因为url可能在我的服务器域之外。 使用fetch API有一个类似ajax的解决方案。 另一个问题是,我有我的服务器在https协议下,并在调用非安全url时抛出异常。
所以,我能想到的最好的解决方案是得到一些工具来执行CURL使用javascript尝试像CURL -I <url>。不幸的是,我没有找到任何,在外观上,这是不可能的。我将感谢任何关于这一点的评论。
但是,最后,我有一个运行PHP的服务器,因为我几乎所有的请求都使用Ajax,所以我在服务器端编写了一个函数来执行curl请求并返回到浏览器。
关于“stackoverflow”问题上的单个单词url,它将引导我到https://daniserver.com.ar/stackoverflow,其中daniserver.com.ar是我自己的域名。
我认为使用本地URL API比@pavlo建议的复杂正则表达式模式更好。虽然它有一些缺点,但我们可以通过一些额外的代码来修复。对于以下有效url,此方法失败。
//cdn.google.com/script.js
我们可以预先添加缺失的协议来避免这种情况。它也无法检测以下无效的url。
http://w
http://..
那么为什么要检查整个url呢?我们可以检查定义域。我借用正则表达式从这里验证域。
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;
}
}
主机名属性是javascript:void(0)的空字符串,所以它也适用于此,你也可以添加IP地址验证器。我最喜欢坚持使用本地API,并希望它在不久的将来开始支持一切。
这似乎是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域。
这里只是一个非常简单的检查,以确保有一个有效的协议,并且域扩展名必须是两个或更多字符。
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
);
};