Skip to main content

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 / "+" / "-" / "." )

示例:

  • http
  • https
  • ftp
  • mailto
  • file
  • data
  • tel

方案名称不区分大小写。规范形式是小写,规范化器应 (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@host
  • user: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

重要特性:

  1. 客户端处理: 片段标识符由客户端处理,不发送到服务器
  2. 文档内导航: 通常用于HTML文档中的锚点
  3. 次要资源: 标识主资源的一部分

示例:

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
组件
schemehttps
userinfouser:pass
hostwww.example.com
port8080
path/path/to/page
querykey=value
fragmentsection

示例2: Mailto URI

mailto:[email protected]?subject=Hello
组件
schememailto
path[email protected]
querysubject=Hello

示例3: File URI

file:///home/user/document.txt
组件
schemefile
authority(空)
path/home/user/document.txt

组件编码规则

不同组件允许不同的字符集:

组件允许的特殊字符必须编码
scheme+ - .其他所有
userinfo: ! $ & ' ( ) * + , ; =其他所有
host- . _ (注册名)其他所有
port0-9其他所有
path: @ ! $ & ' ( ) * + , ; =其他所有
query: @ / ? ! $ & ' ( ) * + , ; =其他所有
fragment: @ / ? ! $ & ' ( ) * + , ; =其他所有