RFC3986

来自Jabber/XMPP中文翻译计划
(版本间的差异)
跳转到: 导航, 搜索
(主机)
(主机)
第291行: 第291行:
 
主机的语法规则是含糊的,因为不能完全区分一个IPv4地址和一个注册名称. 为了澄清语法, 我们应用 "先匹配者赢" 算法: 如果主机匹配IPv4地址规则, 那么它应该被认为是一个IPv4地址文字而不是一个注册名称. 尽管主机是大小写敏感的, 为了统一的目的制作者和正规化者应该对注册名和十六进制地址使用小写, 只在百分号编码使用大写字母.
 
主机的语法规则是含糊的,因为不能完全区分一个IPv4地址和一个注册名称. 为了澄清语法, 我们应用 "先匹配者赢" 算法: 如果主机匹配IPv4地址规则, 那么它应该被认为是一个IPv4地址文字而不是一个注册名称. 尽管主机是大小写敏感的, 为了统一的目的制作者和正规化者应该对注册名和十六进制地址使用小写, 只在百分号编码使用大写字母.
  
  A host identified by an Internet Protocol literal address, version 6
+
由版本6[http://tools.ietf.org/html/rfc3513 RFC3513]或更晚版本的互联网协议文字地址标识的主机, 是通过方括号("[" "]")围起IP文字来区分的. 这是唯一一个被允许在URI语法中出现方括号字符的地方. 在可预见的将来, 还未定义的IP文字地址格式, 实现可以使用一个可选的版本标记来显式地指示这样一个格式而不是依靠启发式的决定.
  [RFC3513] or later, is distinguished by enclosing the IP literal
+
  within square brackets ("[" and "]"). This is the only place where
+
  square bracket characters are allowed in the URI syntax. In
+
  anticipation of future, as-yet-undefined IP literal address formats,
+
  an implementation may use an optional version flag to indicate such a
+
  format explicitly rather than rely on heuristic determination.
+
  
 +
<source lang="text">
 
       IP-literal = "[" ( IPv6address / IPvFuture  ) "]"
 
       IP-literal = "[" ( IPv6address / IPvFuture  ) "]"
  
 
       IPvFuture  = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
 
       IPvFuture  = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
 +
</source>
  
  The version flag does not indicate the IP version; rather, it
+
版本标记不指示IP版本; 而是指示该文字格式的未来版本. 同样的, 实现不能为下面描述的现有的IPv4和IPv6文字地址格式提供该版本标记. 如果一个URI包含一个以 "v" (大小写不敏感)开始的IP-文字, 标识那个版本标记是当前的, 当它由一个不理解该版本标记的含义的应用解参考的时候, 那么该应用返回一个适当的错误 "地址机制不支持".
  indicates future versions of the literal format. As such,
+
  implementations must not provide the version flag for the existing
+
  IPv4 and IPv6 literal address forms described below. If a URI
+
  containing an IP-literal that starts with "v" (case-insensitive),
+
  indicating that the version flag is present, is dereferenced by an
+
  application that does not know the meaning of that version flag, then
+
  the application should return an appropriate error for "address
+
  mechanism not supported".
+
  
 
   A host identified by an IPv6 literal address is represented inside
 
   A host identified by an IPv6 literal address is represented inside
第318行: 第306行:
 
   literal address provided in [RFC3513].  This syntax does not support
 
   literal address provided in [RFC3513].  This syntax does not support
 
   IPv6 scoped addressing zone identifiers.
 
   IPv6 scoped addressing zone identifiers.
 
 
 
 
Berners-Lee, et al.        Standards Track                    [Page 19]
 
 
 
RFC 3986                  URI Generic Syntax              January 2005
 
 
  
 
   A 128-bit IPv6 address is divided into eight 16-bit pieces.  Each
 
   A 128-bit IPv6 address is divided into eight 16-bit pieces.  Each

2013年8月30日 (五) 14:42的版本


本文的英文原文来自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可能是空的(无字符). 当authority是现成的, path必须要么是空的要么是以一个斜杠("/")开始的字符串. 当authority不是当前的, path不能以两个斜杠("//")开始. 这些约束导致5个用于path的不同ABNF规则(3.3), 它们中只有一个将匹配任何给定的URI参数.

以下是两个示例URIs以及它们的部件部分:

         foo://example.com:8042/over/there?name=ferret#nose
         \_/   \______________/\_________/ \_________/ \__/
          |           |            |            |        |
       scheme     authority       path        query   fragment
          |   _____________________|__
         / \ /                        \
         urn:example:animal:ferret:nose

格式

每个URI以一个格式名称开始,它代表分配给带那个格式的标识符的一个协议. 因此, URI语法是一个联合的和可扩展的命名系统,这里每个格式的协议可以进一步约束使用那个格式的标识符的语法和语义.

格式名称包含一系列以一个字母开始的并跟随任意字母,数字,加号("+"), 句号("."), 或连字符("-")的组合. 尽管格式是大小写敏感的, 权威的格式是小写的且那些定义格式的文档必须以小写字符来定义. 为了鲁棒性的目的,一个实现应该接受在格式名称中大写字符等价于小写字符(例如, 除了 "http" 也允许 "HTTP" ) ,但是为了一致性,应该只制作小写格式名称.

      scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )

