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都以方案名称开头,该名称指的是用于解释URI其余部分的规范。方案名称由字母开头,后跟字母、数字、加号("+")、句点(".")或连字符("-")的任意组合。
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
示例:
httphttpsftpmailtofiledatatel
方案名称不区分大小写。规范形式是小写,规范化器应 (SHOULD) 将方案名称转换为小写。
注意: 虽然方案不区分大小写,但生产者和规范化器应 (SHOULD) 使用小写字母。
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地址必须 (MUST) 用方括号括起来。
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. 注册名称 (Registered Name)
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]
主机名规范化: 主机名不区分大小写,应 (SHOULD) 规范化为小写。
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组件包含标识授权范围内资源的数据(或在没有授权的情况下,标识方案范围内资源的数据)。路径由一系列路径段组成,这些段由斜杠("/")字符分隔。
path = path-abempty ; 以 / 开头或为空
/ path-absolute ; 以 / 开头但不是 //
/ path-noscheme ; 以非冒号段开头
/ path-rootless ; 以段开头
/ path-empty ; 零字符
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 = *( 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 | - . _ (注册名) | 其他所有 |
| port | 0-9 | 其他所有 |
| path | : @ ! $ & ' ( ) * + , ; = | 其他所有 |
| query | : @ / ? ! $ & ' ( ) * + , ; = | 其他所有 |
| fragment | : @ / ? ! $ & ' ( ) * + , ; = | 其他所有 |