url 编码 保留冒号_URI、URL与URN

关系

URI = Universal Resourcce Identifier

URL = Uniform Resource Locators

URN = Uniform Resource Name

URI、URL与URN都是用来标识某个资源的,其中URI是一个大的概念,URL与URN是它的两个不同的实现,它们三者之间的关系如下图:

ac20bf810ca24cf4f48ed7f0f89f9a5c.png

URL使用'位置'来标识一个资源,类似于现实中的家庭住址。举个例子,比如一个URL为:

http://www.baidu.com/a/b/c.html

就标识出在百度服务器上的路径a下有路径b,路径b下面有c.html文件。

URN通过'名字'来表示一个资源,类似于现实中的身份证号,只要取到身份证号,就能定位到这个号码后面对应的人。

URI的组成

一个URI的标准组成为:scheme authority path query fragment

4c577c8037fa54b778ab476cbd082fe0.png

scheme

组成scheme的字符包括:字母、数字、加号(+)、点(.)、连字符(-),其中scheme的首字符必须是字母,对于scheme的定义,RFC1738与RFC3986是一致的。

scheme的字符必须都是小写,但是在具体实现中,大写的scheme与小写的scheme是等价的,也就是说,HTTP = http。

authority

authority由三部分组成,authority = [userinfo@] host [:port],中括号表示是可选的。

userinfo提供获取这个资源的认证信息,比如用户名、密码,不同部分使用冒号(:)分割。举个例子:

https://username:passport@www.baidu.com:80

https://username@www.baidu.com:80

https://www.baidu.com

都是合法的,也就是说username:passport、:passport、:port这三者是可以任意省略的。

userinfo可以使用的字符集定义如下:

RFC1738

userinfo        =       *[  uchar | ";" | "?" | "&" | "=" | "@" | ":"  ] 

RFC3986

userinfo        =       *[ unreserved | pct-encoded | sub-delims | ":"  ]

* 表示0个或者多个

[ ] 表示可选的,不是必须的

| 表示可以选择其中之一

uchar、unreserved、pct-encoded、sub-delims以及下文出现的字符集范围都定义在文末。

比较RFC1738与RFC3986的定义,两者字符集一致。

host

标识主机名,可以使用的字符集定义如下:

RFC1738

host           = hostname | hostnumber
hostname = *[ domainlabel "." ] toplabel
domainlabel = alphadigit | alphadigit *[ alphadigit | "-" ] alphadigit
toplabel = alpha | alpha *[ alphadigit | "-" ] alphadigit
alphadigit = alpha | digit
hostnumber = digits "." digits "." digits "." digits

RFC3986

host        = IP-literal | IPv4address | reg-name
IP-literal  = "["  IPv6address | IPvFuture   "]"
reg-name    = *[ unreserved | pct-encoded | sub-delims ]

IPvFuture是一种还在开发中的IP地址表示法,详情可以参考RFC3986文档。比较RFC1738与RFC3986的定义,RFC3986定义的host字符集要多于RFC1738

port

是端口号,字符集只能是数字

path

除去其他部分,剩下的就是path部分,path以"/"划分。path可以使用的字符集如下:

RFC1738

urlpath        = *xchar
xchar          = unreserved | reserved | escape

RFC3986

urlpath          =  *pchar

pchar     = unreserved | pct-encoded | sub-delims | ":" | "@"

两者定义的path字符集几乎一样,只是RFC1738比RFC3986多了一个?。但是问号被用来作为query起始的标志,所以?是不会被算进path里面的,从这个意义上说,这两者定义的path字符集一样。

query

表示查询字符串,从第一个问号(?)开始,到第一个井号(#)之间就是query。query可以使用的字符集定义如下:

query         = *[ uchar | ";" | ":" | "@" | "&" | "=" ]
uchar         = unreserved | escape
query       = *[ pchar | "/" | "?" ]

RFC1738定义的字符集比RFC3986定义的字符集少了一个"/",但是iOS中NSURL虽然遵循RFC1738,也把"/"当成是正常的字符。

fragment

通常用来定位到一个文档中的某个部分,从第一个井号(#)后面开始都是fragment。fragment定义的字符集与query一样。

URL字符编码

URL有时需要对字符进行编码,编码格式为:百分号 + HEX  + HEX,比如逗号(,)被编码成%2C。编码的时,对于十六进制中的字母,大写和小写是等价的。也就是说,两个URL,不会因为编码使用的大小写不一样就是两个不一样的URL。

在URL里面,字符需要编码的情形有3种。

1 不可打印的字符

组成URL的字符都是可打印的ASCII字符,对于无法进行打印的字符(ASCII区间为:0x00-0x1F、0x7F)需要进行编码。

2 不安全的字符需要编码

有些字符使用起来并不安全,比如空格,在URL里面就需要进行编码。RCF1738里面规定的不安全字符有:

空格   |    ">"   |   "

需要注意的是,像%、#并不是在URL的任何地方都需要编码,比如作为fragment标识的时候,#就无需编码,但是如果#出现在其他地方,就需要编码了。

在上面的字符集需要注意的是"[" "]"两个字符,iOS中NSURL遵循RFC1738,但是这两个字符集即使不编码,也可以出现在除了scheme的任何地方,NSURL正常返回;但是对于遵循RFC3986的NSURLComponents来说,除了以IPV6的形式表示host之外,"[" "]"不能出现在任何其他地方。

3 保留字符集

RFC1738和RFC3986规定的reserve保留字符集,如果你确实是想使用这些保留字符集本身,而不是它们在URL里面的特殊意义,那么最好是将它们编码。

字符集定义

RFC1738

lowalpha       = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" |
"i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" |
"q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" |
"y" | "z"
hialpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |
"J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
"S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
alpha          = lowalpha | hialpha
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
"8" | "9"
safe = "$" | "-" | "_" | "." | "+"
extra = "!" | "*" | "'" | "(" | ")" | ","
hex            = digit | "A" | "B" | "C" | "D" | "E" | "F" |
"a" | "b" | "c" | "d" | "e" | "f"
escape = "%" hex hex
unreserved = alpha | digit | safe | extra
uchar = unreserved | escape
xchar = unreserved | reserved | escape
reserved       = ";" | "/" | "?" | ":" | "@" | "&" | "="

RFC3986

reserved    = gen-delims | sub-delims
gen-delims = ":" | "/" | "?" | "#" | "[" | "]" | "@"
sub-delims = "!" | "$" | "&"| "'"| "(" / ")"
| "*" | "+" | "," | ";"| "="
unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded = "%" HEXDIG HEXDIG ;即百分号编码格式

参考资料

https://tools.ietf.org/html/rfc1738#section-3.3

https://www.ietf.org/rfc/rfc3986.txt

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值