URL 编码完全指南
全面了解 URL 编码:它是什么、为什么重要、百分号编码的工作原理,以及在 URL 中处理特殊字符的最佳实践。
什么是 URL 编码?
URL 编码,也称为百分号编码(percent-encoding),是一种在特定情况下对统一资源标识符(URI)中的信息进行编码的机制。虽然它被称为 URL 编码,但它同样适用于更广泛的统一资源标识符(URI)集合,其中既包括统一资源定位符(URL),也包括统一资源名称(URN)。
之所以需要编码,是因为 URL 只能使用 ASCII 字符集在互联网上传输。而 URL 中经常包含 ASCII 字符集之外的字符,因此必须将 URL 转换为合法的 ASCII 格式。URL 编码会把不安全的 ASCII 字符替换为一个 % 后跟两位十六进制数字。
百分号编码是如何工作的?
百分号编码机制的工作方式是:将每个需要编码的字符转换为一个或多个字节,然后用一个百分号加两位十六进制数字来表示每个字节。这两位十六进制数字表示该字符在指定编码(通常是 UTF-8)下的字节值。
例如,空格字符(ASCII 值为 32,十六进制为 20)会变成 %20。与号 &(ASCII 值为 38,十六进制为 26)会变成 %26。像带尖音符的 e 这类非 ASCII 字符,会先被编码为其对应的 UTF-8 字节序列,然后再对每个字节分别进行百分号编码。
保留字符与非保留字符
RFC 3986 为 URI 定义了两类字符:保留字符(reserved)和非保留字符(unreserved)。非保留字符包括大写和小写字母(A-Z、a-z)、数字(0-9)、连字符(-)、句点(.)、下划线(_)和波浪号(~)。这些字符可以不经编码直接包含在 URI 中。
保留字符在 URL 语法中具有特殊含义,包括::、/、?、#、[、]、@、!、$、&、'、(、)、*、+、,、; 和 =。当这些字符在 URI 组件中被用作其保留用途之外的普通字符时,就必须进行百分号编码。
不同语言中的 URL 编码
JavaScript
JavaScript 提供了两对用于 URL 编码的函数:encodeURI() / decodeURI() 用于编码完整的 URI,而 encodeURIComponent() / decodeURIComponent() 用于编码单个 URI 组件。二者的关键区别在于:encodeURI() 会保留那些在 URI 中具有特殊含义的保留字符(如 /、?、#),而 encodeURIComponent() 会对所有非字母数字字符进行编码。
Python
Python 的 urllib.parse 模块提供了 quote() 和 unquote() 用于基本的编码/解码,还提供了 urlencode() 用于将字典编码成查询字符串。quote() 函数接受一个可选的 safe 参数,用于指定哪些字符不应被编码。
PHP
PHP 提供了 urlencode(),它会将空格编码为 +(遵循 application/x-www-form-urlencoded 格式);还提供了 rawurlencode(),它会将空格编码为 %20(遵循 RFC 3986)。解码时,分别使用 urldecode() 和 rawurldecode()。
最佳实践
- 在将用户输入包含进 URL 之前,务必先进行编码
- 在 JavaScript 中编码查询参数的值时,使用
encodeURIComponent() - 仅在编码完整 URI 时才使用
encodeURI() - 在整个应用程序中保持编码方式的一致性
- 在服务器端处理 URL 之前,务必先对其进行解码
- 使用包括 Unicode 在内的特殊字符测试你的编码逻辑
- 不要对 URL 进行重复编码 —— 始终先检查字符串是否已经过编码