从毕业到工做都一年多了,在这一年多的时间里,我发现有的后台程序员连 URL 的查询参数都不知道,再加上最近使用 node 和 python 链接加密的 mongodb 时也遇到了点问题,就决定对我所知道的 URL 方面知识作一个总结。javascript
URL 是 Uniform Resource Location 的缩写,译为“统一资源定位符”。通俗地说, URL 是 Internet 上用来描述信息资源的字符串,主要用在各类 www 客户程序和服务器程序上。采用URL能够用一种统一的格式来描述各类信息资源,包括文件、服务器的地址和目录等。css
顺便也提一下 URI 吧:html
Web上可用的每种资源 - HTML文档、图像、视频片断、程序等 - 由一个经过通 用资源标志符(Universal Resource Identifier, 简称"URI")进行定位。前端
URI通常由三部分组成:java
URL 是 URI 的子集,可是平时的开发中咱们只须要了解 URL 就能够了。node
以 http://test.com:8080/example/index.html
为例进行说明。python
URL的格式由下列三部分组成:linux
HTTP 协议
。test.com:8080
。平时看到的都是域名,以后客户端会经过DNS(域名系统) 查询域名对应的 IP,而后根据IP和端口号进行服务器的链接。稍后会对此进行详细说明。/example/index.html
。<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
nginx
key=value
。window.location.hash
)。这只是通用语法,大多数的 URL 都只遵循了一部分而已,并非每种URL都会有上面的全部信息。git
从上面的语法咱们能够看出至少 :/@;?# 都是敏感字符,因此在其余参数中不能包含这些字符,若是含有敏感字符或者特殊字符,就须要使用对应的转义字符,不然可能会发生不可预料的结果。 在开发过程当中,容易在查询参数中含有 敏感字符,因此查询字符串的值通常都须要使用 encodeURIComponent
进行编码。
http://test.com:8080/user/index.html?id=1&nickName=test#/list
在浏览器中被解析后的格式为:
{
protocol: 'http:', // 协议
host: 'test.com:8080', // 主机名或域名,带端口号
hostname: 'test.com', // 主机名或域名,不带端口号
port: '', // 端口号,http默认80,https默认443
path: '/user/index.html', // 路径
query: '?id=1&nickName=test', // 查询字符串
hash: '#list', //片断或者哈希,
}
复制代码
注意: #后面的东西都不会从客户端传到服务器。
在地址栏中改变 # 后的字符串时,页面并不会刷新,可是会出发 hashchange 事件,不少前端路由的 hash 模式就是根据这种特性实现的。而改变出了frag(hash)
以外的东西都会致使浏览器刷新,由于此时至关于向服务器发出了一个新的请求。
文件传输协议,能够用来从服务器下载或上传文件。
基本格式:
ftp://<user>:<password>@<host>:<port>/<path>;<params>
示例:
ftp://ftpuser:123456.com@test.com:21/path/example
该协议常见于本地文件于浏览器中打开的场景,也多是网络文件系统或者其余一些文件共享系统。这个我就不细说了,感受没啥可说的。
常见于后台程序链接 mongodb 数据库。虽然咱们常见的包都是用对象格式来链接数据库的,可是最后都会被转化为字符串形式的。
基本格式:
mongodb://<user>:<password>@<host>:<port>/<path>?<query>
示例:
mongodb://test:123456@127.0.0.1:27017/novel?authSource=admin
该字符串表示以 mongodb 协议,用户名为test,密码为123456,数据库dbName为novel,验证的数据库为admin,链接至127.0.0.1主机的27017端口。
注意:如mongodb服务器没有开启加密,须要去掉查询参数,不然会链接失败。若开启了加密,authSource的值必须和前方的user和password相对应。,不然用户验证页没法链接。 我用的thinkjs,一开始没有配置 authSource,给我报的错误是链接超时,当时还纳闷远程的服务器再慢也不至于吧???后来调整了超时时间,发现仍是超时,并且一直在尝试从新链接,就想到了多是验证失败了,这个纠结了很多时间。
整个流程以下:
其实,域名解析这个过程要是细说的话仍是有点复杂的,总之有时候也是蛮耗时的,毕竟从 解析 这个用词咱们就能看出它必定是须要时间的?经过DNS会将域名解析为 IP,以后会根据 IP 和 端口链接服务器。
若是咱们直接用IP访问服务器,就能够节省一部分时间,但仍是不建议你们这么作,由于若是更换了服务器的话,域名能够解析到另外一个IP,能够在浏览器端保留相应的数据,而IP就不行了。还有就是,域名的可访问性和可读性可比IP强多了。
上面的大部分都只适用于静态服务器,若是是动态服务器的话,它会有本身的一套解析规则,可是大体上也是相同的,最大的区别可能仍是动态服务器的动态路由吧(前端路由如今也支持动态路由了)。
下面主要就说一下动态服务器相对于静态服务器的特殊点:
好比定义一个获取某我的的信息的接口,它的路径为:{ path: '/user/:id' }
当访问 /user/1?name=test
时,该接口将被框架解析为:
{
params: {
id: 1,
},
query: {
name: 'test',
}
}
复制代码
若是是静态路由的话,只能使用 /user?id=1&name=test
这种方式来传递参数了,从这能够看出动态路由在必定程度上仍是比静态路由有一点优点的;并且动态路由看上去更优雅。
可是若是后台对路由的定义很差,前端传过去的参数为空的话,动态路由就会变成 /user/
,访问到的接口就不是 /user/:id
这个路由,而是 /user/
这个接口了,后台差找不到该路由,直接就返回 404 或者自定义的错误了。
我接触过的后台框架有 ThinkPHP 和 thinkjs, 这两个仍是比较类似的,它们都有一个特性就是可以进行路由重写,好比在定义好的路由以后加上后缀,若是设置 ext: '.html'
,那么访问 /user/1.html
时将被解析为 /user/:id
,在那些先后端还未分离的公司,这个应该是主要的页面输出方式了(记得不知道从哪看到的这样好像有利于SEO优化?)。
因此之后在看到 http://test.com/user/1.html
这样的 URL的时候,就不能再单纯的认为它必定指向服务器的某个静态文件,它如今也多是通过模板渲染以后的一个响应。
说了点动态服务器的,那就再说一点静态服务器的吧,由于我遇到的一个后台,在前端上传文件后,直接把文件存储到linux系统的根目录,而后在域名后面把文件的路径拼上去,还纳闷怎么就是访问不到呢?
经常使用的静态服务器是 nginx,设置一下静态文件的压缩啦,缓存啦,代理啦,识别设备进行跳转,图片裁剪之类的,都是so easy,简直就是咱们大前端的标配嘛。
流行一点的web服务器主要是 nginx, apache,tomcat,后两个主要仍是用于搭配后台使用,不直接向外暴露接口的。这些静态服务器都会有一个配置用于设置 web 服务器的根目录,那么这个根目录的做用是什么呢?就是控制客户端能访问到的顶级目录。 好比根目录是 www,是不能访问 www 目录之外的其余文件的,只能访问 www 的子目录的各文件。