浅谈HTTP之URL

背景介绍

从毕业到工做都一年多了,在这一年多的时间里,我发现有的后台程序员连 URL 的查询参数都不知道,再加上最近使用 node 和 python 链接加密的 mongodb 时也遇到了点问题,就决定对我所知道的 URL 方面知识作一个总结。javascript

何为URL

名词解释

URL 是 Uniform Resource Location 的缩写,译为“统一资源定位符”。通俗地说, URL 是 Internet 上用来描述信息资源的字符串,主要用在各类 www 客户程序和服务器程序上。采用URL能够用一种统一的格式来描述各类信息资源,包括文件、服务器的地址和目录等。css

顺便也提一下 URI 吧:html

Web上可用的每种资源 - HTML文档、图像、视频片断、程序等 - 由一个经过通 用资源标志符(Universal Resource Identifier, 简称"URI")进行定位。前端

URI通常由三部分组成:java

  • 访问资源的命名机制。
  • 存放资源的主机名。
  • 资源自身的名称,由路径表示。

URL 是 URI 的子集,可是平时的开发中咱们只须要了解 URL 就能够了。node

URL格式

http://test.com:8080/example/index.html为例进行说明。python

URL的格式由下列三部分组成:linux

  • 第一部分是协议(或称为服务方式),本例中为HTTP 协议
  • 第二部分是存有该资源的主机IP地址或域名(有时也包括端口号),本例中为 test.com:8080。平时看到的都是域名,以后客户端会经过DNS(域名系统) 查询域名对应的 IP,而后根据IP和端口号进行服务器的链接。稍后会对此进行详细说明。
  • 第三部分是主机资源的具体地址,如目录和文件名等,本例中为 /example/index.html

URL 的语法

通用语法

<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>nginx

  • scheme: 协议,常见的有 http(80),https(443),mailto,ftp(21),rtsp,rtspu,file。
  • user:用户名。
  • password: 密码。
  • host:主机。
  • port: 端口。
  • params: 参数。一般为 key=value
  • query:查询参数或查询字符串。
  • frag: 片断(在浏览器中会被解析为 window.location.hash)。

这只是通用语法,大多数的 URL 都只遵循了一部分而已,并非每种URL都会有上面的全部信息。git

从上面的语法咱们能够看出至少 :/@;?# 都是敏感字符,因此在其余参数中不能包含这些字符,若是含有敏感字符或者特殊字符,就须要使用对应的转义字符,不然可能会发生不可预料的结果。 在开发过程当中,容易在查询参数中含有 敏感字符,因此查询字符串的值通常都须要使用 encodeURIComponent进行编码。

http(s)中的语法

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中的语法

文件传输协议,能够用来从服务器下载或上传文件。

基本格式:

ftp://<user>:<password>@<host>:<port>/<path>;<params>

示例:

ftp://ftpuser:123456.com@test.com:21/path/example

file中的语法

该协议常见于本地文件于浏览器中打开的场景,也多是网络文件系统或者其余一些文件共享系统。这个我就不细说了,感受没啥可说的。

mongodb协议

常见于后台程序链接 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,给我报的错误是链接超时,当时还纳闷远程的服务器再慢也不至于吧???后来调整了超时时间,发现仍是超时,并且一直在尝试从新链接,就想到了多是验证失败了,这个纠结了很多时间。

在浏览器中输入URL后,执行的所有过程

整个流程以下:

  1. 域名解析;
  2. 发起TCP的3次握手;
  3. 创建TCP链接后发起http请求;
  4. 服务器响应htp请求;
  5. 浏览器解析htm代码,并请求html代码中的资源(如js、css、图片等);
  6. 断开TCP链接;
  7. 浏览器对页面进行渲染呈现给用户。

其实,域名解析这个过程要是细说的话仍是有点复杂的,总之有时候也是蛮耗时的,毕竟从 解析 这个用词咱们就能看出它必定是须要时间的?经过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系统的根目录,而后在域名后面把文件的路径拼上去,还纳闷怎么就是访问不到呢?

甘拜下风

web服务器的根目录

经常使用的静态服务器是 nginx,设置一下静态文件的压缩啦,缓存啦,代理啦,识别设备进行跳转,图片裁剪之类的,都是so easy,简直就是咱们大前端的标配嘛。

话虽然这么说,如今的公司仍是把个人前端文件放在tomcat容器下,并无给我一个专属的 nginx 服务器,o(╥﹏╥)o。每次改完文件我得先打包成压缩包,发给后台,他放到 tomcat 容器下,而后再上传至服务器,重启容器,最后缓存没控制好,压缩也没搞。重启以后还得怀疑一下个人文件是否是发错了,这文件怎么没更新???其实用 nginx,再搭配 git 的 hooks,几个命令行的事而已嘛,扯远了,仍是说说 web服务器的根目录吧。

流行一点的web服务器主要是 nginx, apache,tomcat,后两个主要仍是用于搭配后台使用,不直接向外暴露接口的。这些静态服务器都会有一个配置用于设置 web 服务器的根目录,那么这个根目录的做用是什么呢?就是控制客户端能访问到的顶级目录。 好比根目录是 www,是不能访问 www 目录之外的其余文件的,只能访问 www 的子目录的各文件。

参考连接

相关文章
相关标签/搜索