2. 标准化结构化 URI 的当前最佳实践
本节通过建议 Specifications 如何在 URI 内定义结构和语义来更新 [RFC3986]. 当前最佳实践会因所涉及的 URI 组件而异, 如下所述.
2.1. URI Schemes
Applications 和 Extensions 可以要求使用一个或多个特定 URI schemes. 例如, 要求某个 Application 支持 "http" 和 "https" URI 是完全可以接受的. 然而, 除非这些 Applications 明确只能与所指定的 schemes 一起使用, 否则它们不应排除将来使用其他 URI schemes.
如果某个 Specification 为 URI schemes 整体定义子结构 (例如 URI scheme 名称的前缀或后缀), 它 MUST 通过修改 [BCP35] 来完成 (这属于例外情况).
2.2. URI Authorities
Scheme definitions 定义 URI 中 authority 组件的存在性, 格式和语义. 所有其他 Specifications MUST NOT 约束或定义 URI authorities 的结构或语义, 除非它们更新 scheme 注册本身或其所依赖的结构 (例如 [RFC1034] Section 3.5 中定义的 DNS 名称语法).
例如, 除非某个 Extension 或 Application 更新 "http" URI scheme 或 DNS 主机名语法, 否则它不能说 "https://foo_app.example.com" 中的 "foo" 前缀在 URI 中有意义或触发特殊处理.
在适用时, Applications 可以指定或约束它们使用的端口. 例如, BarApp 可以运行在端口 nnnn 上 (前提是它已被正确注册).
2.3. URI Paths
Scheme definitions 定义 URI 中 path 组件的存在性, 格式和语义, 尽管在给定部署中这些内容通常会委托给 Application(s).
为避免冲突, 刚性和错误的客户端假设, Specifications MUST NOT 为其 URI paths 定义固定前缀, 例如 "/myapp", 除非 scheme definition 允许这样做.
此要求的一个例外是已注册的 "well-known" URI, 如 [RFC8615] 所规定. 关于该机制适用性的说明, 请参见该文档.
注意, 这不适用于 Applications 在服务器控制的资源 "之下" 定义 URI path 结构. 由于前缀处于部署该 Application 的一方控制之下, 因而避免了冲突和刚性, 同时降低了错误客户端假设的风险.
例如, 某个 Application 可以将 "app_root" 定义为由部署控制的 URI 前缀. 随后可假定该 Application 定义的资源存在于 "{app_root}/foo" 和 "{app_root}/bar".
Extensions MUST NOT 在单个 URI 组件内部定义结构 (例如前缀或后缀), 同样是为了避免冲突和错误的客户端假设.
2.4. URI Queries
URI 的 query 组件的存在性, 格式和语义取决于许多因素, 并且可由 scheme definition 约束. 它们通常由资源自身的实现决定.
Applications 可以为其控制下的资源指定 queries 的语法. 然而, 这样做可能给不支持特定 query 形式的部署带来操作困难. 例如, 某个站点可能希望使用不支持 query 参数的 "static" 文件来支持某个 Application.
Extensions MUST NOT 约束 queries 的格式或语义, 以避免冲突和错误的客户端假设. 例如, 如果某个 Extension 指出所有名为 "sig" 的 query 参数都表示加密签名, 这将与站点上可能已经存在的 query 参数发生冲突, 并导致客户端假定任何匹配的 query 参数都是签名.
根据 [HTML5] 的 "Form submission" 一节, HTML 约束了表单提交中使用的 query strings 的语法. 鼓励新的表单语言允许创建更广泛种类的 URI (例如, 允许表单创建新的 path 组件等).
2.5. URI Fragment Identifiers
[RFC3986] Section 3.5 指定 fragment identifiers 的语法和语义取决于潜在获取资源的 media type. 因此, 其他 Specifications MUST NOT 在 fragment identifier 内定义结构, 除非它们明确是在定义一种供 media types 在其定义中重用的结构 (例如 JSON Pointer [RFC6901] 所做的那样).
如果某个 Application 在其未控制的多个 media types 上定义通用 fragment identifiers, 将会给这些 media types 的处理程序带来互操作性问题 (因为它们并不预期这种新的非标准语法).