繁體中文

開發者工具 · URL 編碼器和解碼器

為什麼 + 在解碼查詢字串時會變成空格,而在解碼查詢字串時則不會

· 工作原理

url 編碼 JavaScript 開發人員工作流程

加號及其百分比編碼形式在不同的解碼器中保持不同
原始 ToolAcre 向量圖

+ 是否表示空格取決於您呼叫哪個解碼器。這篇文章解釋了decodeURIComponent、URLSearchParams和伺服器框架如何處理+,以及如何避免將真正的加號變成空格。

為什麼 + 在解碼查詢字串時會變成空格,而在解碼查詢字串時則不會

HTML 表單提交使用 application/x-www-form-urlencoded 格式,其中空格變成加號。接收 name=Alice+Smith 的伺服器在提取值之前將每個加號替換為空格。當實數加號屬於資料時,例如在計算 5+3 中,它在形式解碼步驟之後以 5 3 形式到達伺服器。這種無形的轉換是混亂的根源。

JavaScript 解碼會根據您使用的函數產生不同的結果。 URLSearchParams 將加號視為空格,以符合伺服器行為。但decodeURIComponent 保持 plus 不變,按字面意思對待它。函數之間的這種不對稱性就是相同輸入解碼不同的原因。期望兩個解碼器產生相同結果的開發人員發現他們沒有。

兩種看起來相似的編碼 — RFC 3986 百分比編碼與應用程式/x-www-form-urlencoded

兩種編碼標準看起來相似,但工作方式不同。 RFC 3986 定義百分比編碼:任何字元都變成 %HH。空間變成 %20。 application/x-www-form-urlencoded 標準增加了一個簡寫:空格可以加。兩者都適用於表單上下文,但 plus 是可選的並特定於該標準。它們是具有相似外觀的不同域。

呼叫decodeURIComponent 僅適用於RFC 3986 解碼。它將 %20 讀作空格,並將 plus 讀作文字加。 URLSearchParams 應用表單解碼規則:百分比轉義符變為字符,加號變為​​空格。這兩個函數在不同的領域解決相同的問題。混合它們會導致真正的加號消失,或者空間變成加號但無法轉換。

decodeURIComponent 單獨留下 + ; URLSearchParams 將其變成一個空格-兩種 JavaScript 行為的比較

伺服器行為各不相同,這使得問題更加複雜。 Rails 或 Django 自動套用格式規則:加號變成空格。但是使用 URL 解碼器提取並手動解碼原始查詢字串會使 plus 保持不變。相同的值經過不同的框架處理會產生不同的結果。伺服器程式碼通常會隱式處理此問題,隱藏問題,直到您編寫自訂解碼器。

範例:電話號碼欄位儲存 +1-555-0100,加號作為國家/地區代碼。 HTML 表單將其編碼為 %2B1-555-0100 因為 JavaScript 將 plus 編碼為 %2B。伺服器收到此訊息。如果應用形式解碼,%2B 變為正值,則該值是正確的。如果代理程式剝離編碼,則對結果呼叫decodeURIComponent會產生+1-555-0100。每層解碼一次。

伺服器做什麼-查詢字串和請求正文中的常見框架行為,以一般術語描述

JavaScript 可以使用encodeURIComponent 對值進行編碼。給定 a+b,它產生 a%2Bb。當該編碼字串到達伺服器或表單感知解碼器時,%2B 解碼為加號,並結果是正確的。如果您使用格式規則進行編碼,則空格將變為加號,而實數加號將變為 %2B。無論哪種方式,編碼都會產生%2Bb。解釋取決於應用哪種解碼規則。

測試往返:從 a+b 開始。使用encodeURIComponent 進行編碼以獲得%2Bb。使用decodeURIComponent解碼a%2Bb並恢復a+b。將 a+b 傳遞給 URLSearchParams:它將加號視為空格,產生 b。將 a%2Bb 傳遞給 URLSearchParams 以取得 a+b。根據您使用的解碼器,相同的輸入以兩種方式解碼會產生不同的輸出。

工作範例:透過兩個解碼器的「a+b」和「a%2Bb」-表格中的四個結果

常見錯誤如下。開發人員使用decodeURIComponent 進行解碼,並想知道為什麼帶有實數加號的傳入表單資料會中斷。他們應該使用 URLSearchParams。相反,有人在應該使用decodeURIComponent 時使用了URLSearchParams,每個文字加號都消失了。編碼兩次會產生 %252B,需要匹配的編碼器-解碼器對才能正確解碼。

另一個錯誤是手動將查詢字串建構為 ?q=value 而不進行編碼。值中的任何“&”或等於都會默默創建一個新參數。瀏覽器不會事後猜測連接;它將結果視為正確形成的。只有使用encodeURIComponent 進行有意編碼才能防止這種情況發生。 URL 編碼器和解碼器顯示了所有三個函數,揭示了每個函數產生的結果。

常見錯誤 - 解碼兩次,或在路徑段中將空格編碼為 +

表單編碼規則稱為 application/x-www-form-urlencoded 因為它描述了 HTTP 請求正文 Content-Type 標頭。沒有檔案上傳的 HTML 表單以此格式傳送正文。 URL 中的查詢字串也使用此約定,儘管從技術上講它們沒有官方編碼標準。 URL 規範將查詢視為不透明; plus 的含義不是強制的。但在 Web 應用程式中,加號通常意味著空格。

為了確保正確的行為,請謹慎編碼並使用匹配函數進行解碼。如果使用encodeURIComponent 進行編碼,請使用decodeURIComponent 進行解碼。如果讀取 HTML 表單資料或表單格式的請求正文,請使用 URLSearchParams。永遠不要根據外表來猜測。像 a+b 這樣的字串是有歧義的。解碼器不可互換。

這不包括什麼 - 多部分錶單資料和 JSON 請求主體

多部分錶單資料、JSON 請求主體和其他標準具有單獨的編碼規則。 JSON 不使用加號進行空格或百分比編碼;它使用 Unicode 轉義。多部分使用不同的邊界。本文僅涵蓋查詢字串和表單編碼主體,因為這就是加號歧義出現的地方。請務必檢查 Content-Type 標頭和定義它的 RFC。

當文字加號屬於查詢值時,請務必將其編碼為 %2B。 URL 編碼器和解碼器顯示如何在元件模式下將加號保護為 %2B,與成為 %20 的空格分開。將 a+b 和 a%2Bb 通過每種模式,然後檢查結果。這個比較說明了為什麼相同的輸入解碼不同。差別在於兩個不同標準的正確行為。

重點:始終將文字加號編碼為 %2B — URL 編碼器和解碼器如何將值顯示為百分比編碼查詢值

重點:查詢字串中的加號是空格的形式編碼簡寫,而不是文字加號,除非它來自將其保護為 %2B 的編碼。錯誤的解碼器會失去這種保護。 URLSearchParams 在現代 JavaScript 中是最安全的;它處理表單編碼並提供命名參數存取。對於原始字串,encodeURIComponent 會保護一切; debugURIComponent 解釋 %20 和百分比,但按字面意思處理加號。

測試一下:手動建立 ?x=a+b 並將其貼上到 URL 編碼器和解碼器中。檢查它並觀察 URLSearchParams 將其拆分為值為 a b 的參數 x。貼上 ?x=a%2Bb 並查看值 a+b。使用encodeURIComponent 建構URL 並進行比較。這種視覺確認澄清了規則:表單規則使用加號,百分比編碼使用 %20,混合它們是加號消失在空間中的原因。