3. 语法组件 (Syntax Components)
通用 URI 语法由一组层次化组件组成, 分别称为方案 (scheme), 授权 (authority), 路径 (path), 查询 (query) 和片段 (fragment).
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
hier-part = "//" authority path-abempty
/ path-absolute
/ path-rootless
/ path-empty
组件结构示例:
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
| _____________________|__
/ \ / \
urn:example:animal:ferret:nose
以下各节详细描述每个组件.
3.1. 方案 (Scheme)
每个 URI 都以方案名称开始, 方案名称指向用于在该方案内分配标识符的规范. 方案名称由一串字符组成, 以字母开头, 后面跟随字母, 数字, 加号 ("+"), 句点 (".") 或连字符 ("-") 的任意组合.
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
示例:
httphttpsftpmailtofiledatatel
方案名称不区分大小写. 规范形式为小写, 规范化器应当将方案名称转换为小写.
注: 虽然方案不区分大小写, 生成者和规范化器仍应使用小写字母.
3.2. 授权 (Authority)
授权组件由可选的用户信息子组件, 主机子组件和可选的端口子组件组成, 并以前导的两个斜杠 ("//") 引入.
authority = [ userinfo "@" ] host [ ":" port ]
完整示例:
user:[email protected]:8080
\__________/ \______________/ \__/
userinfo host port
3.2.1. 用户信息 (User Information)
userinfo 子组件可以由用户名组成, 也可以可选地包含特定于方案的信息, 用于说明如何获得访问资源的授权.
userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
示例:
user@hostuser:password@host(已弃用, 存在安全风险)anonymous@host
安全警告: 在 URI 中包含密码已被弃用, 因为密码可能暴露在日志, 历史记录等位置.
3.2.2. 主机 (Host)
host 子组件可以是注册名称 (包括但不限于主机名), 也可以是 IP 地址. IPv6 地址必须括在方括号中.
host = IP-literal / IPv4address / reg-name
IP-literal = "[" ( IPv6address / IPvFuture ) "]"
IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
reg-name = *( unreserved / pct-encoded / sub-delims )
主机类型示例:
1. 注册名称
www.example.com
example.org
localhost
2. IPv4 地址
192.0.2.1
127.0.0.1
3. IPv6 地址
[2001:db8::1]
[::1]
[fe80::1]
4. 未来 IP 版本
[v9.abc:def]
主机规范化: 主机名不区分大小写, 应当规范化为小写.
3.2.3. 端口 (Port)
port 子组件是可选的, 并以十进制数字表示.
port = *DIGIT
示例:
http://example.com:80/(HTTP 默认端口)https://example.com:443/(HTTPS 默认端口)http://example.com:8080/(自定义端口)
默认端口: 如果端口为空或未给出, 则假定使用该方案的默认端口.
3.3. 路径 (Path)
path 组件包含用于在 URI 方案和命名授权范围内标识资源的数据, 并与 query 组件中的数据共同发挥作用. 路径由斜杠 ("/") 字符分隔的一系列路径段组成.
path = path-abempty ; begins with "/" or is empty
/ path-absolute ; begins with "/" but not "//"
/ path-noscheme ; begins with a non-colon segment
/ path-rootless ; begins with a segment
/ path-empty ; zero characters
path-abempty = *( "/" segment )
path-absolute = "/" [ segment-nz *( "/" segment ) ]
path-noscheme = segment-nz-nc *( "/" segment )
path-rootless = segment-nz *( "/" segment )
path-empty = 0<pchar>
segment = *pchar
segment-nz = 1*pchar
segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
路径类型示例:
1. 绝对路径
/path/to/resource
/index.html
/
2. 相对路径
path/to/resource
../parent/resource
resource
3. 空路径
http://example.com
路径段: 路径由斜杠分隔的段组成. 特殊段包括:
.(当前目录)..(父目录)
3.4. 查询 (Query)
query 组件包含非层次化数据, 并与 path 组件中的数据共同用于标识资源. query 组件由问号 ("?") 引入.
query = *( pchar / "/" / "?" )
查询字符串示例:
?key=value
?name=John&age=30
?search=hello+world
?filter[]=a&filter[]=b
?q=%E4%BD%A0%E5%A5%BD
常见格式: 虽然 URI 规范没有定义查询字符串格式, 但以 & 分隔的 key=value 对已经成为事实标准:
?key1=value1&key2=value2&key3=value3
3.5. 片段 (Fragment)
fragment 组件允许间接标识由 URI 所标识资源的表示中的次级资源. 片段标识符由井号 ("#") 引入.
fragment = *( pchar / "/" / "?" )
片段示例:
#section1
#top
#chapter-3
#line-42
重要特性:
- 客户端处理: 片段标识符由客户端处理, 不会发送到服务器.
- 文档内导航: 常用于 HTML 文档中的锚点.
- 次级资源: 标识主资源的一部分.
示例:
http://example.com/page.html#section2
- 服务器接收:
http://example.com/page.html - 客户端导航到:
#section2
URI 组件摘要
| 组件 | 前缀 | 必需 | 示例 | 描述 |
|---|---|---|---|---|
| scheme | - | 是 | http | 协议/方案 |
| authority | // | 否 | user@host:port | 授权信息 |
| path | - | 是* | /path/to/resource | 资源路径 |
| query | ? | 否 | key=value | 查询参数 |
| fragment | # | 否 | section1 | 片段标识符 |
*路径可以为空.
完整 URI 示例拆解
示例 1: HTTP URL
https://user:[email protected]:8080/path/to/page?key=value#section
| 组件 | 值 |
|---|---|
| scheme | https |
| userinfo | user:pass |
| host | www.example.com |
| port | 8080 |
| path | /path/to/page |
| query | key=value |
| fragment | section |
示例 2: Mailto URI
mailto:[email protected]?subject=Hello
| 组件 | 值 |
|---|---|
| scheme | mailto |
| path | [email protected] |
| query | subject=Hello |
示例 3: File URI
file:///home/user/document.txt
| 组件 | 值 |
|---|---|
| scheme | file |
| authority | (空) |
| path | /home/user/document.txt |
组件编码规则
不同组件允许不同的字符集:
| 组件 | 允许的特殊字符 | 必须编码的字符 |
|---|---|---|
| scheme | + - . | 其他所有字符 |
| userinfo | : ! $ & ' ( ) * + , ; = | 其他所有字符 |
| host | - . _ (reg-name) | 其他所有字符 |
| port | 0-9 | 其他所有字符 |
| path | : @ ! $ & ' ( ) * + , ; = | 其他所有字符 |
| query | : @ / ? ! $ & ' ( ) * + , ; = | 其他所有字符 |
| fragment | : @ / ? ! $ & ' ( ) * + , ; = | 其他所有字符 |
下一章: 4. URI 引用 (URI Reference) - URI 引用和相对引用