HTTP(三):URL编码与解码

URL

1. URL的组成

URL由三部分组成:资源类型、存放资源的主机域名、资源文件名。

URL的一般语法格式为:(带方括号[]的为可选项):

scheme :// hostname[:port] / path / [;parameters][?query]#fragment

image-20190122163554579

部分 说明 实例
protocol 指定使用的传输协议 http
hostname/port 主机名/端口:是指存放资源的服务器的域名系统 (DNS) 主机名或 IP 地址以及端口号 www.baidu.com
path 由零或多个“/”符号隔开的字符串,一般用来表示主机上的一个目录或文件地址 /path/image/
parameters 用于指定特殊参数的可选项
query 用于给动态网页(如使用CGI、ISAPI、PHP/JSP/ASP/ASP.NET等技术制作的网页)传递参数,可有多个参数,用“&”符号隔开,每个参数的名和值用“=”符号隔开
fragment 用于指定网络资源中的片断。例如一个网页中有多个名词解释,可使用fragment直接定位到某一名词解释

例如,在百度搜索“URL编码”,其url为:

https://www.baidu.com/s?ie=UTF-8&wd=url%20%E7%BC%96%E7%A0%81

2. URL的分隔

从上面的URL可以看出,有一些字符用于分隔不同的部分,如下表:

部分 符号 含义
scheme 分隔协议和主机
authorigyt 分隔主机与端口号
path / 分隔主机与路径
query ? 分隔路径与查询参数
fragement #

此外,还有一部分字符用于同一部分的内部的分隔,划分包括!$&’()*+,;=

符号 含义 实例
= 查询参数中键与值的分隔 wd=url
& 多个键值对的分隔 ie=UTF-8&wd=url

URL 编码

1. 为什么需要编码?

URL 只能使用 ASCII 字符集来通过因特网进行发送。 一般来说,URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号。RFC3896中说到:

1
2
3
4
5
6
A URI is composed from a limited set of characters consisting of
digits, letters, and a few graphic symbols. A reserved subset of
those characters may be used to delimit syntax components within a
URI while the remaining characters, including both the unreserved set
and those reserved characters not acting as delimiters, define each
component's identifying data.

那么,假如URL中有中文怎么办?-> URL编码!

2. 如何编码

参考:percent-encoding wiki cn

  1. 由于 URL 常常会包含 ASCII 集合之外的字符,URL 必须转换为有效的 ASCII 格式。
  2. 目前URL编码方案,也叫百分号编码,即将不允许字符转化为%**,% 加上两位的字符-代表一个字节的16进制形式,URL 编码默认使用的字符集是 US-ASCII。URL 不能包含空格。URL 编码通常使用 + 来替换空格。
  3. URL编码的原则就是使用安全的字符,去表示那些不安全的字符。

URL中允许出现的字符:

  • 英文字母(a-zA-Z)
  • 数字(0-9)
  • 4个特殊字符 - _ . ~
    • 所有保留字符 !*’ ( ) ; : @ & = + $ , / ? # [ ]

URL中不允许出现的字符

  • US-ASCII码中的10-7F字节全都表示控制字符,不可以出现在URL中
  • 80-FF字节(ISO-8859-1),超出了US-ACII定义的字节范围,也不可以放在URL中

3. 编码方案

1. 非保留字符

​ ASCII字符集中的的非保留字符, 此字节无需使用百分号表示;

2. 保留字符

​ 根据下表进行编码:

字符 编码 字符 编码 字符 编码
! %21 # %23 $ $24
& %26 %27 ( %28
) %29 * %2A + %2B
, %2C / %2F : %3A
; %3B = %3D ? %3F
@ %40 [ %5B ] %5D

3. 非 ASCII 字符

​ 需要使用 ASCII 字符集的超集进行编码得到相应的字节,然后再对每个字节执行百分号编码 ;

4. Unicode 字符

​ RFC文档建议使用 UTF-8 对其进行编码得到相应的字节,然后再对每个字节执行百分号编码;

对于汉字,如“我”:

汉字 UTF-8 十进制 UTF-8 十六进制 URL编码
15108241 E68891 %e6%88%91

注意:

  1. 空格,使用+来替换,如:http://a b ,编码后:http%3a%2f%2fa+b;

  2. %,%自身编码为%25;

  3. 在一般工具网站上,汉字的unicode编码与UTF-8编码转换:

    | 汉字 | Unicode | Unicode 十六进制 | UTF-8 | 中文转Unicode | 中文转UTF-8 |
    | —- | ——- | ———— | —– | ———- | ———- |
    | 我 | 25105 | 6211 | 6211 | \u6211 | 我 |

其&#x为HTML 字符实体,其中部分可参考下面:

URL 解码

解码即编码,反之。

参考

链接

  1. RFC3986
  2. wiki-统一资源标志符 en