什么是 URL 编码?
URL 编码(也称百分号编码)是 RFC 3986 定义的、用于在 URL 中传输数据的机制。对在 URL 中具有保留语义的字符(如 ? / # & =)或非 ASCII 可打印字符,会被改写为一个或多个 %XX 三元组,其中 XX 是该字节的十六进制表示。解码时按字节逆向还原。
百分号编码只是一种传输格式,不是安全机制。任何收到编码字符串的人都可以轻易解码;不要把编码误认为加密或哈希。
如何选择模式
本工具暴露了开发者最终都会遇到的三种编码模式。选择的模式决定了哪些字符会被编码。
Component 模式(encodeURIComponent)。当你要把单个值嵌入 URL 的某个位置时使用 —— 查询字符串值、路径片段、fragment 等。它会编码所有 URL 保留字符,因此结果放在任何位置都是安全的。
Whole URL 模式(encodeURI)。当你已经持有一条拼好的 URL,只想转义真正不安全的字符(空格、非 ASCII)时使用。它会保留 : / ? # & = + 等结构性字符,保持 URL 可解析。
Form 模式(application/x-www-form-urlencoded)。当你构建 Content-Type 为 application/x-www-form-urlencoded 的 HTTP 请求体时使用。空格转为 +,换行符归一化为 CRLF(%0D%0A),字符集与浏览器提交 HTML 表单时发出的内容一致。
保留字符参考表
| 字符 | Component | Whole URL | Form |
|---|---|---|---|
| (space) | %20 | %20 | + |
| ! | ! | ! | %21 |
| " | %22 | %22 | %22 |
| # | %23 | # | %23 |
| $ | %24 | $ | %24 |
| % | %25 | %25 | %25 |
| & | %26 | & | %26 |
| ' | ' | ' | %27 |
| ( | ( | ( | %28 |
| ) | ) | ) | %29 |
| * | * | * | * |
| + | %2B | + | %2B |
| , | %2C | , | %2C |
| / | %2F | / | %2F |
| : | %3A | : | %3A |
| ; | %3B | ; | %3B |
| = | %3D | = | %3D |
| ? | %3F | ? | %3F |
| @ | %40 | @ | %40 |
| [ | %5B | %5B | %5B |
| ] | %5D | %5D | %5D |
| ~ | ~ | ~ | %7E |
| %0A | %0A | %0D%0A | |
| 中 | %E4%B8%AD | %E4%B8%AD | %E4%B8%AD |
Component 会编码除 A–Z a–z 0–9 - _ . ! ~ * ' ( ) 之外的全部字符。Whole URL 在此基础上额外保留结构性字符 ; , / ? : @ & = + $ # !。Form 编码与 Component 相同的字符集,并额外编码 ! ' ( ) ~(但不编码 *),把空格换成 + 而不是 %20,并把 \n / \r / \r\n 归一化为 \r\n(编码为 %0D%0A)—— 这正是浏览器提交 application/x-www-form-urlencoded 表单时发出的字节序列。
常见用例
以编程方式构造安全的查询字符串:手工拼接 /search?q=[value] 这类 URL 时,把值经过 Component 模式编码,保证值中出现的 & 或 = 不会污染外层 URL 结构。
在 URL 中嵌套 URL:当你把一个 URL 作为另一个 URL 的参数传递(例如 OAuth 回调地址)时,必须用 Component 模式编码内层 URL,而非 Whole URL —— 否则内层 URL 中的 / : ? & 会被外层 URL 误读为结构符。
使用 fetch 提交表单:当你 POST 一个 Content-Type 为 application/x-www-form-urlencoded 的请求体时,请求体必须按 Form 模式编码。本工具的 Form 模式输出与浏览器发送的字节一致。
局限性
URL 编码不是加密。任何人都可以通过一次函数调用解码其输出;绝不要用编码来隐藏秘密。
模式选择很关键。用 Component 模式编码整条 URL 会把它打烂(每个 / 都变成 %2F)。用 Whole URL 模式编码查询值会留下危险的保留字符(值中的 & 仍然会被消费方当成参数分隔符)。不确定时请选 Component。