长期以来php中空格,URL 中不能显式包含空格已成为共识。 然而,空格存在的方式在不同的标准中并不完全一致,以至于不同的语言有不同的实现。
RFC2396 明确规定空格应编码为 %20。
W3C 标准规定空格可以用 + 或 %20 替换。
老徐当场就懵了。 空格被替换为+,并且+本身只能被编码。 既然如此,为什么不直接对空格进行编码呢? 当然,这只是老徐心中的疑惑。 我们早已无法追溯之前的背景,也无法改变已经既定的事实。 然而,空格到底是用+还是20%代替,+是否需要编码,都是我们今天需要面对的问题。
Go中三种常用的URL编码形式
由于Gopher首先关心的自然是Go语言本身的实现,所以我们首先了解一下Go中常用的三种URL编码形式的优缺点。
url.QueryEscape
fmt.Println(url.QueryEscape(" +Gopher指北"))
// 输出:+%2BGopher%E6%8C%87%E5%8C%97
使用 url.QueryEscape 编码时,空格被编码为 +,+ 本身被编码为 %2B。
url.PathEscape
fmt.Println(url.PathEscape(" +Gopher指北"))
// 输出:%20+Gopher%E6%8C%87%E5%8C%97
使用 url.PathEscape 编码时,空格按 20% 进行编码,而 + 则不进行编码。
url.值
var query = url.Values{}
query.Set("hygz", " +Gopher指北")
fmt.Println(query.Encode())
// 输出:hygz=+%2BGopher%E6%8C%87%E5%8C%97
使用(Values).Encode方法进行编码时,空格被编码为+,+本身被编码为%2B。 进一步检查(Values).Encode方法的源码发现,内部仍然调用了url.QueryEscape函数。 (Values).Encode 方法与 url.QueryEscape 的区别在于,后者仅对查询中的键和值进行编码,而后者对 = 和 & 均进行编码。
对于我们开发者来说,这三种编码方式应该使用哪一种呢? 请继续阅读。 相信你可以在上一篇文章中找到答案。
不同语言的实现
由于空格和+在Go中对URL编码有不同的实现,那么这在其他语言中也存在吗? 我们以PHP和JS为例。
PHP 中的 URL 编码
网址编码
echo urlencode(' +Gopher指北');
// 输出:+%2BGopher%E6%8C%87%E5%8C%97
原始网址编码
echo rawurlencode(" +Gopher指北");
// 输出:%20%2BGopher%E6%8C%87%E5%8C%97
PHP 的 urlencode 与 Go 的 url.QueryEscape 函数具有相同的效果php中空格,而 rawurlencode 对空格和 + 都进行编码。
JS 中的 URL 编码
编码URI
encodeURI(' +Gopher指北')
// 输出:%20+Gopher%E6%8C%87%E5%8C%97
编码URI组件
encodeURIComponent(' +Gopher指北')
// 输出:%20%2BGopher%E6%8C%87%E5%8C%97
JS 的encodeURI 与Go 的url.PathEscape 函数效果相同,而encodeURIComponent 则对空格和+ 都进行编码。
我们应该做什么? 更推荐使用url.PathEscape函数编码
在上一篇文章中,我们已经通过Go、PHP、JS总结了+Gopher的North的编码操作。 这是一个二维表,总结了相应的解码操作是否可行。
编码/解码url.QueryUnescapeurl.PathUnescapeurldecoderawurldecodedecodeURIdecodeURIComponent
url.QueryEscape
url.PathEscape
YY
YY
网址编码
原始网址编码
YY
编码URI
编码URI组件
YY
上表中的YY和Y含义相同。 老徐只用YY表示在Go中建议使用url.PathEscape进行编码,在PHP和JS中建议分别使用rawurldecode和decodeURIComponent进行解码。
在实际开发过程中,Gopher肯定会有需要解码的场景。 这时就需要与URL编码方进行沟通,以获得合适的解码方法。
对值进行编码
那么有没有一种不需要URL编码和解码的通用方法呢? 毫无疑问是有的! 以base32编码为例,编码字符集为AZ和数字2-7。 此时,对value进行base32编码后就不需要再进行url编码了。
最后,衷心希望本文能够对各位读者有所帮助。
本文使用的环境是PHP 7.3.29的Console、go 1.16.6和js Chrome94.0.4606.71。
参考