调整字号

URL 编解码知识

关于 URL 编码知识的笔记:

URL 的结构

一个复杂的 URL 例如 https://bob:bobby@www.lunatech.com:8080/file;p=1?q=2#third,其中的各部分分别为:

名称 数据
协议 https
用户名 bob
密码 bobby
主机地址 www.lunatech.com
端口 8080
路径 /file
路径参数 p=1
查询参数 q=2
片段 third

路径(path)部分以“/”开始,并且用“/”分开各个文件夹。如“/photos/egypt/cairo/first.jpg”包含四个路径片段(path segment):photosegyptcairofirst,jpg。每个路径片段都可以带路径参数(可选,也叫 matrix 参数)。路径参数位于片段末尾,以“;”开头,并用“;”分隔。参数名和数值之间用“=”分开,例如 /file;p=1 表示 file 有一个参数 p=1。这类参数并不常用。

哪些字符需要编码

RFC3986 文档规定,URL 中只允许包含英文字母(a-zA-Z)、数字(0-9)、- _ . ~4个特殊字符以及所有保留字符。

保留字符:URL 可以划分成若干个组件,协议、主机、路径等。有一些字符(: / ? # [ ] @)是用作分隔不同组件的。例如“:”用于分隔协议和主机,“/”用于分隔主机和路径,“?”用于分隔路径和查询参数,等等。还有一些字符(! $ & ( ) * + , ; =)用于在每个组件中起到分隔作用的,如“=”用于表示查询参数中的键值对,“&”符号用于分隔查询多个键值对。当组件中的普通数据包含这些特殊字符时,需要对其进行编码。

RFC3986 中指定了以下字符为保留字符:! * ' ( ) ; : @ & = + $ , / ? # [ ]

因此对于 URL 而言,只有普通英文字符和数字,特殊字符 $ - _ . + ! * ' ( ) 还有保留字符,才能出现在未经编码的 URL 之中。其他字符均需要经过编码之后才能出现在 URL 中。

在路径部分,空格必须编码为 %20(而不是加号),+ 号可以不编码。

对于查询字符串,空格必须编码为 + 号或 20%+ 号只是为了向后兼容,并不是标准),+ 号必须编码为 %2B

JavaScript 中的 escape, encodeURIencodeURIComponent 的区别

安全字符不同:下面列出了这三个函数的安全字符(即函数不会对这些字符进行编码)。

  • escape(69个):*/@+-._0-9a-zA-Z
  • encodeURI(82个):!#$&'()*+,/:;=?@-._~0-9a-zA-Z
  • encodeURIComponent(71个):!'()*-._~0-9a-zA-Z

兼容性不同:escape 函数是从 JavaScript 1.0 的时候就存在了,其他两个函数是在 JavaScript 1.5 才引入的。但是由于 JavaScript 1.5 已经非常普及了,所以实际上使用 encodeURIencodeURIComponent 并不会有什么兼容性问题。

对 Unicode 字符的编码方式不同:这三个函数对于 ASCII 字符的编码方式相同,均是使用百分号+两位十六进制字符来表示。但是对于 Unicode 字符,escape 的编码方式是 %uxxxx,其中的 xxxx 是用来表示 unicode 字符的 4 位十六进制字符。这种方式已经被 W3C 废弃了。但是在 ECMA-262 标准中仍然保留着 escape 的这种编码语法。encodeURIencodeURIComponent 则使用 UTF-8 对非 ASCII 字符进行编码,然后再进行百分号编码。这是 RFC 推荐的。因此建议尽可能的使用这两个函数替代 escape 进行编码。

适用场合不同:encodeURI 被用作对一个完整的 URI 进行编码,而 encodeURIComponent 被用作对 URI 的一个组件进行编码。从上面提到的安全字符范围表格来看,我们会发现,encodeURIComponent 编码的字符范围要比 encodeURI 的大。我们上面提到过,保留字符一般是用来分隔 URI 组件或者子组件(如 URI 中查询参数的分隔符),如“:”号用于分隔协议和主机,“?”号用于分隔主机和路径。由于 encodeURI 操纵的对象是一个完整的的 URI,这些字符在 URI 中本来就有特殊用途,因此这些保留字符不会被 encodeURI 编码,否则意义就变了。

表单提交

当 HTML 的表单被提交时,每个表单域都会被 URL 编码之后才在被发送。对于非 ASCII 字符,使用的编码字符集取决于当前文档使用的字符集。例如我们在 HTML 头部加上

<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

这样浏览器就会使用 gb2312 去渲染此文档,当提交表单时,URL 编码使用的字符集就是 gb2312。

另外,HTML 存储时使用的字符集应当和 <meta> 指定的字符集一致。

还没有评论,沙发空缺中……
flight