了解一下URI(Uniform Resource Identifiers)统一资源标志符

2,475 阅读6分钟

按照下面顺序了URI

  • 什么是统一资源标志符?
  • URI 与URL和URN的关系?
  • URI 的组成。
  • encodeURI()、 encodeURIComponent()、decodeURI()、decodeURIComponent()的使用和区别
  • 百分号编码

什么是统一资源标志符?

统一资源标志符(英语:Uniform Resource Identifier,缩写:URI)在电脑术语中是用于标志某一互联网资源名称的字符串。

URI 与URL和URN的关系?

先看定义

  • URI(Uniform Resource Identifier,统一资源标识符)是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对网络中(一般指万维网)的资源通过特定的协议进行交互操作。
  • URL(Uniform Resource Locator,统一资源定位符),最常见的形式是 URI,经常指定为非正式的网址。

image.png

  • URN(Uniform Resource Name,统一资源名称),其目的是通过提供一种途径,用于在特定的命名空间资源的标识,以补充网址。

image.png 例如

  1. urn:website:language:html:head
  2. urn:isan:0000-0000-2CEA-0000-1-0000-0000-Y
  3. urn:ISSN:0167-6423

image.png

URL(定位符)和URN(名称)方案属于URI的子类,URI可以为URL或URN两者之一。技术上讲,URL和URN属于资源ID;但是,人们往往无法将某种方案归类于两者中的某一个:所有的URI都可被作为名称看待,而某些方案同时体现了两者中的不同部分

URI 的组成

URI文法由URI协议名(例如httpftpmailtofile),一个冒号,和协议对应的内容所构成。特定的协议定义了协议内容的语法和语义,而所有的协议都必须遵循一定的URI文法通用规则,亦即为某些专门目的保留部分特殊字符。URI文法同时也就各种原因对协议内容加以其他的限制,例如,保证各种分层协议之间的协同性。百分号编码也为URI提供附加信息。

通用URI的格式如下:

协议名://主机名:端口/路径?查询参数#片段ID

下图展示了两个 URI 例子及它们的组成部分。

image.png

encodeURI()、 encodeURIComponent()、decodeURI()、decodeURIComponent()的使用和区别

Global(全局)对象可以说是 ECMAScript 中最特别的一个对象了,因为不管你从什么角度上看, 这个对象都是不存在的。ECMAScript 中的 Global 对象在某种意义上是作为一个终极的“兜底儿对象” 来定义的。换句话说,不属于任何其他对象的属性和方法,最终都是它的属性和方法。事实上,没有全局变量或全局函数;所有在全局作用域中定义的属性和函数,都是 Global 对象的属性。

  1. URI 编码方法 Global 对象的 encodeURI()和 encodeURIComponent()方法可以对 URI(Uniform Resource Identifiers,通用资源标识符)进行编码,以便发送给浏览器。有效的 URI 中不能包含某些字符,例如 空格。而这两个URI编码方法就可以对 URI 进行编码,它们用特殊的 UTF-8 编码替换所有无效的字符, 从而让浏览器能够接受和理解。 其中,encodeURI()主要用于整个 URI(例如,www.wrox.com/illegal value.htm),而 encodeURIComponent()主要用于对 URI 中的某一段(例如前面 URI 中的 illegal value.htm)进行编码。 它们的主要区别在于,encodeURI()不会对本身属于 URI 的特殊字符进行编码,例如冒号、正斜杠、 问号和井字号;而 encodeURIComponent()则会对它发现的任何非标准字符进行编码。来看下面的例子。
var uri = "http://www.wrox.com/illegal value.htm#start"; 
//"http://www.wrox.com/illegal%20value.htm#start" 
alert(encodeURI(uri)); 
//"http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start" 
alert(encodeURIComponent(uri)); 

使用 encodeURI()编码后的结果是除了空格之外的其他字符都原封不动,只有空格被替换成 了%20。而 encodeURIComponent()方法则会使用对应的编码替换所有非字母数字字符。这也正是可 以对整个URI使用encodeURI(),而只能对附加在现有URI后面的字符串使用encodeURIComponent() 的原因所在。

一般来说,我们使用 encodeURIComponent() 方法的时候要比使用 encodeURI()更多,因为在实践中更常见的是对查询字符串参数而不是对基础 URI 进行编码。

encodeURI()和 encodeURIComponent()方法对应的两个方法分别是 decodeURI()和 decodeURIComponent()。其中,decodeURI()只能对使用 encodeURI()替换的字符进行解码。例如, 它可将%20 替换成一个空格,但不会对%23 作任何处理,因为%23 表示井字号(#),而井字号不是使用 encodeURI()替换的。同样地,decodeURIComponent()能够解码使用 encodeURIComponent()编码的所有字符,即它可以解码任何特殊字符的编码。来看下面的例子:

var uri = "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start"; 
//http%3A%2F%2Fwww.wrox.com%2Fillegal value.htm%23start 
alert(decodeURI(uri));
//http://www.wrox.com/illegal value.htm#start 
alert(decodeURIComponent(uri));

这里,变量 uri 包含着一个由 encodeURIComponent()编码的字符串。在第一次调用 decodeURI() 输出的结果中,只有%20 被替换成了空格。而在第二次调用 decodeURIComponent()输出的结果中, 所有特殊字符的编码都被替换成了原来的字符,得到了一个未经转义的字符串(但这个字符串并不是一 个有效的 URI)。

URI 方法 encodeURI()、encodeURIComponent()、decodeURI()和 decodeURIComponent()用于替代已经被ECMA-262第3版废弃的escape()和unescape() 方法。URI方法能够编码所有 Unicode字符,而原来的方法只能正确地编码 ASCII 字符。 因此在开发实践中,特别是在产品级的代码中,一定要使用 URI方法,不要使用 escape() 和 unescape()方法。

百分号编码

百分号编码(英语:Percent-encoding),又称:URL编码(URL encoding)是特定上下文的统一资源定位符 (URL)的编码机制,实际上也适用于统一资源标志符 URI)的编码。也用于为 application/x-www-form-urlencoded MIME(准备数据,因为它用于通过HTTP的请求操作(request)提交HTML表单数据。

URI的百分号编码

URI的字符类型

URI所允许的字符分作保留未保留保留字符是那些具有特殊含义的字符,例如:斜线字符用于URL(或URI)不同部分的分界符;未保留字符没有这些特殊含义。百分号编码把保留字符表示为特殊字符序列。上述情形随URI与URI的不同版本规格会有轻微的变化。

!*'();:@&=+$,/?#[]
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789-_.~

URI中的其它字符必须用百分号编码。

对保留字符的百分号编码

如果一个保留字符在特定上下文中具有特殊含义(称作"reserved purpose") , 且URI中必须使用该字符用于其它目的, 那么该字符必须百分号编码。百分号编码一个保留字符,首先需要把该字符的ASCII的值表示为两个16进制的数字,然后在其前面放置转义字符("%"),置入URI中的相应位置。(对于非ASCII字符, 需要转换为UTF-8字节序, 然后每个字节按照上述方式表示.)

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

在特定上下文中没有特殊含义的保留字符也可以被百分号编码,在语义上与不百分号编码的该字符没有差别.

在URI的"查询"查询字符串(页面不存在)")"成分(?字符后的部分)中, 例如"/"仍然是保留字符但是没有特殊含义,除非一个特定的URI有其它规定. 该/字符在没有特殊含义时不需要百分号编码.

如果保留字符具有特殊含义,那么该保留字符用百分号编码的URI与该保留字符仅用其自身表示的URI具有不同的语义。