继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

前端开发工程师应该知道的http协议知识

种子_fe
关注TA
已关注
手记 28
粉丝 84
获赞 479

从访问网页简单理解互联网数据交换的整个过程 这篇手记里讲到了从输入url到看到网页的整个过程,这实际上也是从发送http请求到接收到http响应的过程中在更底层所发生的事,在这么多互联网协议中,我们前端工程师接触最多的就是应用层的浏览器程序和应用层的http协议,资源缓存、CDN加载,页面性能调优都离不开对http协议的了解,所以,对http协议有必要深入学习。

在Firefox浏览器中打开firebug,在地址栏中输入:http://demo-bootstrap-blog.herokuapp.com/,就打开了网页,在firebug的网络面板,可以看到如下内容:
firebug网络面板显示http请求

这里可以看到页面加载完成之前所有的http请求基本信息,包括请求内容,响应状态,所请求的域,以及每个请求所消耗的时间等。时间线部分的信息有助于性能优化,可以看到每个请求的耗时,从而判断哪些请求耗时过长,需要优化,这里可以看到,由于我自己的style.css和script.js文件都没有进行压缩,体积较大,而且也没有用cdn,所以请求耗时是比较长的。前端更详细的性能优化方面的建议可以通过雅虎的Yslow获得,这里也要推荐一下慕课网的Yahoo军规课程,这门课也能促进对http协议的理解。

点击每个http请求还能看到每个请求和响应的详细信息,包括请求头,请求体,响应头,响应体等。

为了了解http请求和响应的详细信息,我看了一些资料,这里放上我这几天初步学习http协议的总结,希望对初学前端的同学有帮助。

http协议的概念

http是HyperText Transfer Protocol的缩写,也称为超文本传输协议,最初的版本只能用来传输html文件,现在则可以传输包括文字、图像、视频和二进制文件的所有内容。

HTTP客户端(这里就是我们的浏览器)发起一个请求,创建一个到服务器指定端口(默认是80端口)的TCP连接。HTTP服务器则在那个端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态,比如"HTTP/1.1 200 OK",以及返回的内容,如请求的文件、错误消息、或者其它信息。

http消息的结构

request消息的结构

Method | path to resource | http/version number
-----------------------------------------------
Header name 1: value 
Header name 2: value
  ...
-----------------------------------------------

-----------------------------------------------
request body(optional)

可以看到http请求分为三个部分:

  • 第一部分是request line,包括请求的方法Method(GET/POST)、请求资源的路径path to resource(对应后端路由部分定义的路径)和http协议的版本号。
  • 第二部分是request header请求头
  • 第三部分是request body请求体,当使用GET方法发送请求的时候,请求体是空的

response消息的结构

http/version number | status code | message
-----------------------------------------------
Header name 1: value
header name 2: value
...
-----------------------------------------------

-----------------------------------------------
response body(optional)

可以看到http响应也分为三个部分:

  • 第一部分是response line,包括http协议版本号,响应状态码和响应状态消息
  • 第二部分是response header响应头
  • 第三部分是响应体

还是以这个项目为实例来看看具体的http请求是怎样的,这里要用到fiddler这个web调试工具,慕课网上的fiddler课程就不错,我就是照着学习的。

打开项目主页,在fiddler的Inspectors tab下以Raw的方式可以看到完整的Request和Response消息:

GET http://demo-bootstrap-blog.herokuapp.com/ HTTP/1.1
-----------------------------------------------
Host: demo-bootstrap-blog.herokuapp.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:49.0) Gecko/20100101 Firefox/49.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: connect.sid=s%3AjmSn4Kj6_JgGbVHrlzErYY_Z0deJ-vN7.sIoDv8fCqGfOr4O5o7q%2BZrCC0MaPiyX5q%2BPUIGU5Bxs
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache

这里因为是GET请求,所以只有request line 和request header部分。

