Node.js 透過全域的 URL 類別解析絕對的 HTTP 與 HTTPS 網址,該類別實作了 WHATWG URL Standard——也就是每個現代瀏覽器中 URL 建構函式所遵循的同一份規格。像 new URL("https://example.com/docs/page?id=42#top") 這樣傳入字串,會回傳一個物件,包含經過標準化的 protocol、host、hostname、port、pathname、search 與 hash 欄位,並附帶一個對應的 URLSearchParams 檢視來呈現查詢字串。由於 Node.js 10 以上的版本已將 WHATWG URL 暴露為全域物件,現代 API 不需要 require('url') 步驟,而在終端機得到的輸出會與瀏覽器中 document.createElement('a') 的結果一致。正是這種對等性,讓像 URL Parser 這樣的瀏覽器端檢查工具,成為在撰寫腳本之前快速原型設計與審核解析結果的利器。這個工具以無 base URL 的方式執行瀏覽器的 URL 建構函式,統一 scheme 與主機大小寫、移除預設埠號,並在不解碼的情況下序列化經百分比編碼的路徑位元組,因此你看到的每個欄位,都與 WHATWG 解析器在 Node.js 腳本中回傳的內容完全一致。

為什麼 Node.js 的 URL 類別與瀏覽器一致
Node.js 開發者可以預期,解析後的 URL 物件行為會與在 Chrome、Firefox 或 Safari 中建立的物件相同,因為兩種環境都以 WHATWG URL Standard 為目標,而非各自獨立的舊版實作。因此 host、hostname 與 port 欄位無論程式碼在何處執行,皆遵循同一個定義,經百分比編碼的位元組也會透過同一個解析器進行標準化。這份標準以 WHATWG URL 規格形式發佈,並記錄在 MDN URL 參考頁面上,對於想查詢邊角案例(例如反斜線處理、IDN 序列化或預設埠號移除)的 Node.js 開發者而言,這也是最權威的參考來源。當你把網址貼進以同一個建構函式打造的瀏覽器檢查工具時,所得到的結果會反映你的 Node.js 程式碼會輸出的內容,因此你可以反覆調整輸入,而不必每次都重新執行腳本並等待 console.log 輸出。
解析器所呈現的 URL 各個組成部分
這個工具會揭露一般 Node.js 或瀏覽器腳本會從解析後的 URL 物件讀取的每個元件,再加上少數對於交接與稽核很有用的衍生欄位。完整的清單(取自 WHATWG URL 物件加上 URL Parser 實作)看起來如下:
| 欄位 | 內容說明 |
|---|---|
| href | 經 WHATWG 標準化後完整序列化的 URL |
| origin | Scheme、hostname,以及有效的非預設埠號 |
| protocol | 一律以冒號結尾,例如 https: |
| host | Hostname 加上埠號(當埠號為非預設值時) |
| hostname | ASCII 主機名稱,國際化名稱以 xn-- 標籤顯示 |
| port | 當埠號為該 scheme 的預設值時為空,否則為明確的數字 |
| pathname | 序列化後的路徑,保留百分比編碼 |
| search | 包含前置 ? 的查詢字串,可能為空 |
| hash | 包含前置 # 的片段,可能為空 |
| filename | 最後一個斜線之後的路徑片段;當路徑以 / 結尾時為空 |
| query parameters | 來自 URLSearchParams 的有序陣列,保留重複的名稱 |
最常讓開發者感到意外的唯一一條規則是預設埠號的移除:在 HTTPS URL 上明確加上 :443 會產生空白的 port 欄位,且 host 中也不會帶有該後綴,因為 WHATWG 解析器將其視為該 scheme 的預設值。而像 :8080 這樣的非預設埠號則會保留在 host 中,也會單獨出現在 port,因此這兩個欄位在這種情況下並不重複。以方括號包裹的 IPv6 主機會保留其方括號序列化形式,而當存在非預設埠號時,host 會再附加該埠號。
三步驟解析一個 URL
- 將一個絕對的 HTTP 或 HTTPS 網址貼入輸入框。字元數會在你輸入時更新,而輸入上限恰好為 8,192 個 UTF-16 程式碼單元——超過的字元會被拒絕,而非截斷。
- 選擇 Parse URL。這個工具會以無 base URL 的方式執行瀏覽器的 URL 建構函式,驗證 scheme 為 http 或 https,並在產生結果前拒絕任何非空的使用者名稱或密碼。接著輸出面板會顯示經標準化的 href、origin、protocol、host、hostname、port、pathname、search、hash、filename,以及由 URLSearchParams 解碼的有序查詢參數。
- 檢查查詢字串與雜湊片段中是否含有任何機密資料,若可安全分享,再複製完整的解析後 JSON。編輯輸入會清除先前的結果、錯誤、查詢清單、摘要、輸出與剪貼簿狀態,因此一個失敗的網址絕不會讓先前的成功結果殘留可見。
解析器在建構結果前會拒絕的項目
這個工具刻意採取嚴格的規範,絕不會把性質不同的輸入當作共享同一個模型來呈現。以下輸入會在邊界處被拒絕,並產生錯誤而非解析後的物件:
- 空白的輸入
- 長度超過 8,192 個 UTF-16 程式碼單元的輸入
- ASCII 控制字元,包括某些編輯器會悄悄移除的換行與定位字元
- 網址前後的空白字元
- 原始的反斜線,某些舊版程式庫會將其視為路徑分隔符號
- 任何不是以不區分大小寫的 http:// 或 https:// 字首開頭的內容
- http 與 https 以外的 scheme,即使瀏覽器的 URL API 能夠解析——這包括 javascript:、data:、file:、ftp:、blob: 與 mailto:
- 相對路徑(例如 /docs/page)、scheme 相對參照(例如 //example.com/path)以及裸網域(例如 example.com),因為建構函式在沒有 base URL 的情況下被呼叫,這些輸入否則會以目前頁面為基準進行解析
- 任何含有非空使用者名稱或密碼的 URL——舉例而言,https://user:[email protected] 會回傳憑證錯誤且不產生任何解析欄位,因為這個工具絕不會顯示或部分遮罩 userinfo
- 查詢字串超過 200 個項目、格式化後的 JSON 輸出超過 50,000 個程式碼單元,或任何會使結果超過這些精確上限的輸入
這些限制代表單一失敗的 URL 不會留下殘留狀態。編輯輸入會移除舊的結果、錯誤、查詢清單、摘要、輸出與剪貼簿狀態,新的一次執行會從清空後的狀態開始。剪貼簿寫入受到世代保護,因此在輸入已變更後,正在進行中的複製承諾無法發佈誤導性的「Copied」狀態。
URL Parser 何時能幫你省下 Node.js 的往返
許多通常需要 Node.js REPL 或臨時腳本才能完成的除錯工作,變成只要貼上並點擊一次:
- 確認預設埠號的標準化。貼上 https://api.example.com:443/v1,確認 port 欄位為空,且 host 中已不再包含 :443。
- 檢查 IDN 主機名稱。貼上一個 Unicode 國際化網域,並讀取 hostname 欄位來查看瀏覽器的 xn-- 序列化形式,這就是你的 Node.js 程式碼會用來比對的形式。
- 稽核重複的查詢參數。像 ?tag=a&tag=b 這樣的網址會產生一個有序陣列,保留兩個項目。解析器不會將重複的項目合併為物件,因此像 tag 這種帶有兩個值的鍵,會以伺服器實際接收到的樣貌呈現。
- 區分路徑、查詢與片段文字。pathname、search 與 hash 欄位會各自獨立顯示,並保留前導的 ? 與 #,這在手工重建一個 URL 時非常實用。
- 找出百分比編碼的差異。pathname 與 filename 會保留像 %20 與 %2E 這樣的百分比編碼,而查詢的鍵與值則由 URLSearchParams 解碼,包含加號轉空格的轉換。用肉眼確認這種區分,比閱讀規格文件更為快速。
有幾項工作是這個工具不適合處理的。它不會前往該網址、擷取其內容、跟隨重新導向、掃描惡意程式、測試 DNS、驗證 TLS、解碼任意的二進位百分比序列,也不會移除追蹤參數。請把它視為對輸入字串的檢查工具,而非對目的地的驗證。針對相鄰的工作,將查詢字串解析為 JSON涵蓋了更廣泛的查詢處理工作流程,而 MDN URL 參考文件則記錄了這個工具所讀取的每個欄位。
由於 Node.js 的 URL 類別與瀏覽器的 URL 建構函式皆實作了 WHATWG URL Standard,URL Parser 所顯示的解析欄位,與你在腳本中呼叫 new URL(...) 所得到的欄位完全相同。這讓這個工具成為將解析器寫入程式碼庫之前一個實用的預先檢查手段,也是一種無需開啟終端機就能向隊友展示 URL 解析的快速方式。