大侠稍等!URL 中为何出现奇怪的字符
為什么中文名稱的圖片打開后網址是一串亂碼?為什么好好的短網址復制粘貼就變長了一大長串?罪魁禍首居然是……
杭州終于出梅了!二狗子看到氣象臺發布的消息,開心的不得了。杭州的雨從五月底一直下,每天除了雨還是雨,天空都是灰蒙蒙的,都快把人搞抑郁了。出梅了,天晴了,二狗子的心也隨著藍天上的白云飄蕩出去了。
同事小峰峰告訴二狗子,公司后邊的皇后公園,向日葵開的正好,一大片一大片的綿延出去,陽光下金燦燦的,可好看了。“要不要一起去看看?你拍點照片給婷婷唄~”
二狗子一想起女神婷婷很喜歡向日葵,拍點美麗的照片,能看到婷婷甜甜的笑,就迫不及待地拉著小峰峰往公園跑。
二狗子拍了好多照片,精挑細選了好幾張,上傳到自己的圖片網站了。他用瀏覽器打開圖片看了看,沒有問題,非常完美,就復制了圖片地址發給婷婷。
二狗子有點尷尬,明明在瀏覽器中是正常顯示的 URL 地址,怎么復制出來就變成一堆奇怪的字符了呢?
二狗子百思不得其解,得,還是問一下自己的存儲服務商——無所不能的又拍云吧。
客服喬巴接待了二狗子,并告訴了二狗子這個問題的由來。
URL - 網絡資源定位符
通過互聯網來訪問網絡中資源的時候,最常見就是通過瀏覽器輸入資源的 URL 地址來進行訪問。
URL(Uniform Resource Locator),是互聯網中的一個核心概念,官方名稱叫做統一資源定位符。簡單的來說,URL 就是一個由網站開發者給資源在互聯網上分配的地址。一般來說,每個有效的 URL 都指向單獨的一個資源,這個資源可以是HTML 頁面、CSS 文檔,又或者是一幅圖像等。
一個 URL 由不同的部分組成,其中一些是必須的,而另一些是可選的。下面我們來看下 URL 的具體組成部分:
上圖就是完整的 URL 結構展示。很多時候其中的一些部分是用不到的,例如 user information。作為參考,我們可以來看一下又拍云存儲的 URL 地址。
https://www.upyun.com/products/file-storage
-
https:// ,請求協議(scheme),指定了瀏覽器需要使用何種協議來與目標服務器進行通訊。常見的協議有 HTTP 和 HTTPS。
-
www.upyun.com,域名(host),表明請求的資源所在的服務器地址。
-
/products/file-storage ,資源路徑地址(path),服務器通過路徑來確認訪問資源在服務器上的哪個位置。
一般常見的 URL 地址由這三個部分組成,其余的部分根據開發的需要,可以進行自定義。
了解 URL 的概念后,就知道二狗子的圖片鏈接 http://fileupload-upyun.test.upcdn.net/images/向日葵1.jpg 的由來了。通過這個地址,婷婷可以訪問到二狗子服務器上拍攝的向日葵圖片。但是,為什么二狗子復制了瀏覽器地址欄中的地址,發送給婷婷的時候,URL 卻變成了 http://fileupload-upyun.test.upcdn.net/images/%E5%90%91%E6%97%A5%E8%91%B51.jpg 了呢?
奇怪的字符 - URL 編碼
我們可以看到,二狗子發給婷婷的鏈接,改變了的部分屬于 URL 的 path 部分,而且,英文部分其實沒有改動,只有中文的部分被轉成 %XX 的這種編碼格式了。
雖然,這不會影響圖片的打開,地址依舊是有效的。但是為什么瀏覽器要把中文轉換成這種奇怪的形式呢?
我們先來看一個例子。如果訪問下面這個 URL 鏈接:
https://www.baidu.com/s?wd=?#!
這是使用百度進行搜索的一個鏈接,/s 后面跟著的 ? 代表請求參數(query),也就是我們想向請求的服務器提交一些參數。wd 為百度規定的查詢參數名,wd 后邊跟著的就是需要搜索的內容。
我們想搜索 ?#! 這個內容,可是當你復制這個鏈接放在瀏覽器中打開時,會發現一個問題,百度僅僅是搜索了 ? 這個內容,#! 不見了。
為什么呢?如果你仔細看上面那張 URL 的構成圖,會發現 URL 結構中還有一個錨點(fragment)的部分,分隔符號就是 #。
所以這里就會出現一個問題,我們的業務需求是將 # 當做一個普通文本來進行搜索,但是 # 在 URL 中有特定的意思,所以瀏覽器就遇到了一個解釋歧義的問題。
這就引申出一個問題,URL 在數據傳遞中,如果存在用作分隔符等特殊作用的保留字符怎么辦?
在實際的業務場景中,會經常碰到一些在 URL 中有歧義性的數據,為了避免解釋錯誤,開發者想出了一個解決方法,就是對這些數據進行一定的處理,從而解決歧義的問題。處理的方法有很多種,最常用的處理方式,就是對歧義性的數據進行 URL 百分號編碼。
哪些是會引起歧義的數據呢?
根據 RFC 3986(https://tools.ietf.org/html/rfc3986#appendix-A)的規定,我們可以得到下面的結果。
-
不在 ASCII 碼范圍內的字符 (URL 使用 ASCII 碼進行編解碼)
-
ASCII 碼中不可顯示的字符
-
URL 中規定的保留字符
-
不安全字符(傳輸環節中可能會被不正確處理),如空格、引號、尖括號等
保留字符由組件分隔符(gen-delims)和子組件分隔符(sub-delims)組成,這些字符在 URL 中都有特殊的意義:
Reserved = gen-delims / sub-delims
-
gen-delims = “:” / “/” / “?” / “#” / “[” / “]” / “@”
-
sub-delims = “!” / “$” / “&” / “’” / “(” / “)” / “*” / “+” / “,” / “;” / “=”
URL 中可以直接使用的非保留字符則有:
Unreserved = ALPHA / DIGIT / “-” / “.” / “_” / “~”
-
ALPHA:%41 - %5A AND %61 - %7A (英文字母大寫 A-Z 以及英文字小寫 a-z)
-
DIGIT:%30 - %39 (數字 0-9)
-
-: %2D .: %2E _: %5F
-
~: %7E (某些服務實現將其作為保留字符,一般也需要進行編碼處理)
這下子我們就了解了,為什么 URL 中有時會出現奇怪的字符,很多時候瀏覽器會自動幫我們做編碼和解碼的操作。就像“向日葵”的 URL 一樣,中文部分因為并不在 ASCII 碼中,于是瀏覽器進行 URL 百分號編碼的形式來進行訪問。
(又拍云服務名的合法范圍就是在非保留字符中獲取,而不能指定為任意字符)
編碼的形式
最常見的編碼形式就是百分號編碼(pct-encoded),這也是瀏覽器默認的編碼形式。
pct-encoded = “%” HEXDIG HEXDIG
百分號編碼一個保留字符, 首先需要把該字符的 ASCII 的值表示為兩個 16 進制的值, 然后在其前面放置轉義字符(%)。對于非 ASCII 字符, 則需要轉換為 UTF-8 字節序, 然后每個字節按照上述方式表示。
(感興趣的同學可以參考百分號編碼 https://zh.wikipedia.org/zh-hans/%E7%99%BE%E5%88%86%E5%8F%B7%E7%BC%96%E7%A0%81 條目)
各個編程語言中也有相對應的方法可以進行百分號編碼,例如 JavaScript 中就提供了多種編碼方法,常用的有 encodeURI 和 encodeURIComponent 兩個方法。
喬巴說,在日常開發使用中,我們使用的開發庫對 URL 編碼的判斷標準可能并不相同,這是因為這些庫所面臨的網絡環境中,對于特殊字符的安全處理策略各有判斷,這也會導致 URL 中如果存在一些特殊字符,開發、訪問過程中可能就會出現一些奇怪的問題。在這里也建議大家使用非保留字符來設計自己程序中 URL 部分,避免一些不必要的 BUG 產生。
聽完喬巴的介紹,二狗子終于明白了為啥 URL 中出現這些奇怪的字符了。嘿嘿,這下可以和婷婷解釋 URL 為什么這么長咯。
總結
以上是生活随笔為你收集整理的大侠稍等!URL 中为何出现奇怪的字符的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何替公司省下数千万勒索费用
- 下一篇: 边缘计算、区块链、5G,哪个能走的更远