尝试使用 JavaScript 验证 URL

IT技术 javascript jquery validation url
2021-01-30 06:17:55

我想验证一个 URL 并显示消息。下面是我的代码:

$("#pageUrl").keydown(function(){
        $(".status").show();
        var url = $("#pageUrl").val();

        if(isValidURL(url)){

        $.ajax({
            type: "POST",
            url: "demo.php",
            data: "pageUrl="+ url,
            success: function(msg){
                if(msg == 1 ){
                    $(".status").html('<img src="images/success.gif"/><span><strong>SiteID:</strong>12345678901234456</span>');
                }else{
                    $(".status").html('<img src="images/failure.gif"/>');
                }
            }
            });

            }else{

                    $(".status").html('<img src="images/failure.gif"/>');
            }

    });


function isValidURL(url){
    var RegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;

    if(RegExp.test(url)){
        return true;
    }else{
        return false;
    }
} 

我的问题是,即使输入正确的 URL 直到匹配正则表达式,它也会显示错误消息,并且即使 URL 类似于"http://wwww".

我很欣赏你的建议。

6个回答

有人提到了 Jquery Validation 插件,如果你只是想验证 url 似乎有点矫枉过正,这是插件中的正则表达式行:

return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);

这是他们从这里得到的:http : //projects.scottsplayground.com/iri/

@nhahtdh 指出这已更新为:

        // Copyright (c) 2010-2013 Diego Perini, MIT licensed
        // https://gist.github.com/dperini/729294
        // see also https://mathiasbynens.be/demo/url-regex
        // modified to allow protocol-relative URLs
        return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );

来源:https : //github.com/jzaefferer/jquery-validation/blob/c1db10a34c0847c28a5bd30e3ee1117e137ca834/src/core.js#L1349

上面的正则表达式已经被jQuery Validation 源码中Diego Perini 的正则表达式所取代:github.com/jzaefferer/jquery-validation/blob/master/src/...
2021-03-30 06:17:55
jQuery 验证的方法允许在域名中使用下划线 ("_")。据我所知,它不允许出现在域名中。只允许使用连字符 ("-")。例如,PHPfilter_var($url, FILTER_VALIDATE_URL)似乎不允许在域名中使用下划线。
2021-03-31 06:17:55
\u00A0-\uD7FF 范围过于宽泛。像 ” (\u201D) 这样的引号字符在该范围内。例如,如果首先在空格上拆分,引用的句子的结尾可能是“this”。如果这在技术上不是误报,那么如果使用此正则表达式来识别 url,则通常会在实践中出现。
2021-04-03 06:17:55
2021-04-03 06:17:55
@Kousha:www.google.com 不是有效的 URL,因此它应该无法通过测试。
2021-04-04 06:17:55

使用正则表达式解析 URL 是不切实际的。RFC1738 规则的完整实现将导致非常长的正则表达式(假设它甚至可能)。当然,您当前的表达式未能通过许多有效的 URL,并通过无效的 URL。

反而:

一个。使用真正遵循真实规则的正确 URL 解析器。(我不知道 JavaScript 中的一个;这可能有点矫枉过正。不过,您可以在服务器端进行)。或者,