本文没有定义独立的格式. 注册一个新URI格式的过程被独立地定义于BCP35. 格式注册表维护了格式名称和它们的协议之间的对应关系. 给新URI格式设计者的建议可以在RFC2718找到. URI格式协议必须定义它们自己的语法,这样所有和它们的格式特有的语法匹配的字符串也将和<absolute-URI>语法匹配, 如4.3所述.

当一个URI发生了违反一个或多个格式特有的约束的情况, 该格式特有的解析过程应该把该参数标记为一个错误而不是忽略未使用的部分; 这样做减少了相当的URIs的数量并有助于检测对通用语法的滥用, 它可以预示构建的URI把用户带入歧途(7.6).

机构

一些URI schemes包含一个层次元素来描述一个命名的机构,这样由该URI的其他部分定义的命名空间的管理方式就被授予那个机构(它可以相应地进一步授予). 通用语法提供了一个常见方法来基于已注册的名称或服务器地址来区分一个机构, 以及可选的端口和用户信息.

机构部件的前面是一个双斜杠("//")并结束于下一个斜杠("/"), 问号("?"), 或井号("#")字符, 或随着该URI结束.

      authority   = [ userinfo "@" ] host [ ":" port ]

如果端口部件是空的,URI制作者和正规化者应该省略把端口和主机分隔开的 ":" 分隔符. 一些schemes不允许用户信息 和/或 端口子部件.

如果一个URI包含一个机构部件, 那么路径部件必须要么是空的要么以一个斜杠("/")字符开始. 不检查的解析器(那些很少分隔一个URI参数到它的主要部件的解析器)将经常忽略机构的子部件结构, 把从双斜杠到第一个终止分隔符之间的东西当成一个不透明的字符串, 直到该URI被解析的时间.

用户信息

用户信息子部件可以包含一个用户名和, 可选的, 关于如何获得授权访问资源的格式特有的信息. 用户信息, 如果出现, 后面会跟随一个商标("@")以和主机分开.

      userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )

在用户信息字段对格式 "user:password" 的使用已经被废弃了. 应用不应该在一个用户信息子部件中找到的第一个冒号(":")字符后面提出任何明码文本数据,除非在该冒号后面的数据是空字符串(表示没有密码). 当收到作为一个参数的一部分的这样的数据的时候,应用可以选择忽略或拒绝这类数据并且应该拒绝这类数据以未加密方式存储. 以明码方式通过验证信息已经被证明在绝大多数情况使用它是一个安全风险.

为了用户反馈的目的而提供一个URI的应用, 类似图形化的超文本浏览, 应该以某种从一个URI的其他部分区分出来的方式提供用户信息, 在可能的时候. 当发生用户信息已经被手工误导看起来像一个被信任的域名的情况,这类表达可以帮助到用户(7.6).

主机

机构的主机子部件是由一个封装在方括号内的IP文字, 一个点分十进制格式的IPv4地址, 或一个注册名称来标识的. 主机子部件是大小写敏感的. 在一个URI中出现了主机子部件不意味着该格式要求访问互联网上的给定主机. 在一些情况下, 主机语法只被用于重用现有的用于DNS的创建和部署的注册流程, 从而获得一个全局唯一的名称而不用费劲部署另一个注册表. 无论如何, 这种用法有它自己的代价: 域名所有者可能因为URI制作者无法预计的原因而随时变更. 在另外一些情况下, 子部件内的数据标识一个注册名称但没有任何事情要在一个互联网主机上去做. 我们使用ABNF规则的名称 "host" 是因为那是它最常用的目的, 不是它仅有的目的.

      host        = IP-literal / IPv4address / reg-name

主机的语法规则是含糊的,因为不能完全区分一个IPv4地址和一个注册名称. 为了澄清语法, 我们应用 "先匹配者赢" 算法: 如果主机匹配IPv4地址规则, 那么它应该被认为是一个IPv4地址文字而不是一个注册名称. 尽管主机是大小写敏感的, 为了统一的目的制作者和正规化者应该对注册名和十六进制地址使用小写, 只在百分号编码使用大写字母.

由版本6RFC3513或更晚版本的互联网协议文字地址标识的主机, 是通过方括号("[" 和 "]")围起IP文字来区分的. 这是唯一一个被允许在URI语法中出现方括号字符的地方. 在可预见的将来, 还未定义的IP文字地址格式, 实现可以使用一个可选的版本标记来显式地指示这样一个格式而不是依靠启发式的决定.

      IP-literal = "[" ( IPv6address / IPvFuture  ) "]"
 
      IPvFuture  = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )

