V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
pq
V2EX  ›  JavaScript

PAC 文件的 js 脚本中, dnsDomainIs()中的匹配到底是什么语法?

  •  
  •   pq · 2017-11-27 14:25:49 +08:00 · 4103 次点击
    这是一个创建于 2556 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如果写成 dnsDomainIs(host, "v2ex.com")的话,那么,当 host=="www.v2ex.com"或 host=="v2ex.com"时,是否都为 true ?我在 Chrome 上测试时,确实是如此,但是,网上大量的文档,包括一些很权威性的网站,Mozilla、Oracle、websense 之类的,都没有详细说明这一点,从列出的例子来看,应该是不包含 www 时才为真,有些例子则是当匹配串为".v2ex.com"时,www 为真,不带 www 则为假,真的有点混乱了。。。

    本站上有些人认为的这么牛 B 的 js,语法难道这么不严谨?还是我没找到真正的网站?

    11 条回复    2017-11-29 13:24:08 +08:00
    pq
        1
    pq  
    OP
       2017-11-27 14:33:20 +08:00
    我目前的 pac 中写法是这样的:
    shExpMatch(host, "(*.ggpht.com|ggpht.com)")

    这是照网上的例子写的,可以正常工作,但我觉得不够优雅,一个域名重复写了两遍,浪费存贮器,作为强迫症,于是我才上网找语法,结果发现另一个函数 dnsDomainIs 或许可以直接搞定,我的想法是,匹配串只写一个 domain_name,不管 host 有或没有二级域名甚至更多级域名,都返回真。
    yangg
        2
    yangg  
       2017-11-27 14:35:36 +08:00
    源码
    "function dnsDomainIs(host, domain) {\n"
    " return (host.length >= domain.length &&\n"
    " host.substring(host.length - domain.length) == domain);\n"
    "}\n"

    see https://github.com/ldx/libpac/blob/master/nsProxyAutoConfig.h
    pq
        3
    pq  
    OP
       2017-11-27 14:44:23 +08:00
    @yangg 这么说来,匹配串直接写成"v2ex.com"的话,完全可以匹配 www.v2ex.comv2ex.com 了?那各网站的那些例子为嘛要脱裤子放屁,还在后面加一个 || host == 'v2ex.com'呢? websense 上有关 pac 的例子就那样写的。
    pq
        4
    pq  
    OP
       2017-11-27 14:47:37 +08:00
    @yangg 你引的这个代码库不像是官方代码,后面好多\n,在 windows 下写的,没搞好就提交上去了。。。
    pq
        5
    pq  
    OP
       2017-11-27 15:01:40 +08:00
    @yangg 下面这个例子加上你贴的源码提醒了我,匹配串开头还是要加上'.':
    dnsDomainIs("www.notmycompany.com", "mycompany.com") returns true dnsDomainIs("www.myCompany.com", "mycompany.com") returns false

    否则会出问题。

    不过,我加上.后在 Chrome 里试了一下,居然仍能匹配不带 www 的 host,按照你的源码,这种情况下 host.length 是小于 domain.length 的,host=="v2ex.com"; domain==".v2ex.com";
    yangg
        6
    yangg  
       2017-11-27 15:51:59 +08:00   ❤️ 1
    autoxbc
        7
    autoxbc  
       2017-11-28 03:57:53 +08:00   ❤️ 1
    function dnsDomainIs(host, domain)
    {
       return new RegExp('\\b'+domain+'$').test(host);
    }

    >>> dnsDomainIs('v2ex.com','v2ex.com')
    true
    >>> dnsDomainIs('www.v2ex.com','v2ex.com')
    true
    >>> dnsDomainIs('notv2ex.com','v2ex.com')
    false
    >>> dnsDomainIs('v2ex.com.cn','v2ex.com')
    false
    pq
        8
    pq  
    OP
       2017-11-28 10:56:37 +08:00
    @autoxbc 这个太完美了!那么,可以直接在 pac 文件中重新定义 dnsDomainIs 这个函数么?
    autoxbc
        9
    autoxbc  
       2017-11-28 21:33:18 +08:00
    @pq #8 我测试可以的
    autoxbc
        10
    autoxbc  
       2017-11-29 03:12:15 +08:00   ❤️ 1
    仔细看了一下,#7 的代码没有对 "." 转义,匹配边界有问题
    >>> dnsDomainIs('v2exycom.cn','v2ex.com.cn')
    true

    应该改成这样
    function dnsDomainIs(host,domain)
    {
       return new RegExp( '\\b' + domain.replace(/\./g,'\\.') + '$' ).test(host);
    }

    考虑到正则的性能问题,又写了个非正则版,实测性能好 1~3 倍
    function dnsDomainIs(host,domain)
    {
       var idx = host.length - domain.length ;
       return (host == domain) || (idx > 0 && host.lastIndexOf('.' + domain) == idx - 1);
    }
    pq
        11
    pq  
    OP
       2017-11-29 13:24:08 +08:00
    @autoxbc 这个真的好,我也正是因为考虑到正则表达式的性能可能不太好,所以才从 shExpMatch 换成 dnsDomainIs 的,而原版的 dnsDomainIs,实现虽然简单高效,但没有考虑到不带二级域名的域名本体,你后边的这个实现,看来是比较完美的,可以考虑向 Chrome 提交修正代码。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1039 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 21:31 · PVG 05:31 · LAX 13:31 · JFK 16:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.