只需修剪掉任何前导或尾随空格,然后检查它前面是否有您喜欢的方案之一(通常是“http://”或“https://”),然后将其保留在那里。或者,

C。尝试使用 URL 并查看末尾是什么,例如通过从服务器端发送 HTTP HEAD 请求。如果您收到 404 或连接错误,则可能是错误的。

即使 url 类似于“ http://wwww ”,它也会返回 true

嗯,这确实是一个完全有效的 URL。

如果您想检查诸如“wwww”之类的主机名是否确实存在,您别无选择,只能在 DNS 中查找。同样,这将是服务器端代码。

这是务实的吗?是的。它是否回答了问题或为要实现的实现提供了足够的信息?不。
2021-03-28 06:17:55
对于与 IRI ( RFC 3987 ) 非常接近的正则表达式,请参阅“ W3C 兼容 URL 的正则表达式? ”。请注意,这将匹配任何IRI,而不仅仅是 URL(RFC 1738)或 URI(RFC 3986)。
2021-04-10 06:17:55
function validateURL(textval) {
    var urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
    return urlregex.test(textval);
}

对于像这样的 URL,这可以返回 true:

http://stackoverflow.com/questions/1303872/url-validation-using-javascript

或者:

http://regexlib.com/DisplayPatterns.aspx?cattabindex=1&categoryId=2
这完全取决于您对“有效 URL”的理解。您给出的所有示例在粘贴到浏览器地址栏时都将起作用(被认为有效),并且当用作<a href="">.
2021-03-15 06:17:55
为什么是RegExp构造函数?文字在这里很好。为什么将对象分配给变量?function validateURL(textval) { return /^(http...$/.test(textval) }更短更清晰。
2021-03-17 06:17:55
asdf.asdf 用这个返回 true。为什么?
2021-03-27 06:17:55
[...&...] 不会做你所期望的。字符类不允许字符串。
2021-03-31 06:17:55
这个 URL 不通过验证,即使它是合法的:uk.reuters.com/article/2013/02/25/...(从末尾删除 20130225 并且它是有效的)
2021-04-11 06:17:55

我还编写了一个基于 rfc1738 和 rfc3986 的 URL 验证函数来检查 http 和 https url。我尽量保持这个module化,所以它可以更好地维护和适应自己的要求。

一行中的 RegExp 显示在本文末尾。

RegExp 接受带有一些国际域或 IPv4 号码的 HTTP 和 HTTPS URL。尚不支持 IPv6。

window.isValidURL = (function() {// wrapped in self calling function to prevent global pollution

     //URL pattern based on rfc1738 and rfc3986
    var rg_pctEncoded = "%[0-9a-fA-F]{2}";
    var rg_protocol = "(http|https):\\/\\/";

    var rg_userinfo = "([a-zA-Z0-9$\\-_.+!*'(),;:&=]|" + rg_pctEncoded + ")+" + "@";

    var rg_decOctet = "(25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9]|[1-9][0-9]|[0-9])"; // 0-255
    var rg_ipv4address = "(" + rg_decOctet + "(\\." + rg_decOctet + "){3}" + ")";
    var rg_hostname = "([a-zA-Z0-9\\-\\u00C0-\\u017F]+\\.)+([a-zA-Z]{2,})";
    var rg_port = "[0-9]+";

    var rg_hostport = "(" + rg_ipv4address + "|localhost|" + rg_hostname + ")(:" + rg_port + ")?";

    // chars sets
    // safe           = "$" | "-" | "_" | "." | "+"
    // extra          = "!" | "*" | "'" | "(" | ")" | ","
    // hsegment       = *[ alpha | digit | safe | extra | ";" | ":" | "@" | "&" | "=" | escape ]
    var rg_pchar = "a-zA-Z0-9$\\-_.+!*'(),;:@&=";
    var rg_segment = "([" + rg_pchar + "]|" + rg_pctEncoded + ")*";

    var rg_path = rg_segment + "(\\/" + rg_segment + ")*";
    var rg_query = "\\?" + "([" + rg_pchar + "/?]|" + rg_pctEncoded + ")*";
    var rg_fragment = "\\#" + "([" + rg_pchar + "/?]|" + rg_pctEncoded + ")*";

    var rgHttpUrl = new RegExp( 
        "^"
        + rg_protocol
        + "(" + rg_userinfo + ")?"
        + rg_hostport
        + "(\\/"
        + "(" + rg_path + ")?"
        + "(" + rg_query + ")?"
        + "(" + rg_fragment + ")?"
        + ")?"
        + "$"
    );

    // export public function
    return function (url) {
        if (rgHttpUrl.test(url)) {
            return true;
        } else {
            return false;
        }
    };
})();

正则表达式在一行中:

var rg = /^(http|https):\/\/(([a-zA-Z0-9$\-_.+!*'(),;:&=]|%[0-9a-fA-F]{2})+@)?(((25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9]|[1-9][0-9]|[0-9])(\.(25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9]|[1-9][0-9]|[0-9])){3})|localhost|([a-zA-Z0-9\-\u00C0-\u017F]+\.)+([a-zA-Z]{2,}))(:[0-9]+)?(\/(([a-zA-Z0-9$\-_.+!*'(),;:@&=]|%[0-9a-fA-F]{2})*(\/([a-zA-Z0-9$\-_.+!*'(),;:@&=]|%[0-9a-fA-F]{2})*)*)?(\?([a-zA-Z0-9$\-_.+!*'(),;:@&=\/?]|%[0-9a-fA-F]{2})*)?(\#([a-zA-Z0-9$\-_.+!*'(),;:@&=\/?]|%[0-9a-fA-F]{2})*)?)?$/;
这很棒!你把它分解成不同的部分非常有帮助 - 我不想盲目地相信一个庞大的正则表达式。
2021-04-09 06:17:55

在类似的情况下,我逃脱了这个:

someUtils.validateURL = function(url) {
    var parser = document.createElement('a');
    try {
        parser.href = url;
        return !!parser.hostname;
    } catch (e) {
        return false;
    }
};

即如果浏览器可以为您做,为什么要发明轮子?但是,当然,这只适用于浏览器。

解析后的 URL 有各个部分,浏览器将如何解释它:

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

使用这些,您可以根据要求改进验证功能。唯一的缺点是它会接受相对 URL 并使用当前页面服务器的主机和端口。但是您可以利用它来发挥自己的优势,通过从部分重新组装 URL 并始终将其完整地传递给您的 AJAX 服务。

什么validateURL也不会接受无效的网址,例如http:\:8883将返回false,但是:1234是有效的,被解释为http://pagehost.example.com/:1234即作为相对路径。

更新

这种方法不再适用于 Chrome 和其他 WebKit 浏览器。即使 URL 无效,主机名也会填充一些值,例如取自base. 它仍然有助于解析 URL 的一部分,但不允许对其进行验证。

可能更好的 no-own-parser 方法是使用var parsedURL = new URL(url)和捕获异常。参见例如URL API受所有主要浏览器和 NodeJS 支持,但仍处于实验阶段。

@Subin 在现代浏览器中,此答案中的方法不再有效。感谢您对它的关注。实际上,无论您传递什么字符串,都会填充主机名。
2021-03-17 06:17:55
这将返回 TRUE <script>alert();</script>
2021-03-28 06:17:55