URL
URL描述了一台特定服务器上某资源的特定位置,它们可以明确说明如何从一个精确、固定的位置获取资源
- URI 本质上是一个字符串,这个字符串的作用是唯一地标记资源的位置或者名字。
- 它不仅能够标记万维网的资源,也可以标记其他的,如邮件系统、本地文件系统等任意资源。而“资源”既可以是存在磁盘上的静态文本、页面数据,也可以是由 Java、PHP 提供的动态服务。
大部分URL都遵循一种标准格式,这种格式包含三个部分:
- 第一部分叫做scheme,告知Web客户端怎样访问资源,比如http://
- 第二部分给出了服务器的因特网地址,告知去哪里找资源,比如www.baidu.com
- 第三部分指定了Web服务器上的某个资源
URL可以通过HTTP之外的其他协议来访问资源,比如FTP获取各种文件:ftp://ftp.www.com/pub/coanyh.xml;比如流视频服务器上访问视频:rtsp://www.abdiu:554/inphuyvideo
URL的语法
URL提供了一种同一的资源命名方式:方案://服务器/资源路径。
URL提供了一种定位因特网上任意资源的手段,但这些资源是可以通过各种不同的方案(比如HTTP/FTP/SMTP)来访问的,因此URL语法会随着方案的不同而不同。
这是不是意味着每种不同的URL方案会有完全不同的语法呢?不对,大部分URL都遵循通用的URL语法: scheme :// hostname[:port] / path / [;parameters][?query]#fragment
方案(scheme):使用什么协议
- URI 第一个组成部分叫scheme,翻译成中文叫“方案
名”或者“协议名”,表示资源应该使用哪种协议来访问。 - 最常见的当然就是“http”了,表示使用 HTTP 协议。另外还有“https”,表示使用经过加密、安全的 HTTPS 协议。此外还有其他不是很常见的 scheme,例如 ftp、ldap、file、news 等。
- 浏览器或者你的应用程序看到 URI 里的 scheme,就知道下一步该怎么走了,会调用相应的 HTTP 或者 HTTPS 下层API。显然,如果一个 URI 没有提供 scheme,即使后面的地址再完善,也是无法处理的。
方案必须以一个字母符号开始,由第一个://
将其与其他URL部分分隔开来。方案是大小写无关的,比如HTTP://
等价于http://
- 实话实说,这个设计非常的怪异,我最早上网的时候看见地址栏里的
://
就觉得很别扭,直到现在也还是没有太适应。URI 的创造者蒂姆·伯纳斯 - 李也曾经私下承认://
并非必要,当初有些“过于草率”了。 - 不过这个设计已经有了三十年的历史,不管我们愿意不愿意,只能接受。
主机与端口
在
://
之后,是被称为“authority”的部分,表示资源所在的主机名,通常的形式是“host:port”,即主机名加端口号。
要想在因特网上找到资源,应用程序要知道是哪台机器上装载了资源,以及什么地方能够找到对目标资源进行访问的服务器。URL的主机和端口组件提供了这两组信息。
- 主机组件:
- 标识了因特网上能够访问资源的宿主主机,可以使用主机名(www.baicu.com)或者IP地址(192.163.0.4)来表示主机名。
- 必须要有,否则浏览器就会找不到服务器。
- 端口组件:
- 标识了服务器正在监听的网络端口。
- 可以省略,浏览器等客户端会依据 scheme 使用默认的端口号,例如 HTTP 的默认端口号是 80,HTTPS 的默认端口号是 443。
用户名和密码
- 有些服务器要求输入用户名和密码才允许用户访问数据,比如FTP服务器:
ftp://oceanstar:password@www.myftp.com/salene.txt
- 但现在已经不推荐使用这种形式了(RFC7230),因为它把敏感信息以明文形式暴露出来,存在严重的安全隐患。
路径
URL的路径组件说明了资源位于什么地方
- URI 的 path 部分必须以“/”开始,也就是必须包含“/”,不要把“/”误认为属于前面 authority
- 可以用字符
/
将HTTP URL的路径组件划分为一些路径段。每个路径段都有自己的参数组件。
例子:
http://23e.baidu.com:80/seacnla/index.html
- 协议名是“http”
- 主机名是“23e.baidu.com”
- 端口号 80
- 路径为
/seacnla/index.html
http://nginx.org/
- 协议名是“http”
- 主机名是“nginx.org”
- 端口号省略,所以是默认的 80
- 路径部分也被省略了,默认就是一个“/”,表示根目录。
file:///D:/http_study/www/
- 它的协议名不是“http”,而是“file”,表示这是本地文件,而后面居然有三个斜杠,这是怎么回事
- 这三个斜杠里的前两个属于 URI 特殊分隔符“
://
”,然后后面的“/D:/http_study/www/”是路径,而中间的主机名被“省略”了。这实际上是 file 类型 URI 的“特例”,它允许省略主机名,默认是本机 localhost。 - 但对于 HTTP 或 HTTPS 这样的网络通信协议,主机名是绝对不能省略的。原因之前也说了,会导致浏览器无法找到服务器
参数
为了向应用程序提供它们所需要的输入参数,以便正确的与服务器进行交互,URL中有一个参数组件。这个组件就是URL中的名值对列表,由字符;
将其与URL的其他部分分隔来,它们为应用程序提供了访问资源所需的所有附加信息。比如:ftp://pro.me.edr/pub.gun:type=d
中,有一个参数type=d,参数名为type,值为d。
如前所述,HTTP URL的路径组件可以分为若干路径段,每段都可以由自己的参数,比如:http://222.baidu.com/nihuiyi;sale=false/index.htnl;grame=true
中,由两个路径段,nihuiyi和index.htnl。nihuiyi路径段有参数sale,index.htnl有参数grame
查询字符串
比如:http://www.aaa.com/iniy/cihu.cgi?item=1244
中,?
右边的内容叫做查询组件。URL的查询组件和标识网关资源的URL路径组件一起被发送给网关资源。
- 常规中,查询字符串以一系列“名/值”对的形式出现,名值对之间用
&
分隔。 - 浏览器和客户端都可以按照这个格式把长串的查询参数解析成可理解的字典或关联数组形式。
实践
浏览器输入http://www.chrono.com:8080/11-1?uid=1234&name=mario&ref
,然后F12查询:
片段
- 查询参数后是片段标识符
#fragment
,它是 URI 所定位的资源内部的一个“锚点”或者说是“标签”,浏览器可以在获取资源后直接跳转到它指示的位置。 - 但片段标识符仅能由浏览器这样的客户端使用,服务器是看不到的。也就是说,浏览器永远不会把带“#fragment”的URI 发送给服务器,服务器也永远不会用这种方式去处理资源的片段。
各种令人头疼的字符
URL是可移植的。它要统一的命名因特网上所有的资源,这也意味着要通过各种不同的协议来传送这些资源。所以,设计URL,使其可以通过任意因特网协议安全的传输是很重要的。
- 在 URI 里只能使用 ASCII 码,但如果要在 URI 里使用英语以外的汉语、日语等其他语言该怎么办呢?
- 还有,某些特殊的 URI,会在 path、query 里出现“@&?"等起界定符作用的字符,会导致 URI 解析错误,这时又该怎么办呢?
所以,URI 引入了编码机制,对于 ASCII 码以外的字符集和特殊字符做一个特殊的操作,把它们转换成与 URI 语义不冲突的形式。这在 RFC 规范里称为“escape”和“unescape”,俗称“转义”
URL字符集
- 默认的计算机系统使用的US-ASCII字符集。
- 但是有些URL还会包含任意的二进制数据。因此,URL的设计者设计了URL支持转义序列。通过转义序列,就可以用US-ASCII字符集的有限自己对任意字符值或数据进行编码了。
编码机制
- 为了避开安全字符集表示法带来的限制,人们设计了一种编码机制,用来在URL中表示各种不安全的字符。
- 这种编码机制就是通过一种转义表示法来表示不安全字符的:直接把非 ASCII 码或特殊字符转换成六进制字节值,然后前面再加上一个“%”。
看例子:
- 空格被转义成“%20”
- “?”被转义成“%3F”。
- 而中文、日文等则通常使用 UTF-8 编码后再转义,例如“银河”会被转义成“%E9%93%B6%E6%B2%B3”
字符限制
在URL中,有几个字符被保留起来,有着特殊的含义。
- 有些字符不在定义的US-ASCII可打印字符集中。
- 有些字符会与某些因特网网关和协议产生混淆,因此不推荐使用。
你可能会感到奇怪,为什么使用一些不安全字符的时候并没有发生什么不好的事情。比如,你可以访问http://www.cde.com/~joe的主页,而无需对~
字符进行编码。对某些传输协议来说,这并不是什么问题,但对应用程序开发人员来说,对非安全字符进行编码仍然是明智的。客户端应用程序在向其他应用程序发送任意URL之前,最好把所有不安全或者受限字符都进行转换。由于有些人会恶意对额外的进行进行编码,所以解释URL的应用程序必须在处理URL之前对其进行解码