前端JS如何獲取主域名(根域名)

pon發表於2017-09-05

背景

最近專案中需要獲取url的主域名,比如www.baidu.com那麼就需要獲取baidu.com,看似簡單,.號分隔,取到最後兩位就行,但是坑爹的是有xxx.com.cn這類域名,還有很多日本的域名,類似toei.aichi.jp等,這些都無法通過這種簡單的取最後兩位的方式來獲取,看來只能列舉了。

Public Suffix List

這問題肯定是早有人就遇到了,於是各路有識之士已經幫你完整得準備好了一個列表,裡面全部都是那些奇葩域名,一些jp域名也是讓我長見識了,不知道各位老司機在秋名山飆車的時候有沒有見過這些個域名:

秋田.jp
群馬.jp
香川.jp
高知.jp
鳥取.jp
鹿児島.jp
// jp geographic type names
// http://jprs.jp/doc/rule/saisoku-1.html
*.kawasaki.jp
*.kitakyushu.jp
*.kobe.jp
*.nagoya.jp
*.sapporo.jp
*.sendai.jp
*.yokohama.jp
!city.kawasaki.jp
!city.kitakyushu.jp
!city.kobe.jp
!city.nagoya.jp
!city.sapporo.jp
!city.sendai.jp
!city.yokohama.jp
// 4th level registration
aisai.aichi.jp

感興趣的朋友可以看看這個github專案:https://github.com/wrangr/psl

這裡有各種主域名的列表:https://publicsuffix.org/list/public_suffix_list.dat.

瀏覽器其實也有內建類似的東西,用來做域名判斷,cookie儲存之類的事宜。

pls的問題

問題看似好像解決了,已經有現成的指令碼去獲取,但是仔細一看這指令碼竟然有將近200K,而我自己的指令碼才10K,既然瀏覽器已經內建了pls,那瀏覽器有沒有暴露內建介面呢?很遺憾,搜尋了一下並沒有,而且瀏覽器那麼多,即使chrome暴露了,IE肯定沒有,等等,剛剛好像我們說到瀏覽器用來做域名判斷,cookie儲存,那我們能不能用這類方式間接地去呼叫內建pls呢?

最終解決方案

目前想到有兩種方式可以間接去調,document.doamindocument.cookie,測試一下就會發現,如果你嘗試把當前域名設定為com.cn或者把cookie設定到com.cn上面,瀏覽器並不會生效,document.domain在第二次設定的時候,firefox會拋錯,看來並不是很合適,而且可能多多少少會影響到業務,cookie設定方便,而且清除也方便,上程式碼:

function getMainHost() {
  let key  = `mh_${Math.random()}`;
  let keyR = new RegExp( `(^|;)\s*${key}=12345` );
  let expiredTime = new Date( 0 );
  let domain = document.domain;
  let domainList = domain.split( `.` );

  let urlItems   = [];
  // 主域名一定會有兩部分組成
  urlItems.unshift( domainList.pop() );
  // 慢慢從後往前測試
  while( domainList.length ) {
    urlItems.unshift( domainList.pop() );
    let mainHost = urlItems.join( `.` );
    let cookie   = `${key}=${12345};domain=.${mainHost}`;

    document.cookie = cookie;

    //如果cookie存在,則說明域名合法
    if ( keyR.test( document.cookie ) ) {
      document.cookie = `${cookie};expires=${expiredTime}`;
      return mainHost;
    }
  }
}

拉了差不多幾十個pls裡面的域名,跑了一下單元測試,沒有問題。


相關文章