1. 什么是URL编码
URL编码(也叫百分号编码)是把URL中不能直接使用的字符转换成"%"加两位十六进制数的过程。由于URL规范只允许ASCII字符集,中文、空格、以及大部分符号都必须先编码才能安全地放进URL里。比如空格会变成%20,@符号会变成%40,中文"你好"会被编码成%E4%BD%A0%E5%A5%BD。这个规则来自RFC 3986标准,规定除了字母、数字和-、_、.、~这几个符号外,其他字符都需要编码。URL的不同部分(路径、查询参数、锚点)在编码细节上也略有差异。
安全地对URL进行编码或解码。自动处理查询参数中的特殊字符、中文和空格,帮助你生成格式正确的URL。
URL编码(也叫百分号编码)是把URL中不能直接使用的字符转换成"%"加两位十六进制数的过程。由于URL规范只允许ASCII字符集,中文、空格、以及大部分符号都必须先编码才能安全地放进URL里。比如空格会变成%20,@符号会变成%40,中文"你好"会被编码成%E4%BD%A0%E5%A5%BD。这个规则来自RFC 3986标准,规定除了字母、数字和-、_、.、~这几个符号外,其他字符都需要编码。URL的不同部分(路径、查询参数、锚点)在编码细节上也略有差异。
URL里的很多符号本身就有特殊含义,如果不编码直接使用,浏览器和服务器会误解你的意图。比如&是用来分隔多个参数的,如果参数值里本身就含有&,就必须编码成%26,否则会被当成新的参数。同理,=用来连接键和值,?标志查询字符串的开始,#表示锚点位置。空格通常编码为%20或+。如果把用户输入的中文、符号原样拼进URL,轻则出现404或参数解析错误,重则可能引发注入类的安全问题。所以只要是动态拼接的内容,尤其是用户输入或搜索关键词,都建议先编码再使用。
查询参数是URL里最需要编码的部分。例如 https://example.com/search?q=搜索词&category=分类,这里的"搜索词"和"分类"都必须编码。在JavaScript里,encodeURIComponent()会把=、&、?这些结构字符也一并编码,非常适合处理单个参数值。而encodeURI()是给整段URL用的,它不会编码=、&、?,所以如果你只是想编码某个参数值,用encodeURI()反而会出问题。正确的做法是:对键和值分别调用encodeURIComponent(),再手动用&和=拼接成完整的查询字符串。
JavaScript提供了两个常用的编码函数,用途不同。encodeURI()面向整个URL,它保留URL的结构字符(如:、/、?、&、=),只编码那些真正非法的字符,适合你已经拼好一个完整地址、只想做一次整体转义的场景。encodeURIComponent()则更彻底,它会把结构字符也编码掉,专门用于处理URL的某一部分——比如一个查询参数的值、路径中的一段动态内容。绝大多数业务场景下(比如把用户输入塞进URL),应该优先使用encodeURIComponent(),这样才不会因为用户输入里恰好含有&或=而破坏URL结构。对应的解码函数分别是decodeURI()和decodeURIComponent()。
如果域名本身包含中文或其他非拉丁字符(比如"中国.com"),浏览器不会用普通的百分号编码,而是转换成Punycode格式,并加上xn--前缀,例如"中国.com"会变成"xn--fiqs8s.com"。这是因为域名系统(DNS)在底层只支持ASCII字符,Punycode是专门为国际化域名设计的编码方案。浏览器地址栏会自动完成这个转换,普通用户几乎感觉不到,但如果你在代码里需要手动处理域名,就需要引入专门的Punycode编码库,不能直接用encodeURIComponent()来处理域名部分。
在实际开发中使用URL编码时,有几个要点值得注意。第一,任何来自用户的输入在拼进URL前都应编码,这也是防范XSS等注入攻击的基本措施之一。第二,要留意"重复编码"的问题——如果一个字符串已经是编码过的,再编码一次会把%本身也转义掉,变成完全无法识别的乱码,所以处理前最好先确认当前状态。第三,现代HTTP客户端(如fetch、axios)通常会自动处理URL编码,手动再编码一次容易导致双重编码,应仔细核对文档。第四,调试或记录日志时,建议保留解码后的可读形式,方便排查问题;只有在真正发送请求时才使用编码后的版本。