Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

1. 什么是URI?

1.1. URI

URI,全称为 统一资源标识符,是一个更广义的概念。它的核心作用是标识一个资源。

1.2. URL

URL,全称为 统一资源定位符,它是 URI 的一个子集(或者说是一种具体类型)。它的核心作用是定位一个资源,即告诉你如何以及在哪里可以访问到这个资源。

1.3. URN

URN,全称为 统一资源名称,它也是 URI 的一个子集。它的核心是给资源一个永久的、与位置无关的名称

1.4. 三者之间的关系

我们以书籍的例子来做一个比喻:

  • URI 是广义的“标识”概念。
  • URL 是“住址”,依赖于位置。
  • URN 是“身份证号”,是永久的名称,不依赖于位置。

例子

  • URNurn:isbn:978-7-505-12345-6 (这是一本书的 URN)
  • URLhttps://example-library.com/books/978-7-505-12345-6.pdf (这是这本书在当前图书馆的电子版位置)

即使图书馆的网站倒闭了,这个 URN 依然有效,它永远指向那本特定的书。但那个 URL 就失效了,因为你找不到那个位置了。

2. URI的编码与解码

2.1. 为什么需要 URI 编码?

URI 是由一组有限的字符组成的:

  • 保留字符:如 :, /, ?, #, &, =, +, $ 等,它们在 URI 中有特殊含义。
  • 非保留字符:如字母(A-Z, a-z)、数字(0-9)以及 -, _, ., ~
  • 其他字符:如空格、中文、日文等非 ASCII 字符,以及像 <, >, " 等。

如果 URI 中包含这些“其他字符”或者需要在参数值中使用“保留字符”,就会引起歧义,导致 URI 无法被正确解析。

例如:
如果你想传递一个参数 name,其值为 "O‘Reilly & Associates"

1
https://example.com/search?name=O’Reilly & Associates

这个 URL 会被解析为:

  • 路径:/search
  • 查询参数1:name=O’Reilly
  • 查询参数2:Associates (一个没有值的参数)

这显然不是我们想要的结果。为了解决这个问题,我们需要对不安全的字符进行编码(Encode)

2.2. URI是如何编码的?

URI 编码,也称为百分比编码,其机制非常简单:

  1. 将需要编码的字符转换成其 UTF-8 编码的字节序列。
  2. 然后将每个字节表示为一个 %XX 的格式,其中 XX 是该字节的十六进制数字。

说明: 解码的过程与编码的过程正好相反,就是编码的逆过程。

例如:

  • 空格:其 UTF-8 字节是 0x20(十进制是32),所以编码后是 %20。在查询字符串中,+ 号也常被用来代表空格。
  • 中文字符 “中”
    • 它的 UTF-8 编码是 3 个字节:0xE4, 0xB8, 0xAD
    • 所以编码后是 %E4%B8%AD
  • 符号 “&”:其字节是 0x26,编码后是 %26

现在,用编码来解决上面的例子:
原始值:O’Reilly & Associates
编码后:O%27Reilly%20%26%20Associates
被编码为 %27,空格为 %20&%26

现在 URL 就安全了:

1
https://example.com/search?name=O%27Reilly%20%26%20Associates

3. 编码与解码函数

3.1. encodeURI 与 encodeURIComponent

在JavaScript中,有两个核心的URI编码函数:encodeURI()encodeURIComponent()。它们的主要区别在于编码范围的不同,这直接决定了它们各自的使用场景。

  • **encodeURI()**:
    • 用于编码完整的 URI。它假设输入的是一个完整的 URL,因此会保留那些在 URI 中具有特殊含义的保留字符
    • 对应的解码函数是 decodeURI()
  • **encodeURIComponent()**:
    • 用于编码 URI 的组成部分(比如查询参数的值、路径片段等)。它会把几乎所有非标准字符都编码掉,包括保留字符
    • 对应的解码函数是 decodeURIComponent()

3.2. 编码的区别

这是理解两者区别的关键。下表清晰地展示了它们对待不同字符的行为:

字符类型 示例字符 encodeURI encodeURIComponent 原因
保留字符 ; / ? : @ & = + $ , # 保留 编码 这些字符在 URI 各部分有特殊作用,不能乱编码。
非保留字符 字母、数字、- _ . ! ~ * ' ( ) 保留 保留 这些是安全的,不需要编码。
未保留字符(但有例外) 空格 %20 %20 (或 +application/x-www-form-urlencoded 中) 空格是非法的,必须编码。
其他所有字符 中文、表情等 Unicode 字符 编码 编码 这些字符必须转换为 UTF-8 字节后再进行百分比编码。

简单记忆:

  • encodeURIComponentencodeURI 编码得更多、更彻底
  • encodeURI 只编码那些在任何 URI 部分都非法的字符(如空格、中文字符)。
  • encodeURIComponent 会编码所有在它所在组件中可能引起歧义的字符(包括保留字符)。

评论