HTTP/1.1 200 OK
-----------------------------------------------
Server: Cowboy
Connection: keep-alive
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 5780
Etag: W/"1694-tmfktg3QbjE3Ve+kl9Epsw"
Date: Mon, 07 Nov 2016 08:00:10 GMT
Via: 1.1 vegur
-----------------------------------------------

-----------------------------------------------
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8" />
...
</body>
</html>

这里响应的状态码是200、状态消息是ok,响应体的内容是页面html(比较长,这里就省略了)。

GET和POST的区别

GET和POST是我们最常用的两种请求方法,它们有几点不同:

  • GET请求是为了从服务器获取内容,在需要提交数据的情况下,提交的数据会作为querystring放在URL之后,以?分割URL和querystring,querystring也只是为了获取内容所发送的参数;POST请求是为了向服务器发送内容(比如表单),会把提交的数据放在HTTP包的request body中。
  • GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制。
  • 在express框架中,对于GET请求的参数’?xxxx=’,使用req.query.xxxxx方法获得;对于POST请求的参数,使用req.body.xxxxx方法获得
  • GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码。

http响应状态码

状态码主要用来表示响应的状态,根据状态码可以判断响应是否如预期。

HTTP/1.1中定义了5类状态码, 状态码由三位数字组成,第一个数字定义了响应的类别

1XX 提示信息类 - 表示请求已被成功接收,继续处理

2XX 响应成功类 - 表示请求已被成功接收,理解,接受

3XX 重定向类 - 要完成请求必须进行更进一步的处理

4XX 客户端错误类 - 请求有语法错误或请求无法实现

5XX 服务器端错误类 - 服务器未能实现合法的请求

状态码有很多,不过一开始只需要掌握一些比较常见的:

  • 200 ok: 最常见的就是成功响应状态码200了, 这表明该请求被成功地完成,所请求的资源发送回客户端。上面打开项目主页的实例中就是200
  • 304 not modified: 假如我们打开主页后在浏览器中刷新,就会看到响应的状态码变成了304,这代表之前响应的html文档已经被缓存了,服务器端相同的文档没有变化,可以继续使用缓存的文档,因此304响应没有response body部分
  • 302 found: 重定向,新的URL会在response header中的Location中返回,浏览器将会自动使用新的URL发出新的Request,假如我们在登录页提交登录表单发送一个POST请求进行登录,就会得到一个302响应并且重定向到/index路径下
  • 404 not found: 请求资源不存在(输错了URL,或者服务器端现在没有这个页面了)
  • 500 Internal Server Error: 服务器发生了不可预期的错误,这个一般在会在服务器的程序代码出错时发生

http请求头和响应头详解

request line和response line部分给出的只是请求和响应最最基本的信息,我们还需要了解请求头和响应头部分的内容。

使用Fiddler 能很方便的查看Request(Response) header, 点击Inspectors tab ->Request(Response) tab-> headers可以看到分类整理过的头域。

这里还是介绍一些常用的header,request header和response header中有些域是有对应关系的,就放在一起讲解

缓存相关

  • If-Modified-Since和Last-Modified:If-Modified-Since的值是浏览器端缓存内容的最后修改时间,属于请求头,Last-Modified的值是服务器端资源的最后修改时间,属于响应头,If-Modified-Since的值发送到服务器去,服务器会把这个时间与服务器上实际文件的Last-Modified的值进行对比。如果时间一致,那么返回304,客户端就直接使用本地缓存文件。如果时间不一致,就会返回200和新的文件内容。客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示在浏览器中。

    例子:If-Modified-Since: Thu, 03 Nov 2016 14:54:11 GMT & Last-Modified: Thu, 03 Nov 2016 14:54:11 GMT

  • If-None-Match和Etag:Etag是服务器端对于某个资源的某个特定版本的一个标识符,浏览器初次请求某个资源时,服务器http响应头中会添加一个Etag信息,当浏览器再次请求该资源时,会在request header中加入If-None-Match,其值就是之前收到的Etag值,如果服务器验证资源的ETag没有改变(该资源没有更新),将返回一个304状态告诉客户端使用本地缓存文件。否则将返回200状态和新的资源和Etag。

    例子:If-None-Match: W/“162c-1582aaed638” & Etag: W/“162c-1582aaed638”

