php encodeuricomponent 还原,淺談 HTTP URL 規範 - 善用 JavaScript encodeURIComponent() 與 PHP rawurlencode() 來...

惱人的 URL Encode/Decode

我們常在開發 Web 時,會發生連結失效 (404 Page not found.)、特別的參數值傳遞不正確、Query String 解譯錯誤等等問題或 Bug。追究之後常常都是忽略了 URL 編碼或者用了不正確的編碼所造成,看來我們需要多多認識 URL 的特性,順便養成「對 URL 敏感」的習慣。

URI 規範的歷史淵源

先來看看 URI 的歷史。最早在 1994 年 12 月,RFC 1738 起頭定義了 URI 最初的規範。經過了幾年的混亂與磨練,一直到了 1998 年 8 月才有了比較廣泛的標準,那就是 RFC 2396。而我們最常接觸的 RFC 2616 (也就是 HTTP 1.1) 在處理 URI 也是遵循 RFC 2396 標準,我們可以在規範看見以下描述:3.2.3 URI Comparison

Characters other than those in the "reserved" and "unsafe" sets (see RFC 2396 [42]) are equivalent to their ""%" HEX HEX" encoding.

但是後來隨著環境的演進,直到 2005 年 1 月所發佈的 RFC 3986 最終成為目前主流所實作的規範。因此以目前來說,採用 RFC 3986 是比較明智的選擇。

PHP urlencode() 與 rawurlencode() 的差異

先來測試一下:

1

2

3

4

5

6

7

8

9<?php

$str='1+2&b and c';

echourlencode($str);

// show: 1%2B2%26b+and+c

echorawurlencode($str);

// show: 1%2B2%26b%20and%20c

發現了嗎?兩者在於對空白 (space) 的處理有不同的邏輯,根據官方文件描述 PHP 中的 urlencode() function 是遵循 application/x-www-form-urlencoded (就是我們常說的 Query String) 編碼規範,因此會把 space 空白變成 + 而不是  %20,如下:urlencode differs from RFC 1738 by encoding spaces as + instead of %20

然而 PHP 中的 rawurlencode() function 是遵循 RFC 3986 進行實作,如下:Encodes the given string according to » RFC 3986.

由此看來使用 rawurlencode() 才是最推薦的方法,測試如下:

JavaScript 中的 encodeURIComponent() 與encodeURI() 的差異

JavaScript 測試如下:

1

2

3

4

5

6

7

8

9<scripttype="text/javascript">

document.write(encodeURIComponent('1+2&b and c'));

// show: 1%2B2%26b%20and%20c

</script>

<scripttype="text/javascript">

document.write(encodeURI('1+2&b and c'));

// show: 1+2&b%20and%20c

</script>

在 JavaScript 中,encodeURIComponent() 與 encodeURI() 差別在保留字 (不進行編碼的字元) 的定義不同:

encodeURI() 的保留字為 ~!@#$&*()=:/,;?+'

encodeURIComponent() 的保留字為 ~!*()'

此外 JavaScript 中的 encodeURIComponent() 也是遵循 RFC 3986 編碼,因此比較推薦採用這個函式。

討論

其實最混亂的就是 + 與 %20 的問題,在 JavaScript 中所提供的 encodeURI() 並不是遵循 application/x-www-form-urlencoded 編碼規範,如果要在 JavaScript 環境下自行實作 application/x-www-form-urlencoded 編碼就必須先使用 encodeURIComponent() 轉換,然後再另外將 %20 取代為 + 即可,如此就達到跟 PHP urlencode() 一樣的效果。

此外,我們在 Web 開發的過程中輸出 HTML 連結,雖然大多數瀏覽器都會很友善的自動對網址進行轉換再送出 HTTP Request 連線,但未了避免例外情況,我們還是遵循 RFC 3986 來處理 URL 比較正確,相容性也比較高。

參考資料

這是真的廣告

白金贊助

ebb7e7de37b5329315caa8bad2210398.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值