【问题标题】:URL Validator: If http:// not typed pass it dynamicallyURL 验证器:如果 http:// 未输入,则动态传递它
【发布时间】:2012-01-09 22:48:58
【问题描述】:

我正在尝试为小型书签应用程序制作 URL 验证器。

我已经完成验证器接受,以便它接受应该有效的内容:

http://example.com
http://www.examples.com
http://www.example.com
ftp://www.example.com
ftp://cdn.example.com/
etc.

现在,在现实生活中,我们通常不会为网站输入 http://,所以我希望,当用户输入任何没有 http:// 、 https:// 或 ftp:// 的内容时默认情况下通过 http:// 。请注意,我不想将其传递给输入,而是传递给后端。

所以对于我的例子,我有这个:

$("#in").on('keyup', function () {    
     var url = $('#in').val();

     var match = /^(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})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/


     if (match.test(url)) {
         console.log("URL OK")

     } else {
         console.log("URL invalid")

     }

});

如果 http:// 未输入,则将其传递到 console.log 以显示为有效 url。

我不确定这是否是一个好的做法,因为它最终可能会出现许多错误,但这是我能想到的唯一方法,我最终会得到一个 http:// 网站。我不能强迫用户在每个书签上都输入 http://。

另外请注意,我不想使用任何类型的插件。

请告诉我你对此的想法。

谢谢

【问题讨论】:

    标签: javascript jquery regex uri validation


    【解决方案1】:

    假设你的匹配是有效的......

    $("#in").on('keyup', function () {    
         var url = $('#in').val();
    
         var match = /^(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})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/;
    
        var noprotocolmatch = /^(((([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})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/;
    
         if (match.test(url)) {
             console.log("URL OK with protocol");
    
         } else if (noprotocolmatch.test(url)) {
             console.log("URL OK without protocol");
             url = 'http://'+url;
    
         } else {
             console.log("URL invalid")
    
         }
    
    });
    

    实际上,如果 URL 失败,我们至少会尝试将其与第二部分进行匹配,如果它匹配但错过了我们添加它的协议,如果一切都失败,则它是无效的。

    或者像这样,在第一个匹配中使用可选协议,并在第二步中检查协议是否存在:

    $("#in").on('keyup', function () {    
         var url = $('#in').val();
    
         var match = /^((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})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/;
         var protomatch = /^(https?|ftp):\/\/(.*)/;
    
         if (match.test(url)) {
             console.log("URL OK");
    
             if(!protomatch.test(url))
                url = 'http://'+url;
    
         } else {
             console.log("URL invalid")
    
         }
    
    });
    

    【讨论】:

    • 谢谢。我一直在寻找什么。你认为这是一个好习惯吗?我在想它最终会出现很多错误?
    • 如果以干净的方式实现,这不太容易出现错误,但您可能想对 url 验证正则表达式进行一些研究,这些东西有许多不同的变体......另一方面,您可能希望在您的服务器上执行此操作以确保您无法确定没有通过此发送的恶意代码,因为这是客户端控制的代码。无论如何,您都需要检查服务器上可能存在的安全问题,所以为什么不首先在那里过滤它。
    • 书签基于本地存储,因此我的服务器没有任何内容。我对 url 验证进行了研究,这就是为什么我最终使用了这么长的 regExp。问题是,如果有人故意尝试查找或添加错误的 url,他将实现它。除此之外,我相信用户最终会得到真正的网址。
    【解决方案2】:

    首先:绑定表单提交而不是keyup

    在每次击键时验证 URL 效率极低,因为您只需要在发送到服务器之前检查 URL - 即在表单提交时。所以改用这个事件处理程序:

    $('FORM').on('submit', function() {
     if (!url_is_valid()) {
       return false;  // Cancel form submission when URL isn't valid.
                      // You'll need to display an error message as well.
     }
    });
    

    每次提交页面时,您的 URL 解析/验证只会运行一次,而不是每秒运行几次(取决于输入速度)。

    第二:

    另外请注意,我不想使用任何类型的插件。

    为什么不呢? JavaScript 中的 URI 解析是 solved problem。不要重新发明轮子?

    【讨论】:

    • 关键是为了测试目的,主要是为了stackoverflow。因为我和用户可以更快地看到结果。不,我不想使用任何插件,也不会使用任何类型的插件。 bardiir 回答中的 1 行额外代码为我节省了 1263 行代码可怕的插件。
    • 对你有用的才是最重要的。我觉得有趣的是你使用 jQuery,它的时钟频率为 9000+ LOC——即使你极不可能使用 jQuery 的 5% 的特性——所以在我看来,这艘船已经航行了。
    猜你喜欢
    • 2015-10-17
    • 2013-08-23
    • 2018-10-12
    • 2011-09-26
    • 1970-01-01
    • 2017-08-12
    • 2020-02-03
    • 2016-07-29
    • 2016-03-03
    相关资源
    最近更新 更多