版本标记不指示IP版本; 而是指示该文字格式的未来版本. 同样的, 实现不能为下面描述的现有的IPv4和IPv6文字地址格式提供该版本标记. 如果一个URI包含一个以 "v" (大小写不敏感)开始的IP-文字, 标识那个版本标记是当前的, 当它由一个不理解该版本标记的含义的应用解参考的时候, 那么该应用返回一个适当的错误 "地址机制不支持".

  A host identified by an IPv6 literal address is represented inside
  the square brackets without a preceding version flag.  The ABNF
  provided here is a translation of the text definition of an IPv6
  literal address provided in [RFC3513].  This syntax does not support
  IPv6 scoped addressing zone identifiers.
  A 128-bit IPv6 address is divided into eight 16-bit pieces.  Each
  piece is represented numerically in case-insensitive hexadecimal,
  using one to four hexadecimal digits (leading zeroes are permitted).
  The eight encoded pieces are given most-significant first, separated
  by colon characters.  Optionally, the least-significant two pieces
  may instead be represented in IPv4 address textual format.  A
  sequence of one or more consecutive zero-valued 16-bit pieces within
  the address may be elided, omitting all their digits and leaving
  exactly two consecutive colons in their place to mark the elision.
     IPv6address =                            6( h16 ":" ) ls32
                 /                       "::" 5( h16 ":" ) ls32
                 / [               h16 ] "::" 4( h16 ":" ) ls32
                 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
                 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
                 / [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
                 / [ *4( h16 ":" ) h16 ] "::"              ls32
                 / [ *5( h16 ":" ) h16 ] "::"              h16
                 / [ *6( h16 ":" ) h16 ] "::"
     ls32        = ( h16 ":" h16 ) / IPv4address
                 ; least-significant 32 bits of address
     h16         = 1*4HEXDIG
                 ; 16 bits of address represented in hexadecimal
  A host identified by an IPv4 literal address is represented in
  dotted-decimal notation (a sequence of four decimal numbers in the
  range 0 to 255, separated by "."), as described in [RFC1123] by
  reference to [RFC0952].  Note that other forms of dotted notation may
  be interpreted on some platforms, as described in Section 7.4, but
  only the dotted-decimal form of four octets is allowed by this
  grammar.
     IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
     dec-octet   = DIGIT                 ; 0-9
                 / %x31-39 DIGIT         ; 10-99
                 / "1" 2DIGIT            ; 100-199
                 / "2" %x30-34 DIGIT     ; 200-249
                 / "25" %x30-35          ; 250-255
  A host identified by a registered name is a sequence of characters
  usually intended for lookup within a locally defined host or service
  name registry, though the URI's scheme-specific semantics may require
  that a specific registry (or fixed name table) be used instead.  The
  most common name registry mechanism is the Domain Name System (DNS).
  A registered name intended for lookup in the DNS uses the syntax


Berners-Lee, et al. Standards Track [Page 20]


RFC 3986 URI Generic Syntax January 2005


  defined in Section 3.5 of [RFC1034] and Section 2.1 of [RFC1123].
  Such a name consists of a sequence of domain labels separated by ".",
  each domain label starting and ending with an alphanumeric character
  and possibly also containing "-" characters.  The rightmost domain
  label of a fully qualified domain name in DNS may be followed by a
  single "." and should be if it is necessary to distinguish between
  the complete domain name and some local domain.
     reg-name    = *( unreserved / pct-encoded / sub-delims )
  If the URI scheme defines a default for host, then that default
  applies when the host subcomponent is undefined or when the
  registered name is empty (zero length).  For example, the "file" URI
  scheme is defined so that no authority, an empty host, and
  "localhost" all mean the end-user's machine, whereas the "http"
  scheme considers a missing authority or empty host invalid.
  This specification does not mandate a particular registered name
  lookup technology and therefore does not restrict the syntax of reg-
  name beyond what is necessary for interoperability.  Instead, it
  delegates the issue of registered name syntax conformance to the
  operating system of each application performing URI resolution, and
  that operating system decides what it will allow for the purpose of
  host identification.  A URI resolution implementation might use DNS,
  host tables, yellow pages, NetInfo, WINS, or any other system for
  lookup of registered names.  However, a globally scoped naming
  system, such as DNS fully qualified domain names, is necessary for
  URIs intended to have global scope.  URI producers should use names
  that conform to the DNS syntax, even when use of DNS is not
  immediately apparent, and should limit these names to no more than
  255 characters in length.
  The reg-name syntax allows percent-encoded octets in order to
  represent non-ASCII registered names in a uniform way that is
  independent of the underlying name resolution technology.  Non-ASCII
  characters must first be encoded according to UTF-8 [STD63], and then
  each octet of the corresponding UTF-8 sequence must be percent-
  encoded to be represented as URI characters.  URI producing
  applications must not use percent-encoding in host unless it is used
  to represent a UTF-8 character sequence.  When a non-ASCII registered
  name represents an internationalized domain name intended for
  resolution via the DNS, the name must be transformed to the IDNA
  encoding [RFC3490] prior to name lookup.  URI producers should
  provide these registered names in the IDNA encoding, rather than a
  percent-encoding, if they wish to maximize interoperability with
  legacy URI resolvers.

端口

路径

查询

片段

个人工具