客户端相关

  • Accept:请求头,规定请求可以接受的媒体类型,例子:Accept: text(大类)/html(子类),代表可以接受的响应内容类型为html

  • Accept-Encoding和Content-Encoding:Accept-Encoding表示接受的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法,是请求头,Content-Encoding表示WEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应体中的内容,属于响应头。

    例子:Accept-Encoding: gzip, deflate & Content-Encoding: gzip

  • Accept-Language和Content-Language:请求接受的语言和响应数据的语言,例子:Accept-Language: zh-CN & Content-Language: zh-CN

  • User-Agent:用户代理,告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本,

    例子:Mozilla/5.0 (Windows NT 10.0; rv:49.0) Gecko/20100101 Firefox/49.0

Entity头域

  • Content-Type和Content-Length:只用于响应头或者POST请求的请求头,Content-Type表示请求体或者响应体内容的MIME类型(互联网媒体类型),Content-Length则表示请求体或者响应体内容的长度,以字节为单位,每个字符都是一个字节。

    例子:在这个项目里,输入用户名和密码,提交登录表单会发送一个请求体为用户名和密码的POST请求,服务器返回一个302 found的响应,页面跳转到/index路径下,在fiddler中看请求头和响应头的这两个域分别为:

    //请求头
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 28
    -----------------------------------------------
    //响应头
    Content-Type: text/html; charset=utf-8
    Content-Length: 56
    

    其中请求头Content-Type中application代表POST请求体以二进制发送,x-www-form-urlencoded代表是使用HTTP的POST方法提交的表单。

Miscellaneous 头域

  • Referer:请求头,提供了Request的上下文信息的服务器,告诉服务器我是从哪个链接过来的

    例子:比如上面登录后跳转到/index路径的请求头中Referer: http://demo-bootstrap-blog.herokuapp.com/

  • Server:响应头,源服务器处理请求的软件的信息,例子:Server: Cowboy,Cowboy是Erlang编写的WebServer

  • X-Powered-By:响应头,表示网站是用什么技术开发的,例子:X-Powered-By: Express

Location头域

  • Location:响应头,指定一个url,重定向到这个url,例子:还是以前面的登录跳转的302响应为例,Location: /index

Transport 头域

  • Connection:连接类型,请求头和响应头中都有。

    Connection: keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接

    Connection: close 代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭, 当客户端再次发送Request,需要重新建立TCP连接。

  • Host:请求头,用于指定被请求资源所在服务器的域名(用于虚拟主机 )和端口号,Web上的一台主机可以存在多个域,有了Host这个请求头就避免了多个域名指向同一个IP地址产生的混淆,而且有了这个域名,在request line部分请求资源的路径就可以用相对路径了。

    例子:Host: demo-bootstrap-blog.herokuapp.com,此处使用缺省端口号80

Cache头域

  • Date:响应头,此条消息被发送时的日期和时间,例子:Date: Tue, 08 Nov 2016 12:44:35 GMT

  • Expires:响应头,指定一个日期/时间,超过该时间则认为此回应已经过期,浏览器会在指定过期时间内使用本地缓存

    例子:Expires: Sat, 05 Nov 2016 21:51:32 GMT


总结

http协议的内容很多,初学阶段需要了解http协议的基本概念,http消息的基本结构以及http请求和响应所包含的基本信息,但http协议还有更多的内容需要学习,包括缓存、cookie、压缩和认证等等,深入学习http协议的相关知识必将帮助前端工程师更好地完成工作。


参考资料


本作品采用知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。要查看该许可协议,可访问 http://creativecommons.org/licenses/by-nc-sa/4.0/ 或者写信到 Creative Commons, PO Box 1866, Mountain View, CA 94042, USA。

打开App,阅读手记
4人推荐
发表评论
随时随地看视频慕课网APP