大俠稍等!URL 中爲什麼出現奇怪的字符

爲何中文名稱的圖片打開後網址是一串亂碼?爲何好好的短網址複製粘貼就變長了一大長串?罪魁禍首竟然是……html

杭州終於出梅了!二狗子看到氣象臺發佈的消息,開心的不得了。杭州的雨從五月底一直下,天天除了雨仍是雨,天空都是灰濛濛的,都快把人搞抑鬱了。出梅了,天晴了,二狗子的心也隨着藍天上的白雲飄蕩出去了。編程

同事小峯峯告訴二狗子,公司後邊的皇后公園,向日葵開的正好,一大片一大片的綿延出去,陽光下金燦燦的,可好看了。「要不要一塊兒去看看?你拍點照片給婷婷唄~」瀏覽器

二狗子一想起女神婷婷很喜歡向日葵,拍點美麗的照片,能看到婷婷甜甜的笑,就火燒眉毛地拉着小峯峯往公園跑。安全

二狗子拍了好多照片,精挑細選了好幾張,上傳到本身的圖片網站了。他用瀏覽器打開圖片看了看,沒有問題,很是完美,就複製了圖片地址發給婷婷。服務器

二狗子有點尷尬,明明在瀏覽器中是正常顯示的 URL 地址,怎麼複製出來就變成一堆奇怪的字符了呢?網絡

二狗子百思不得其解,得,仍是問一下本身的存儲服務商——無所不能的又拍雲吧。app

客服喬巴接待了二狗子,並告訴了二狗子這個問題的由來。編程語言

URL - 網絡資源定位符

經過互聯網來訪問網絡中資源的時候,最多見就是經過瀏覽器輸入資源的 URL 地址來進行訪問。網站

URL(Uniform Resource Locator),是互聯網中的一個核心概念,官方名稱叫作統一資源定位符。簡單的來講,URL 就是一個由網站開發者給資源在互聯網上分配的地址。通常來講,每一個有效的 URL 都指向單獨的一個資源,這個資源能夠是HTML 頁面、CSS 文檔,又或者是一幅圖像等。編碼

一個 URL 由不一樣的部分組成,其中一些是必須的,而另外一些是可選的。下面咱們來看下 URL 的具體組成部分:

上圖就是完整的 URL 結構展現。不少時候其中的一些部分是用不到的,例如 user information。做爲參考,咱們能夠來看一下又拍雲存儲的 URL 地址。

https://www.upyun.com/product...

  • https:// ,請求協議(scheme),指定了瀏覽器須要使用何種協議來與目標服務器進行通信。常見的協議有 HTTP 和 HTTPS。
  • www.upyun.com,域名(host),代表請求的資源所在的服務器地址。
  • /products/file-storage ,資源路徑地址(path),服務器經過路徑來確認訪問資源在服務器上的哪一個位置。

通常常見的 URL 地址由這三個部分組成,其他的部分根據開發的須要,能夠進行自定義。

瞭解 URL 的概念後,就知道二狗子的圖片連接 http://fileupload-upyun.test.... 的由來了。經過這個地址,婷婷能夠訪問到二狗子服務器上拍攝的向日葵圖片。可是,爲何二狗子複製了瀏覽器地址欄中的地址,發送給婷婷的時候,URL 卻變成了 http://fileupload-upyun.test.... 了呢?

奇怪的字符 - 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/r...)的規定,咱們能夠獲得下面的結果。

  • 不在 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-h... 條目)
各個編程語言中也有相對應的方法能夠進行百分號編碼,例如 JavaScript 中就提供了多種編碼方法,經常使用的有 encodeURI 和 encodeURIComponent 兩個方法。

中文百分號編碼的結果展現

喬巴說,在平常開發使用中,咱們使用的開發庫對 URL 編碼的判斷標準可能並不相同,這是由於這些庫所面臨的網絡環境中,對於特殊字符的安全處理策略各有判斷,這也會致使 URL 中若是存在一些特殊字符,開發、訪問過程當中可能就會出現一些奇怪的問題。在這裏也建議你們使用非保留字符來設計本身程序中 URL 部分,避免一些沒必要要的 BUG 產生。

聽完喬巴的介紹,二狗子終於明白了爲啥 URL 中出現這些奇怪的字符了。嘿嘿,這下能夠和婷婷解釋 URL 爲何這麼長咯。

推薦閱讀

從 301 跳轉,聊聊邊緣規則的那些小妙用

企業如何高效平穩實現數據遷移

相關文章
相關標籤/搜索