當前位置: 華文問答 > 數位

Chrome 是怎麽判斷位址列輸入的東西是不是網址?

2022-10-18數位

Chrome 的位址列代號是 Omnibox,omni 是萬能、全能的詞根,Omnibox 就是全能盒子的意思。在 2008 年 Chrome 釋出的時候,其它瀏覽器都是在一個長的位址列右側有個短的搜尋框,Omnibox 把搜尋和網址輸入合二為一是當時一個大的創新。

Omnibox 是個很復雜的東西,遠比我們使用者想的要復雜,Chrome 就內建一個給他們的開發者偵錯用的頁面,chrome://omnibox:

最核心的功能就是要判斷你輸入的東西是什麽,是個 query 還是個 url,也就是偵錯頁面裏展示出的那個 type = 的值。比如當你輸入 http://www. baidu.com :

Ominibox 判斷出了這個字串是個 url,所以排在第一位的結果,也就是我們立刻回車執行的那個操作,就是 url-what-you-typed,也就是以網址形式開啟你輸入的內容,當然,我們的輸入其實是缺了 https:// 協定頭的,所以實際上它會給補上,也就是倒數第二列展示的那個。

而第二位的結果型別叫 search-other-engine,是因為它判斷出了 http://www.baidu.com 剛好是瀏覽器內建的谷歌以外的一個搜尋引擎,所以它會提示你,按下 TAB 鍵,就可以輸入關鍵詞,從而開啟百度搜尋。

第三位叫 search-what-you-typed,就是用預設的搜尋引擎搜尋輸入的字串,拼接好的谷歌網址也展示了出來。

前三個結果在 Omnibox 裏展示出來是這樣的:

實際上判斷是不是 url 是個非常復雜的邏輯,更何況這裏的輸入不能期望它是個完整的 url,比如沒有協定頭的話,JS API 裏 new URL('www.baidu.com') 是可以直接報錯說它不是個 url,但這裏不行。而且這裏還得考慮自己的業務內容,比如不允許的協定型別,xxx:www.baidu.com:

它沒有辨識成 url 型別,也不是 query 型別,而是 unknown,unknown 型別類似 query,排第一的結果也是預設搜尋,但是它和 query 不一樣的是,也可以作為網址開啟,箭頭向下移動到最底部再回車就可以。比如我在之前回答中提到的谷歌公司內部短網址網域名稱 go 的網址,就會被判斷成 unknown:

而 localhost 就被特殊處理成了 url 型別:

還有這裏還得考慮本地路徑格式,比如斜杠 / 表示根目錄和波浪線 ~ 表示 Home 目錄。

還有個有趣的 javascript: 協定,這是從網景時代 Brendan Eich 手裏傳下來的偵錯功能,BE 不在 Mozilla 以後,Firefox 已經完全禁掉了它。在 Omnibox 裏,javascript:1+1 預設會是搜尋,因為被判定成了 unknown:

而 javascript:alert(1+1) 就會被辨識成 url,會彈出 2。這是因為很多年前,有人說搜素 JavaScript 犀牛書的名字 JavaScript: The Definitive Guide,結果沒有開啟谷歌,而是給當成程式碼執行了:

所以他們加了個簡單的正則:

只有 javascript: 協定後的文本包含一些括弧、點、分號等才認為是程式碼,通常來說,也夠了。

我這裏只是說一些簡單的有趣的 case,其實很多你想都想不到的場景有很多,比如輸入 ip,而且還有 ipv4 和 ipv6 的情況,等等。辨識這個字串是不是 url 涉及到的 C++ 程式碼怎麽都有幾千行,這不是一個正則能實作的。

現在據說流行一個面試題:

我這裏說的就是這道題的答案的第一步的梗概。