RFC3986
本文的英文原文来自Uniform Resource Identifier (URI): Generic Syntax
被更新: 6874 | 标准 |
存在勘误表 | |
网络工作组 | T. Berners-Lee |
申请讨论: 3986 | W3C/MIT |
STD: 66 | R. Fielding |
更新: 1738 | Day Software |
取代: 2732 2396 1808 | L. Masinter |
类别: 标准跟踪 | Adobe Systems |
2005年1月 |
- 统一资源标识符(URI):通用语法
本文的状态
- 本文为互联网社区指定了一个互联网标准跟踪协议, 并为改进它而请求讨论和建议. 关于标准化状态和本协议的状态请参考当前版本的 "互联网官方协议标准" (STD 1). 本文不受限制分发.
版权声明
- Copyright (C) The Internet Society (2005).
摘要
- 一个统一资源标识符(URI)是一个字符的紧凑序列,用来标识一个抽象或物理资源. 本协议定义了通用的URI语法和一个解析相应格式URI引用的过程, 以及在互联网上使用URIs的指南和安全事项. URI语法定义了所有合法的URIs的一个超集的语法, 允许一个实现来解析一个URI引用的常用部件而不需要知道每个可能的标识符的scheme特有的需求. 本协议不为URIs定义现成的语法; 那个任务由每个URI scheme的个体的协议来执行.
目录 |
绪论
一个统一资源标识符(URI)为识别一个资源而提供一个简单的可扩展含义. 本协议的URI语法和语义衍生于万维网全局信息倡议所引入的概念, 这些标识符的使用从1990年就开始了并且在 "WWW中的统一资源标识符" RFC1630 中描述了它们. 语法的设计满足了 "互联网资源定位器功能建议" RFC1736 和 "统一资源名称功能需求" RFC1737 提出的建议.
本文取代了 RFC2396, 它融合了 "统一资源定位器" RFC1738 和 "相对统一资源定位器" RFC1808 以为所有URIs定义一个单一, 通用的语法. 它取代了 RFC2732, 该协议引入了用于IPv6地址的语法. 它排除了RFC 1738中定义了个别URI schemes的特有语法的部分; 那些部分将被更新到独立的文档中. 新URI schemes的注册过程被独立地定义在 BCP35. 给新URI schemes设计者的建议可以在 RFC2718 找到. 所有从 RFC 2396 而来的显著变更都备注在 附录D. RFC 2396以来的变更
本协议遵循 BCP19 提供的建议使用术语 "character" 和 "coded character set" , 并且以 "character encoding" 来取代 BCP19 中所指的 "charset".
URIs概述
URIs的特征如下:
统一
- 统一性提供了很多好处. 它允许不同类型的资源标识符被用在相同的上下文中, 即使当访问那些资源使用的机制不同的时候. 它允许跨越资源标识符的不同类型的常用语法习惯拥有统一的语义解释. 它允许引入新类型的资源标识符而不妨碍现有标识符的使用. 他允许标识符被重用于不同的上下文, 从而允许新的应用或协议支持一个早已存在的, 大的, 和广泛的资源标识符的集合.
资源
- 本协议不限制能成为一个资源的范围; 相反, 术语 "resource" 被用于一般意义上的任何可以由URI标识的东西. 熟悉的例子包括一个电子文档, 一个图片, 一个包含一致的目的的信息源(例如, "洛杉矶今日天气"), 一个服务(例如, 一个 HTTP 到 短信 的网关), 以及一个其他资源的集合. 通过互联网来访问一个资源不是必需的; 例如, 自然人, 组织, 以及在一个图书馆内的限定的书也可能成为资源. 同样的, 抽象概念能成为资源, 类似一个数学方程式的运算符和操作数, 关系的类型(例如, "父母" 或 "雇员"), 或数值(例如, 0, 1, 以及 无穷大).
- 标识符
- 一个标识符包含如何在身份识别的范围中从其他事物区分出被标识的事物的信息. 我们使用术语 "identify" 和 "identifying" (识别)来指代从其他资源区分出一个资源的行动, 不管那个行为是如何完成的(例如, 通过名称, 地址, 或上下文). 这些术语不应错误地假定一个标识符定义或包含的身份所指的事物, 尽管对某些标识符来会发生这种情况. 不应假定一个使用URIs的系统将成功访问所标识的资源: 在很多情况下, URIs被用于指示资源而没有让任何它们被访问的意图. 同样的, "一个" 资源可能并不自然地标识单数(例如, 一个资源可以是一个被命名的组合或一个随时间变化的映射).
一个URI是一个标识符,包含了一系列字符,匹配第三章中<URI>命名的语法规则. 它使得通过独立定义命名的Scheme3.1的可扩展组合来表达资源的统一身份成为可能. 那个身份如何被实现, 被指定, 或被允许取决于每个scheme协议.
本协议没有对一个资源的性质做任何限制, 原因是一个应用可能专注于一个资源, 其他各种系统可能把URIs用来标识多个资源. 本协议不要求一个URI随着时间变化而坚持标识相同资源, 尽管那是所有URI schemes的一个常见目标. 不过, 本协议没有任何东西阻止一个应用把自己限制到特有的资源类型, 或由那个应用维护的具有其期望特性的URIs的一个子集.
URIs有一个全局范围并且对它的一致性解释和上下文无关, 即使那个解释的结果可能和最终用户的上下文产生关系. 例如, "http://localhost/" 对于涉及的每个用户有相同的解释, 即使相当于 "localhost" 的网络接口对每个最终用户可以是不同的: 解释独立于访问. 无论如何, 在那个引用的基础上所做的一个动作将和该最终用户的上下文发生关系, 这暗示一个旨在涉及一个全局唯一的事物的动作必须使用URI来把那个资源从所有其他事物中区分出来. 识别该最终用户的本地上下文的URIs只应该在该上下文本身是该资源的定义的一部分的时候使用, 类似当一个在线帮助手册指向一个位于该最终用户的文件系统上的一个文件(例如, "file:///etc/hosts").
通用语法
每个URI开始于一个scheme名, 如3.1所定义的, 那代表一个该scheme赋予该标识符的协议. 就其本身而言, URI语法是他一个联合的可扩展的命名系统,每个scheme的协议可以进一步限制使用那个scheme的标识符的语法和语义.
本协议定义了那些所有URI schemes或很多常用的URI schemes需要的URI语法的元素. 为此它定义了需要的语法和语义来实现一个独立于scheme的URI参数解析机制, 由此对一个URI的独立于scheme的处理可以延期到需要该独立于scheme的语义的时候. 同样, 用于URI参数的协议和数据格式可以参考本协议,作为所有URIs都允许的语法的范围的定义, 包括那些已经被定义的schemes. 这把身份schemes的演变从协议,数据格式,和使用URIs的实现的演变中隔离出来.
一个通用URI语法的解析器可以把任何URI参数解析成它的主要部件. 一旦该scheme被确认, 更多scheme特有的解析可以在部件上被执行. 换句话说, URI通用语法是所有URI schemes语法的子集.
示例
以下示例URIs展示了一些它们的常用语法部件中的URI schemes和变量:
- ftp://ftp.is.co.za/rfc/rfc1808.txt
- http://www.ietf.org/rfc/rfc2396.txt
- ldap://[2001:db8::7]/c=GB?objectClass?one
- mailto:John.Doe@example.com
- news:comp.infosystems.www.servers.unix
- tel:+1-816-555-1212
- telnet://192.0.2.16:80/
- urn:oasis:names:specification:docbook:dtd:xml:4.1.2
URI, URL, 和URN
一个URI可以被进一步归类为一个定位器, 一个名字, 或两者都是. 术语统一资源定位器 "Uniform Resource Locator" (URL) 代表URIs的那个子集, 除了识别一个资源, 通过描述它的主要访问机制(例如, 它的网络位置 "location")来提供一个该定位资源的含义. 术语统一资源名称 "Uniform Resource Name" (URN) 历史上曾被同时用来代表在 "urn" scheme RFC2141 下的URIs(即使当资源终止存在或成为不可用的时候要想仍然保持全局唯一和持久化就需要它)和任何其他带有名称属性的URI.
一个独立的scheme不一定要被分类成名称 "name" 或定位器 "locator" 之一. 来自任何给定scheme的URIs的实例可以有名称或定位器的性质或两者都是, 经常取决于命名授权机构分配标识符的持久行和意愿, 而不是该scheme的任何能力. 未来的西医和相关文档应该使用通用术语 "URI" 而不是更加受限制的术语 "URL" 和 "URN" RFC3305.
设计事项
转录
URI语法已经被设计成把全局转录作为其主要因素. 一个URI是一系列来自有限集合中的字符: 基本拉丁字母表中的字母,数字,以及一些特殊字符. 一个URI可以被以各种方式展现; 例如, 纸上的墨水, 屏幕上的像素, 或一系列八进制编码的字符. 一个URI的解释只依赖于使用的字符而不是那些字符如何在一个网络协议中展现.
转录的目标可以由一个简单长今来描述. 想想两个同事, Sam 和 Kim, 坐在一个国际化会议的酒店并交换研究思路. Sam向Kim请求一个定位器以获得更多信息, 所以Kim在一个餐巾纸上写下了该研究网站的URI. 然后返回到家里, Sam拿出餐巾纸并把该URI输入到一台电脑中, 然后他获取Kim提到的信息.
这个场景揭示了很多设计因素:
- o 一个URI是一系列字符,不总是以一个八进制序列展现的.
- o 一个URI可以从一个非网络的来源转录并且因此应该包含适合输入到计算机的字符, 同时受到键盘(以及相关的输入设备)从语言到时区的限制的约束.
- o 一个URI经常不得不被人们记住, 并且当它包含有意义的或熟悉的部件的时候是易于被人们记住的.
这些设计因素不总是一致的. 例如, 经常会出现这种情况,对于一个URI部件的最有意义的名称将需要一些无法输入到某些系统的字符. 从一个介质转录一个资源标识符到另一个介质的能力被认为比让URI包含最有意义的组件更重要.
在时区或地区上下文中随着技术的提升, 用户可以从能使用更大范围的字符的能力中受益; 这类用法没有在本协议中定义. 百分号编码八位字节(2.1)可被用于一个URI以展示超出US-ASCII编码字符集范围的字符,如果这一展示被该URI引用的scheme或协议元素允许的话. 这样一个定义应该指定使用的字符编码以在为该URI执行百分号编码之前把那些字符映射到八位字节.
从交互分离身份
对URIs的一个常见误解是它们只用于代表可访问的资源. URI本身只提供身份识别; 一个URI的出现既不保证也不暗示能访问资源. 反之, 和一个URI参数关联的任何操作是由协议元素,数据格式属性,或它所显现的自然语言文本所定义的.
给定一个URI, 一个系统可以尝试对该资源执行各种操作, 这可以被描述为 "access" (访问), "update" (更新), "replace" (替换), 或 "find attributes" (寻找属性). 这类操作由那个使用URIs的协议定义, 不由本协议定义. 无论如何, 为了描述在URIs上的常用操作,我们确实会使用一些通用术语. URI "resolution" 是确定一个访问机制和适当的参数以解参考一个URI的过程; 这一解读可能需要多次迭代. 要使用那个访问机制以在该URI的资源上执行一个操作,就要 "dereference" (解参考)该URI.
当URIs被用于信息获取系统以识别信息来源, 最常用的URI格式解参考是 "retrieval" (获取): 使用一个URI是为了获取一个和它相关的资源的展现. 一个 "representation" (展现)是一系列八位字节, 同时带有展现元数据以描述那些八位字节, 那指定了但展现被生成的时候的那一刻该资源的状态的一个记录. 获取是由一个过程来实现的,可能包括使用一个URI作为一个缓存键来检查一个本地缓存的展现, 为了应用一个获取的操作, 对该URI的解读决定一个适当的访问机制(如果有的话), 以及解参考该URI. 执行获取取决于协议, 可能提供额外的关于该资源的信息(资源元数据)以及它和其他资源的关系.
信息获取系统中的URI参数被设计成延迟绑定: 一个访问的结果通常在它被访问的时候才决定,并且可能随着时间的过去而不同或取决于交互的其他方面. 这些参数的建立是为了在将来使用: 正在被识别的事物并不是一些过去获得的特定结果, 而不是一些用于将来结果的并被期望为真的特征. 在这种情况下, 由该URI代表的资源实际上是一个随时间消逝而被观察到的特征的同一个东西, 可能由额外的资源提供者做出的注释或声明来解释.
尽管很多URI schemes在协议之后被命名, 这不表示使用这些URIs将导致通过命名的协议来访问该资源. URIs经常被简单的用于身份识别的目的. 甚至当一个URI被用于获取一个资源的一个展现, 那个访问可能是通过网关, 代理, 缓存, 以及独立于该scheme名称相关的协议的名称解析服务. 一些URIs的解析可能需要使用多个协议(例如, DNS和HTTP典型的都被用于访问一个 "http" URI的原始服务器,当未在本地缓存中发现一个展现的时候.
层次标识符
URI语法被组织成多层次的, 列出的部件从左到右重要性逐次降低. 对于某些URI schemes, 可见的层次受限于该scheme本身: 在scheme部件分隔符(":")之后的每个东西被认为对URI处理是不透明的. 其他URI schemes让层次对通用解析算法明确和可见.
通用语法使用斜杠("/"), 问号("?"), 以及数字符号("#") 字符以分隔那些对于通用解析器对一个标识符的分层次解释很重要的部件. 除了通过熟悉的语法的一致性使用有助于这类标识符的可读性, 跨命名scheme的层次统一展示允许独立于scheme的参数被关联到那个层次.
常有的情况是一个文档组或树("tree")被构造出来服务于某个常见的目的, 其中在这些文档中的绝大多数URI参数指向的资源有树在里面而不是在它外面. 类似的, 位于一个特定网站的文档更加类似于代表那个网站的其他资源而不是位于远端网站的资源. URIs的相关参考允许文档树被部分独立于它们的位置和访问scheme. 例如, 单独一组超文本有可能被同时访问和遍历, 通过每个 "file", "http", 和 "ftp" schemes,如果这些文档以相对引用互相参考的话. 而且, 这类文档树可以被移动, 作为一个整体, 不改变任何相对引用.
一个代表一个资源的相对引用(4.2),就是描述一个层次名字空间中该参数上下文和该目标URI之间的不同. 该参数解析算法, 在第5章介绍, 定义了一个参数被转化多少到目标URI. 因为相对引用只能被用于一个层次化URI的上下文, 新URI schemes的设计者应该使用一个和通用语法的层次化部件一致的语法,除非有强迫的原因要禁止对那个scheme做相对引用.
- 注意: 之前的协议使用术语局部URI( "partial URI" )和相对URI ( "relative URI" )以表示一个对URI的相对引用. 因为一些读者误解那些术语,以为它意味着相对URIs是URIs的一个子集而不是一个引用URIs的方法, 本协议简单地以相对引用来代表它们.
所有URI参数使用的时候由通用语法解析器解析. 然而, 因为层次处理不影响在一个参数中的绝对URI,除非它包含一个或多个点段(完整的 "." 或 ".." 路径段, 如3.3所述), URI scheme协议可以定义不透明的标识符,通过不允许使用斜杠字符, 问号字符, 和URIs "scheme:." 以及 "scheme:..".
语法符号
本协议使用RFC2234的增强巴科斯范式(ABNF)符号, 包括由以下协议定义的核心ABNF语法规则: ALPHA (字母), CR (回车), DIGIT (小数位数), DQUOTE (双引号), HEXDIG (十六进制数字), LF (换行), 和 SP (空格). 完整的URI语法收集在附录A.
字符
URI语法提供了一个编码数据的方法, 想必为了识别一个资源的缘故, 如同一系列字符. URI字符顺序和经常性地被编码成八位字节用于传输或展示. 本协议不强制任何特定的在URI字符和用于存储或传输那些字符的八位字节之间的字符编码映射表. 当一个URI出现在一个协议元素中, 字符编码由协议定义; 没有这里定义, 则一个URI被假定其字符编码和周围的文本相同.
ABNF字符定义它的终端值为非负整数(码点)基于US-ASCII编码字符集ASCII. 因为一个URI是一系列字符, 我们必须倒置关系以理解该URI语法. 所以, ABNF使用的整数值必须通过US-ASCII映射回它们的相应字符以完成该语法规则.
一个URI由一个包含数字,字母,和一些图形符号的有限集合的字符组成. 一个那些字符的保留子集可能被用于限定一个URI中的语法部件使用保留字符, 同时包括未保留集合和那些不作为分隔符的字符, 定义每个部件的识别数据.
百分号编码
一个百分号编码机制被用于在一个部件里展示一个八位字节码数据,当那个八位字节码相应的字符超出了允许的集合或被用作分隔符,或在部件之内的时候. 一个百分号编码的八位字节码被编码成一个三重字符, 包括百分号字符 "%" 和随后的两个十六进制数字展示那个八位字节的数值. 例如, "%20" 是二进制字节 "00100000" (ABNF: %x20)的百分号编码, 它在US-ASCII中对应空格字符(SP). 2.4描述了何时应用百分号编码和解码.
pct-encoded = "%" HEXDIG HEXDIG
大写的十六进制数字 'A' 到 'F' 分别等价于小写的数字 'a' 到 'f' . 如果两个URIs在百分号编码字节中使用的十六进制数字的大小写不同, 它们是等价的. 为了了一致性, URI制作造和正规化者应该对所有百分号编码使用大写十六进制数字.
保留字符
包含部件和子部件的的URIs由 "保留" 集合中的字符来分隔. 这些字符被成为保留( "reserved" )是因为它们可能(也可能不)被一个URI的解参考算法的通用语法,每个scheme特有的语法,或实现特有的语法定义成分隔符. 如果用于一个URI的数据和一个保留的作为分隔符的字符发生冲突, 那么该冲突的数据必须在该URI被格式化之前进行百分号编码.
reserved = gen-delims / sub-delims gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
保留字符的目的是提供一组分隔符号来把一个URI从其他数据中区分开. URIs把保留字符替换成相应的百分号编码字节之后就就和原来的URIs不等价了. 百分号编码一个保留字符, 或解码一个对应某个保留字符的百分号编码字节, 将改变该URI如何被大部分应用理解. 因此, 在保留集合中的字符被从标准化中保护并且因而可以安全地用于scheme特有和制作者特有的算法以从一个URI分隔出数据子部件.
一个保留字符的子集(gen-delims)被用作通用URI部件的分割符,如第3章所述. 一个部件的ABNF语法规则将不直接使用保留的或gen-delims规则名; 反之, 每个语法规则列出那个部件允许的字符(即, 不分隔它), 并且那些也在保留集合中的任何字符都会是保留的 "reserved" ,被用作该部件中的子部件分隔符. 只有大多数常用子部件由本协议定义; 其他子部件可以由一个URI scheme的协议, 或由一个URI的解参考算法的实现特有的语法定义, 这样这类子部件就由那个部件中允许的保留集合中字符来分隔了.
制作URI的应用应该对在保留集合中的字符的数据字节做百分号编码以在那个组件展示数据,除非这些字符被URI scheme特别允许. 如果在一个URI部件中发现一个保留字符并且那个字符没有已知的分隔规则, 那么它必须被解释成展示相对应的那个字符的US-ASCII编码的数据字节.
非保留字符
被允许出现在一个URI中的字符但是没有被保留用途,被成为非保留(unreserved). 这包含大写和小写字母, 小数数字, 连字符, 句号, 下划线, 以及波浪号.
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
URIs中的一个非保留字符被替换成相应的百分号编码的US-ASCII字节之后和原来是等价的: 它们标识相同的资源. 无论如何, URI比较的实现不总是在比较之前执行标准化(见第6章). 为了保持一致性, 在范围 ALPHA (%41-%5A 和 %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), underscore (%5F), 或 tilde (%7E) 中的百分号编码不应该被URI制作者创建,并且当它们被在一个URI中发现了, 应该由URI标准化把它们解码成相应的非保留字符.
何时编码或解码
在正常情况下, 只有在从部件部分生成URI的过程中一个URI内的字节才有机会被百分号编码. 正是在这个时候一个实现会决定哪个保留字符被用作子部件分隔符以及哪个能被安全地用作数据. 一旦生成了, 一个URI总是保持它的百分号格式.
当一个URI被解参考的时候, 对scheme特有的解参考过程(如果有的话)重要的部件和子部件在那些部件中的百分号编码字节能被解码之前必须被解析和分离, 因为否则数据会和部件分隔符搞错. 唯一的例外是百分号编码的字节相应的字符在非保留集合中, 它能在任何时候被解码. 例如, 在旧的URI处理实现中, 对应于波浪号("~")字符的字节经常被编码成 "%7E" ; "%7E" 可以被 "~" 替代而不需要改变它的解释.
因为百分号("%")字符用作百分号编码字节的指针, 它必须被百分号编码成 "%25" 才能把那个字节用作一个URI的数据. 实现不能多次百分号编码或解码相同的字符串, 因为解码一个现有的已解码字符串可能导致把一个百分号数据字节错误地解释成一个百分号编码的开始, 反之亦然,百分号编码一个已做百分号编码的字符串.
识别数据
URI字符为该URI部件的每一部分提供识别数据, 作用看起来像一个用于系统之间识别身份的外部接口. 尽管URI制作接口的出现和类型被使用它的URIs的客户端隐藏了(并且因而超出了本协议定义的互操作性需求的范围), 它经常是对URI字符发表的解释出现混淆和错误的来源. 实现不得不注意到有多重字符编码被卷入到URIs的制作和传输中: 本地名称和数据编码, 公共接口编码, URI字符编码, 数据格式编码, 以及协议编码.
本地名称, 类似文件系统名称, 被以一个本地字符编码存储. URI制作应用(例如, 起源服务器)典型地将使用本地编码作为基础用于制作有意义的名称. 该URI制作者将把本地编码转换成一个适合公共接口的东西,接着把该公共接口编码转换成URI字符的受限集合(保留, 非保留, 以及百分号编码). 那些字符顺序地被编码成八位字节以用于带有一个数据格式的参数(例如, 一个文档字符集), 并且这类数据格式经常随后被编码以在互联网协议上传输.
对大多数系统, 出现在一个URI部件中的非保留字符被视为展示对应于那个字符的US-ASCII编码的数据字节. URIs的消费者假定字符 "X" 对应于字节 "01011000", 并且甚至当那个假定不正确时, 这么对待它也没有害处. 一个内部提供不同的字符编码的标识符的系统, 类似 EBCDIC, 通常将在一个内部接口对原文的标识符执行字符翻译成UTF-8STD63 (或一些其他的US-ASCII字符编码的超集) , 从而提供更有意义的标识符而不是那些从简单地对原始字节做百分号编码而来的结果.
例如, 考虑一个提供数据的信息服务, 在本地使用基于EBCDIC的文件系统存储, 客户端则在互联网上通过一个HTTP服务器访问它. 当一个作者在那个文件系统上创建一个名为 "Laguna Beach" 的文件, "http" URI对应的那个资源被期望包含有意义的字符串 "Laguna%20Beach". 如果, 无论如何, 那个服务器使用一个过于简单的纯字节映射来制作URIs, 那么该结果将是一个包含 "%D3%81%87%A4%95%81@%C2%85%81%83%88" 的URI. 一个内部转码接口通过在制作该UIR之前把本地名称转码成一个US-ASCII的超集修复了这个问题. 自然的, 一个在这样一个接口上的入站URI的正确解释需要在该反向转换被应用之前把那个百分号编码字节解码(例如, 把 "%20" 解码成 SP)以获得本地名称.
在某些情况下, 在一个URI部件和识别数据之间的已经被手工制作的内部接口展现得还不如一个字符编码翻译直接. 例如, 一个URI的一部分可能反映一个对非ASCII数据的查询, 或一个地图上的数字坐标. 同样的, 一个URI scheme可能定义部件时要求在格式化该部件并制作该URI之前进行编码.
当一个新的URI scheme定义一个展示包含来自统一字符集UCS的字符的原文数据的部件, 该数据应该首先根据UTF-8字符编码STD63被编码成字节; 然后只有那些在非保留集合中没有对应字符的字节应该被百分号编码. 例如, 字符 A 将被展示成 "A", 字符 LATIN CAPITAL LETTER A WITH GRAVE 将被展示成 "%C3%80", 而字母 KATAKANA LETTER A 将被展示成 "%E3%82%A2".
语法部件
通用URI语法包括一系列分层的由 scheme, authority, path, query, 和 fragment 参考的部件.
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty
部件的scheme和path部件是必需的, 尽管path可能是空的(无字符). When authority is present, the path must
either be empty or begin with a slash ("/") character. When authority is not present, the path cannot begin with two slash characters ("//"). These restrictions result in five different ABNF rules for a path (Section 3.3), only one of which will match any given URI reference.
The following are two example URIs and their component parts:
foo://example.com:8042/over/there?name=ferret#nose \_/ \______________/\_________/ \_________/ \__/ | | | | | scheme authority path query fragment | _____________________|__ / \ / \ urn:example:animal:ferret:nose