作者|cxuan
编辑|屠敏
头图|CSDN下载自视觉中国。
我是一名程序员,主要的编程语言是Java,我是一名Web开发人员,所以我必须了解HTTP,所以这篇文章将带你从入门到HTTP的高级水平。看完之后,你会有一种豁然开朗、豁然开朗的感觉。
起初,在互联网出现之前,我们的电脑都是单机的,单机系统是孤立的。还记得五年前家里有一台电脑,两个人在同一台电脑上玩电脑游戏很不方便。我很奇怪为什么家里不让我上网。我同学xxx家里有互联网。每次提到这个,都会得到一片批评声:xxx,xxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx。虽然我家里没有上网,但是互联网已经在高速发展了,HTTP就是高速发展的产物。
关于HTTP你最应该听到的第一句话就是HTTP是一个HypertextTransferProtocol,这个你肯定可以说,但是这还不够。如果你是大厂的面试官,这不可能是他想要的最终结果。我们在面试的时候往往会尽可能的多讲一些,以便和面试官谈判。那么什么是超文本传输协议呢?
超文本传输协议可以分为文字:超文本、传输和协议,它们之间的关系如下。
超文本是根据范围的大小协议传输的。下面分别对这三个排名进行说明。
什么是超文本在互联网早期的时候,我们输入的信息只能保存在本地,不能和其他电脑互动。我们保存的信息通常以文本的形式存在,也就是简单的字符。文本是可以被计算机解析的有意义的二进制数据包。随着互联网的快速发展,在两台计算机之间可以传输数据后,人们不满足于在两台计算机之间只传输文本,还想传输图片、音频、视频,甚至点击文字或图片跳转到超链接,于是文本的语义被扩展,这种语义扩展的文本被称为超文本。
什么是传输所以,正如我们上面所说的,两台计算机将以互连的关系相互通信,存储的超文本将被解析成二进制数据包。传输载体(如同轴电缆、电话线、光缆)负责将二进制数据包从计算机终端传输到另一个终端(有关终端的详细说明,请参考《你说你懂互联网,那这些你知道么?》篇文章),这种传输称为传输。
通常,我们将发送数据包的一方称为请求方,将接收二进制数据包的一方称为响应方。请求者和被请求者可以互换。请求者也可以作为响应者接受数据,响应者也可以作为请求者请求数据。它们之间的关系如下。
如图,A和B是两个不同的端系统,可以作为信息交换的载体存在。起初,A作为请求方请求与B交换信息,B作为响应方提供信息;久而久之,B也可以作为请求者请求A交换信息,A也可以作为回应者回应B所请求的信息。
术语& quot什么是协议协议& quot不仅仅局限于网络,还体现在日常生活中。比如情侣约定去哪里吃饭,这个约定也是约定。比如你求职成功,企业会和你签订劳动合同,双方的这种雇佣关系也是一种协议。注意,自己与自己的约定不能是约定,约定的前提条件必须是多人的约定。
那么什么是网络协议呢?
网络协议是在网络(包括互联网)中传输和管理信息的一些规范。就像人与人之间的通信需要遵循一定的规则一样,计算机之间的通信也需要一起遵循一定的规则,这些规则被称为网络协议。
没有网络协议的互联网是混乱的,就像人类社会一样,人们不能为所欲为,你的行为受到法律的约束;那么互联网中的端系统也不能想发什么就发什么,还需要被通信协议绑定。
那么我们可以总结一下,什么是HTTP?可以用下面的经典总结来回答:HTTP是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。
随着网络世界的演进,HTTP相关的组件几乎已经成为不可替代的协议。在了解了HTTP的基本构成之后,下面就带大家了解更多关于HTTP的知识。
网络模型网络是一个复杂的系统,不仅包括大量的应用程序、终端系统、通信链路、分组交换机等。还包括各种协议,所以现在我们来谈谈网络中的协议级别。
为了给网络协议的设计提供一个结构,网络设计人员以分层的方式组织协议,每个协议属于其中一个层次模型。每一层都为其上层提供一个服务,也就是所谓的servicemodel。每层中的所有关联
议称为协议栈(protocolstack)。因特网的协议栈由五个部分组成:物理层、链路层、网络层、运输层和应用层。我们采用自上而下的方法研究其原理,也就是应用层->物理层的方式。应用层是网络应用程序和网络协议存放的分层,因特网的应用层包括许多协议,例如我们学web离不开的HTTP,电子邮件传送协议SMTP、端系统文件上传协议FTP、还有为我们进行域名解析的DNS协议。应用层协议分布在多个端系统上,一个端系统应用程序与另外一个端系统应用程序交换信息分组,我们把位于应用层的信息分组称为报文(message)。
因特网的运输层在应用程序断点之间传送应用程序报文,在这一层主要有两种传输协议TCP和UDP,利用这两者中的任何一个都能够传输报文,不过这两种协议有巨大的不同。
TCP向它的应用程序提供了面向连接的服务,它能够控制并确认报文是否到达,并提供了拥塞机制来控制网络传输,因此当网络拥塞时,会抑制其传输速率。
UDP协议向它的应用程序提供了无连接服务。它不具备可靠性的特征,没有流量控制,也没有拥塞控制。我们把运输层的分组称为报文段(segment)
因特网的网络层负责将称为数据报(datagram)的网络分层从一台主机移动到另一台主机。网络层一个非常重要的协议是IP协议,所有具有网络层的因特网组件都必须运行IP协议,IP协议是一种网际协议,除了IP协议外,网络层还包括一些其他网际协议和路由选择协议,一般把网络层就称为IP层,由此可知IP协议的重要性。
现在我们有应用程序通信的协议,有了给应用程序提供运输的协议,还有了用于约定发送位置的IP协议,那么如何才能真正的发送数据呢?为了将分组从一个节点(主机或路由器)运输到另一个节点,网络层必须依靠链路层提供服务。链路层的例子包括以太网、WiFi和电缆接入的DOCSIS协议,因为数据从源目的地传送通常需要经过几条链路,一个数据包可能被沿途不同的链路层协议处理,我们把链路层的分组称为帧(frame)
虽然链路层的作用是将帧从一个端系统运输到另一个端系统,而物理层的作用是将帧中的一个个比特从一个节点运输到另一个节点,物理层的协议仍然使用链路层协议,这些协议与实际的物理传输介质有关,例如,以太网有很多物理层协议:关于双绞铜线、关于同轴电缆、关于光纤等等。
五层网络协议的示意图如下
我们上面讨论的计算网络协议模型不是唯一的协议栈,ISO(国际标准化组织)提出来计算机网络应该按照7层来组织,那么7层网络协议栈与5层的区别在哪里?
从图中可以一眼看出,OSI要比上面的网络模型多了表示层和会话层,其他层基本一致。表示层主要包括数据压缩和数据加密以及数据描述,数据描述使得应用程序不必担心计算机内部存储格式的问题,而会话层提供了数据交换的定界和同步功能,包括建立检查点和恢复方案。
就如同各大邮箱使用电子邮件传送协议SMTP一样,浏览器是使用HTTP协议的主要载体,说到浏览器,你能想起来几种?是的,随着网景大战结束后,浏览器迅速发展,至今已经出现过的浏览器主要有:
浏览器正式的名字叫做WebBroser,顾名思义,就是检索、查看互联网上网页资源的应用程序,名字里的Web,实际上指的就是WorldWideWeb,也就是万维网。
我们在地址栏输入URL(即网址),浏览器会向DNS(域名服务器,后面会说)提供网址,由它来完成URL到IP地址的映射。然后将请求你的请求提交给具体的服务器,在由服务器返回我们要的结果(以HTML编码格式返回给浏览器),浏览器执行HTML编码,将结果显示在浏览器的正文。这就是一个浏览器发起请求和接受响应的过程。
Web服务器的正式名称叫做WebServer,Web服务器一般指的是网站服务器,上面说到浏览器是HTTP请求的发起方,那么Web服务器就是HTTP请求的应答方,Web服务器可以向浏览器等Web客户端提供文档,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。目前最主流的三个Web服务器是Apache、Nginx、IIS。
CDN的全称是ContentDeliveryNetwork,即内容分发网络,它应用了HTTP协议里的缓存和代理技术,代替源站响应客户端的请求。CDN是构建在现有网络基础之上的网络,它依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。
打比方说你要去亚马逊上买书,之前你只能通过购物网站购买后从美国发货过海关等重重关卡送到你的家里,现在在中国建立一个亚马逊分基地,你就不用通过美国进行邮寄,从中国就能把书尽快给你送到。
WAF是一种Web应用程序防护系统(WebApplicationFirewall,简称WAF),它是一种通过执行一系列针对HTTP/HTTPS的安全策略来专门为Web应用提供保护的一款产品,它是应用层面的防火墙,专门检测HTTP流量,是防护Web应用的安全技术。
WAF通常位于Web服务器之前,可以阻止如SQL注入、跨站脚本等攻击,目前应用较多的一个开源项目是ModSecurity,它能够完全集成进Apache或Nginx。
WebService是一种Web应用程序,WebService是一种跨编程语言和跨操作系统平台的远程调用技术。
WebService是一种由W3C定义的应用服务开发规范,使用client-server主从架构,通常使用WSDL定义服务接口,使用HTTP协议传输XML或SOAP消息,它是一个基于Web(HTTP)的服务架构技术,既可以运行在内网,也可以在适当保护后运行在外网。
HTML称为超文本标记语言,是一种标识性的语言。它包括一系列标签.通过这些标签可以将网络上的文档格式统一,使分散的Internet资源连接为一个逻辑整体。HTML文本是由HTML命令组成的描述性文本,HTML命令可以说明文字,图形、动画、声音、表格、链接等。
Web页面(Webpage)也叫做文档,是由一个个对象组成的。一个对象(Objecy)只是一个文件,比如一个HTML文件、一个JPEG图形、一个Java小程序或一个视频片段,它们在网络中可以通过URL地址寻址。多数的Web页面含有一个HTML基本文件以及几个引用对象。
举个例子,如果一个Web页面包含HTML文件和5个JPEG图形,那么这个Web页面就有6个对象:一个HTML文件和5个JPEG图形。HTML基本文件通过URL地址引用页面中的其他对象。
在互联网中,任何协议都不会单独的完成信息交换,HTTP也一样。虽然HTTP属于应用层的协议,但是它仍然需要其他层次协议的配合完成信息的交换,那么在完成一次HTTP请求和响应的过程中,需要哪些协议的配合呢?一起来看一下
TCP/IP协议你一定听过,TCP/IP我们一般称之为协议簇,什么意思呢?就是TCP/IP协议簇中不仅仅只有TCP协议和IP协议,它是一系列网络通信协议的统称。而其中最核心的两个协议就是TCP/IP协议,其他的还有UDP、ICMP、ARP等等,共同构成了一个复杂但有层次的协议栈。
TCP协议的全称是TransmissionControlProtocol的缩写,意思是传输控制协议,HTTP使用TCP作为通信协议,这是因为TCP是一种可靠的协议,而可靠能保证数据不丢失。
IP协议的全称是InternetProtocol的缩写,它主要解决的是通信双方寻址的问题。IP协议使用IP地址来标识互联网上的每一台计算机,可以把IP地址想象成为你手机的电话号码,你要与他人通话必须先要知道他人的手机号码,计算机网络中信息交换必须先要知道对方的IP地址。(关于TCP和IP更多的讨论我们会在后面详解)
你有没有想过为什么你可以通过键入www.google.com就能够获取你想要的网站?我们上面说到,计算机网络中的每个端系统都有一个IP地址存在,而把IP地址转换为便于人类记忆的协议就是DNS协议。
DNS的全称是域名系统(DomainNameSystem,缩写:DNS),它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。
我们上面提到,你可以通过输入www.google.com地址来访问谷歌的官网,那么这个地址有什么规定吗?我怎么输都可以?AAA.BBB.CCC是不是也行?当然不是的,你输入的地址格式必须要满足URI的规范。
URI的全称是(UniformResourceIdentifier),中文名称是统一资源标识符,使用它就能够唯一地标记互联网上资源。
URL的全称是(UniformResourceLocator),中文名称是统一资源定位符,也就是我们俗称的网址,它实际上是URI的一个子集。
URI不仅包括URL,还包括URN(统一资源名称),它们之间的关系如下
HTTP一般是明文传输,很容易被攻击者窃取重要信息,鉴于此,HTTPS应运而生。HTTPS的全称为(HyperTextTransferProtocoloverSecureSocketLayer),全称有点长,HTTPS和HTTP有很大的不同在于HTTPS是以安全为目标的HTTP通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性。HTTPS在HTTP的基础上增加了SSL层,也就是说HTTPS=HTTP+SSL。(这块我们后面也会详谈HTTPS)
你是不是很好奇,当你在浏览器中输入网址后,到底发生了什么事情?你想要的内容是如何展现出来的?让我们通过一个例子来探讨一下,我们假设访问的URL地址为http://www.someSchool.edu/someDepartment/home.index,当我们输入网址并点击回车时,浏览器内部会进行如下操作
DNS服务器会首先进行域名的映射,找到访问www.someSchool.edu所在的地址,然后HTTP客户端进程在80端口发起一个到服务器www.someSchool.edu的TCP连接(80端口是HTTP的默认端口)。在客户和服务器进程中都会有一个套接字与其相连。
HTTP客户端通过它的套接字向服务器发送一个HTTP请求报文。该报文中包含了路径someDepartment/home.index的资源,我们后面会详细讨论HTTP请求报文。
HTTP服务器通过它的套接字接受该报文,进行请求的解析工作,并从其存储器(RAM或磁盘)中检索出对象www.someSchool.edu/someDepartment/home.index,然后把检索出来的对象进行封装,封装到HTTP响应报文中,并通过套接字向客户进行发送。
HTTP服务器随即通知TCP断开TCP连接,实际上是需要等到客户接受完响应报文后才会断开TCP连接。
HTTP客户端接受完响应报文后,TCP连接会关闭。HTTP客户端从响应中提取出报文中是一个HTML响应文件,并检查该HTML文件,然后循环检查报文中其他内部对象。
检查完成后,HTTP客户端会把对应的资源通过显示器呈现给用户。
至此,键入网址再按下回车的全过程就结束了。上述过程描述的是一种简单的请求-响应全过程,真实的请求-响应情况可能要比上面描述的过程复杂很多。
从上面整个过程中我们可以总结出HTTP进行分组传输是具有以下特征
支持客户-服务器模式
简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
我们上面描述了一下HTTP的请求响应过程,流程比较简单,但是凡事就怕认真,你这一认真,就能拓展出很多东西,比如HTTP报文是什么样的,它的组成格式是什么?下面就来探讨一下
HTTP协议主要由三大部分组成:
起始行(startline):描述请求或响应的基本信息;
头部字段(header):使用key-value形式更详细地说明报文;
消息正文(entity):实际传输的数据,它不一定是纯文本,可以是图片、视频等二进制数据。
其中起始行和头部字段并成为请求头或者响应头,统称为Header;消息正文也叫做实体,称为body。HTTP协议规定每次发送的报文必须要有Header,但是可以没有body,也就是说头信息是必须的,实体信息可以没有。而且在header和body之间必须要有一个空行(CRLF),如果用一幅图来表示一下的话,我觉得应该是下面这样
我们使用上面的那个例子来看一下http的请求报文
如图,这是http://www.someSchool.edu/someDepartment/home.index请求的请求头,通过观察这个HTTP报文我们就能够学到很多东西,首先,我们看到报文是用普通ASCII文本书写的,这样保证人能够可以看懂。然后,我们可以看到每一行和下一行之间都会有换行,而且最后一行(请求头部后)再加上一个回车换行符。
每个报文的起始行都是由三个字段组成:方法、URL字段和HTTP版本字段。
HTTP请求方法一般分为8种,它们分别是
GET获取资源,GET方法用来请求访问已被URI识别的资源。指定的资源经服务器端解析后返回响应内容。也就是说,如果请求的资源是文本,那就保持原样返回;
POST传输实体,虽然GET方法也可以传输主体信息,但是便于区分,我们一般不用GET传输实体信息,反而使用POST传输实体信息,
PUT传输文件,PUT方法用来传输文件。就像FTP协议的文件上传一样,要求在请求报文的主体中包含文件内容,然后保存到请求URI指定的位置。
但是,鉴于HTTP的PUT方法自身不带验证机制,任何人都可以上传文件,存在安全性问题,因此一般的Web网站不使用该方法。若配合Web应用程序的验证机制,或架构设计采用REST(REpresentationalStateTransfer,表征状态转移)标准的同类Web网站,就可能会开放使用PUT方法。
HEAD获得响应首部,HEAD方法和GET方法一样,只是不返回报文主体部分。用于确认URI的有效性及资源更新的日期时间等。
DELETE删除文件,DELETE方法用来删除文件,是与PUT相反的方法。DELETE方法按请求URI删除指定的资源。
OPTIONS询问支持的方法,OPTIONS方法用来查询针对请求URI指定的资源支持的方法。
TRACE追踪路径,TRACE方法是让Web服务器端将之前的请求通信环回给客户端的方法。
CONNECT要求用隧道协议连接代理,CONNECT方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。主要使用SSL(SecureSocketsLayer,安全套接层)和TLS(TransportLayerSecurity,传输层安全)协议把通信内容加密后经网络隧道传输。
我们一般最常用的方法也就是GET方法和POST方法,其他方法暂时了解即可。下面是HTTP1.0和HTTP1.1支持的方法清单
HTTP协议使用URI定位互联网上的资源。正是因为URI的特定功能,在互联网上任意位置的资源都能访问到。URL带有请求对象的标识符。在上面的例子中,浏览器正在请求对象/somedir/page.html的资源。
我们再通过一个完整的域名解析一下URL
比如http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument这个URL比较繁琐了吧,你把这个URL搞懂了其他的URL也就不成问题了。
首先出场的是http
http://告诉浏览器使用何种协议。对于大部分Web资源,通常使用HTTP协议或其安全版本,HTTPS协议。另外,浏览器也知道如何处理其他协议。例如,mailto:协议指示浏览器打开邮件客户端;ftp:协议指示浏览器处理文件传输。
第二个出场的是主机
www.example.com既是一个域名,也代表管理该域名的机构。它指示了需要向网络上的哪一台主机发起请求。当然,也可以直接向主机的IPaddress地址发起请求。但直接使用IP地址的场景并不常见。
第三个出场的是端口
我们前面说到,两个主机之间要发起TCP连接需要两个条件,主机+端口。它表示用于访问Web服务器上资源的入口。如果访问的该Web服务器使用HTTP协议的标准端口(HTTP为80,HTTPS为443)授予对其资源的访问权限,则通常省略此部分。否则端口就是URI必须的部分。
上面是请求URL所必须包含的部分,下面就是URL具体请求资源路径
第四个出场的是路径
/path/to/myfile.html是Web服务器上资源的路径。以端口后面的第一个/开始,到?号之前结束,中间的每一个/都代表了层级(上下级)关系。这个URL的请求资源是一个html页面。
紧跟着路径后面的是查询参数
?key1=value1&key2=value2是提供给Web服务器的额外参数。如果是GET请求,一般带有请求URL参数,如果是POST请求,则不会在路径后面直接加参数。这些参数是用&符号分隔的键/值对列表。key1=value1是第一对,key2=value2是第二对参数
紧跟着参数的是锚点
#SomewhereInTheDocument是资源本身的某一部分的一个锚点。锚点代表资源内的一种“书签”,它给予浏览器显示位于该“加书签”点的内容的指示。例如,在HTML文档上,浏览器将滚动到定义锚点的那个点上;在视频或音频文档上,浏览器将转到锚点代表的那个时间。值得注意的是#号后面的部分,也称为片段标识符,永远不会与请求一起发送到服务器。
表示报文使用的HTTP协议版本。
这部分内容只是大致介绍一下,内容较多,后面会再以一篇文章详述。
在表述完了起始行之后我们再来看一下请求头部,现在我们向上找,找到http://www.someSchool.edu/someDepartment/home.index,来看一下它的请求头部
Host:www.someschool.edu
Connection:close
User-agent:Mozilla/5.0
Accept-language:fr
这个请求头信息比较少,首先Host表示的是对象所在的主机。你也许认为这个Host是不需要的,因为URL不是已经指明了请求对象的路径了吗?这个首部行提供的信息是Web代理高速缓存所需要的。Connection:close表示的是浏览器需要告诉服务器使用的是非持久连接。它要求服务器在发送完响应的对象后就关闭连接。User-agent:这是请求头用来告诉Web服务器,浏览器使用的类型是Mozilla/5.0,即Firefox浏览器。Accept-language告诉Web服务器,浏览器想要得到对象的法语版本,前提是服务器需要支持法语类型,否则将会发送服务器的默认版本。下面我们针对主要的实体字段进行介绍(具体的可以参考https://developer.mozilla.org/zh-CN/docs/Web/HTTP/HeadersMDN官网学习)
HTTP的请求标头分为四种:通用标头、请求标头、响应标头和实体标头,依次来进行详解。
通用标头主要有三个,分别是Date、Cache-Control和Connection
Date
Date是一个通用标头,它可以出现在请求标头和响应标头中,它的基本表示如下
Date:Wed,21Oct201507:28:00GMT
表示的是格林威治标准时间,这个时间要比北京时间慢八个小时
Cache-Control
Cache-Control是一个通用标头,他可以出现在请求标头和响应标头中,Cache-Control的种类比较多,虽然说这是一个通用标头,但是有一些特性是请求标头具有的,有一些是响应标头才有的。主要大类有可缓存性、阈值性、重新验证并重新加载和其他特性
可缓存性是唯一响应标头才具有的特性,我们会在响应标头中详述。
阈值性,这个我翻译可能不准确,它的原英文是Expiration,我是根据它的值来翻译的,你看到这些值可能会觉得我翻译的有点道理
max-age:资源被认为仍然有效的最长时间,与Expires不同,这个请求是相对于request标头的时间,而Expires是相对于响应标头。(请求标头)
s-maxage:重写了max-age和Expires请求头,仅仅适用于共享缓存,被私有缓存所忽略(这块不理解,看完响应头的Cache-Control再进行理解)(请求标头)
max-stale:表示客户端将接受的最大响应时间,以秒为单位。(响应标头)
min-fresh:表示客户端希望响应在指定的最小时间内有效。(响应标头)
Connection
Connection决定当前事务(一次三次握手和四次挥手)完成后,是否会关闭网络连接。Connection有两种,一种是持久性连接,即一次事务完成后不关闭网络连接
Connection:keep-alive
另一种是非持久性连接,即一次事务完成后关闭网络连接
Connection:close
HTTP1.1其他通用标头如下
实体标头是描述消息正文内容的HTTP标头。实体标头用于HTTP请求和响应中。头部Content-Length、Content-Language、Content-Encoding是实体头。
Content-Length实体报头指示实体主体的大小,以字节为单位,发送到接收方。
Content-Language实体报头描述了客户端或者服务端能够接受的语言,例如
Content-Language:de-DE
Content-Language:en-US
Content-Language:de-DE,en-CA
Content-Encoding这又是一个比较麻烦的属性,这个实体报头用来压缩媒体类型。Content-Encoding指示对实体应用了何种编码。
常见的内容编码有这几种:gzip、compress、deflate、identity,这个属性可以应用在请求报文和响应报文中
Accept-Encoding:gzip,deflate//请求头
Content-Encoding:gzip//响应头
下面是一些实体标头字段
上面给出的例子请求报文的属性比较少,下面给出一个MDN官网的例子
GET/home.htmlHTTP/1.1
Host:developer.mozilla.org
User-Agent:Mozilla/5.0(Macintosh;IntelMacOSX10.9;rv:50.0)Gecko/20100101Firefox/50.0
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language:en-US,en;q=0.5
Accept-Encoding:gzip,deflate,br
Referer:https://developer.mozilla.org/testpage.html
Connection:keep-alive
Upgrade-Insecure-Requests:1
If-Modified-Since:Mon,18Jul201602:36:04GMT
If-None-Match:"c561c68d0ba92bbeb8b0fff2a9199f722e3a621a"
Cache-Control:max-age=0
Host
Host请求头指明了服务器的域名(对于虚拟主机来说),以及(可选的)服务器监听的TCP端口号。如果没有给定端口号,会自动使用被请求服务的默认端口(比如请求一个HTTP的URL会自动使用80作为端口)。
Host:developer.mozilla.org
上面的Accpet、Accept-Language、Accept-Encoding都是属于内容协商的请求标头,我们会在下面说明
Referer
HTTPReferer属性是请求标头的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。
Referer:https://developer.mozilla.org/testpage.html
Upgrade-Insecure-Requests
Upgrade-Insecure-Requests是一个请求标头,用来向服务器端发送信号,表示客户端优先选择加密及带有身份验证的响应。
Upgrade-Insecure-Requests:1
If-Modified-Since
HTTP的If-Modified-Since使其成为条件请求:
返回200,只有在给定日期的最后一次修改资源后,服务器才会以200状态发送回请求的资源。
如果请求从开始以来没有被修改过,响应会返回304并且没有任何响应体
If-Modified-Since通常会与If-None-Match搭配使用,If-Modified-Since用于确认代理或客户端拥有的本地资源的有效性。获取资源的更新日期时间,可通过确认首部字段Last-Modified来确定。
大白话说就是如果在Last-Modified之后更新了服务器资源,那么服务器会响应200,如果在Last-Modified之后没有更新过资源,则返回304。
If-Modified-Since:Mon,18Jul201602:36:04GMT
If-None-Match
If-None-MatchHTTP请求标头使请求成为条件请求。对于GET和HEAD方法,仅当服务器没有与给定资源匹配的ETag时,服务器才会以200状态发送回请求的资源。对于其他方法,仅当最终现有资源的ETag与列出的任何值都不匹配时,才会处理请求。
If-None-Match:"c561c68d0ba92bbeb8b0fff2a9199f722e3a621a"
ETag属于响应标头,后面进行介绍。
内容协商机制是指客户端和服务器端就响应的资源内容进行交涉,然后提供给客户端最为适合的资源。内容协商会以响应资源的语言、字符集、编码方式等作为判断的标准。
内容协商主要有以下3种类型:
服务器驱动协商(Server-drivenNegotiation)
这种协商方式是由服务器端进行内容协商。服务器端会根据请求首部字段进行自动处理
客户端驱动协商(Agent-drivenNegotiation)
这种协商方式是由客户端来进行内容协商。
透明协商(TransparentNegotiation)
是服务器驱动和客户端驱动的结合体,是由服务器端和客户端各自进行内容协商的一种方法。
内容协商的分类有很多种,主要的几种类型是Accept、Accept-Charset、Accept-Encoding、Accept-Language、Content-Language。
Accept
接受请求HTTP标头会通告客户端其能够理解的MIME类型
那么什么是MIME类型呢?在回答这个问题前你应该先了解一下什么是MIME
MIME:MIME(MultipurposeInternetMailExtensions)是描述消息内容类型的因特网标准。MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。
也就是说,MIME类型其实就是一系列消息内容类型的集合。那么MIME类型都有哪些呢?
文本文件:text/html、text/plain、text/css、application/xhtml+xml、application/xml
图片文件:image/jpeg、image/gif、image/png
视频文件:video/mpeg、video/quicktime
应用程序二进制文件:application/octet-stream、application/zip
比如,如果浏览器不支持PNG图片的显示,那Accept就不指定image/png,而指定可处理的image/gif和image/jpeg等图片类型。
一般MIME类型也会和q这个属性一起使用,q是什么?q表示的是权重,来看一个例子
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
这是什么意思呢?若想要给显示的媒体类型增加优先级,则使用q=来额外表示权重值,没有显示权重的时候默认值是1.0,我给你列个表格你就明白了
也就是说,这是一个放置顺序,权重高的在前,低的在后,application/xml;q=0.9是不可分割的整体。
Accept-Charset
accept-charset属性规定服务器处理表单数据所接受的字符集。
accept-charset属性允许您指定一系列字符集,服务器必须支持这些字符集,从而得以正确解释表单中的数据。
该属性的值是用引号包含字符集名称列表。如果可接受字符集与用户所使用的字符即不相匹配的话,浏览器可以选择忽略表单或是将该表单区别对待。
此属性的默认值是unknown,表示表单的字符集与包含表单的文档的字符集相同。
常用的字符集有:UTF-8-Unicode字符编码;ISO-8859-1-拉丁字母表的字符编码
Accept-Language
首部字段Accept-Language用来告知服务器用户代理能够处理的自然语言集(指中文或英文等),以及自然语言集的相对优先级。可一次指定多种自然语言集。和Accept首部字段一样,按权重值q来表示相对优先级。
Accept-Language:en-US,en;q=0.5
请求标头我们大概就介绍这几种,后面会有一篇文章详细深挖所有的响应头的,下面是一个响应头的汇总,基于HTTP1.1
响应标头是可以在HTTP响应种使用的HTTP标头,这听起来是像一句废话,不过确实是这样解释。并不是所有出现在响应中的标头都是响应标头。还有一些特殊的我们上面说过,有通用标头和实体标头也会出现在响应标头中,比如Content-Length就是一个实体标头,但是,在这种情况下,这些实体请求通常称为响应头。下面以一个例子为例和你探讨一下响应头
200OK
Access-Control-Allow-Origin:*
Connection:Keep-Alive
Content-Encoding:gzip
Content-Type:text/html;charset=utf-8
Date:Mon,18Jul201616:06:00GMT
Etag:"c561c68d0ba92bbeb8b0f612a9199f722e3a621a"
Keep-Alive:timeout=5,max=997
Last-Modified:Mon,18Jul201602:36:04GMT
Server:Apache
Set-Cookie:mykey=myvalue;expires=Mon,17-Jul-201716:06:00GMT;Max-Age=31449600;Path=/;secure
Transfer-Encoding:chunked
Vary:Cookie,Accept-Encoding
x-frame-options:DENY
响应状态码
首先出现的应该就是200OK,这是HTTP响应标头的状态码,它表示着响应成功完成。HTTP响应标头的状态码有很多,并做了如下规定
以2xx为开头的都表示请求成功响应。
以3xx为开头的都表示需要进行附加操作以完成请求
以4xx的响应结果表明客户端是发生错误的原因所在。
以5xx为开头的响应标头都表示服务器本身发生错误
Access-Control-Allow-Origin
一个返回的HTTP标头可能会具有Access-Control-Allow-Origin,Access-Control-Allow-Origin指定一个来源,它告诉浏览器允许该来源进行资源访问。否则-对于没有凭据的请求*通配符,告诉浏览器允许任何源访问资源。例如,要允许源https://mozilla.org的代码访问资源,可以指定:
Access-Control-Allow-Origin:https://mozilla.org
Vary:Origin
如果服务器指定单个来源而不是*通配符的话,则服务器还应在Vary响应标头中包含Origin,以向客户端指示服务器响应将根据原始请求标头的值而有所不同。
Keep-Alive
上面我们提到,HTTP报文标头会分为四种,这其实是按着上下文来分类的
还有一种分类是根据代理进行分类,根据代理会分为端到端头和逐跳标头
而Keep-Alive表示的是Connection非持续连接的存活时间,如下
Connection:Keep-Alive
Keep-Alive:timeout=5,max=997
Keep-Alive有两个参数,它们是以逗号分隔的参数列表,每个参数由一个标识符和一个由等号=分隔的值组成。
timeout:指示空闲连接必须保持打开状态的最短时间(以秒为单位)。
max:指示在关闭连接之前可以在此连接上发送的最大请求数。
上述HTTP代码的意思就是限制最大的超时时间是5s和最大的连接请求是997个。
Server
服务器标头包含有关原始服务器用来处理请求的软件的信息。
应该避免使用过于冗长和详细的Server值,因为它们可能会泄露内部实施细节,这可能会使攻击者容易地发现并利用已知的安全漏洞。例如下面这种写法
Server:Apache/2.4.1(Unix)
Set-Cookie
Cookie又是另外一个领域的内容了,我们后面文章会说道Cookie,这里需要记住Cookie、Set-Cookie和Content-Disposition等在其他RFC中定义的首部字段,它们不是属于HTTP1.1的首部字段,但是使用率仍然很高。
Transfer-Encoding
首部字段Transfer-Encoding规定了传输报文主体时采用的编码方式。
Transfer-Encoding:chunked
HTTP/1.1的传输编码方式仅对分块传输编码有效。
X-Frame-Options
HTTP首部字段是可以自行扩展的。所以在Web服务器和浏览器的应用上,会出现各种非标准的首部字段。
首部字段X-Frame-Options属于HTTP响应首部,用于控制网站内容在其他Web网站的Frame标签内的显示问题。其主要目的是为了防止点击劫持(clickjacking)攻击。
下面是一个响应头的汇总,基于HTTP1.1
在HTTP协议通信交互中使用到的首部字段,不限于RFC2616中定义的47种首部字段。还有Cookie、Set-Cookie和Content-Disposition等在其他RFC中定义的首部字段,它们的使用频率也很高。这些非正式的首部字段统一归纳在RFC4229HTTPHeaderFieldRegistrations中。
HTTP首部字段将定义成缓存代理和非缓存代理的行为,分成2种类型。
一种是End-to-end首部和Hop-by-hop首部
这些标头必须发送给消息的最终接收者:请求的服务器,或响应的客户端。中间代理必须重新传输未经修改的标头,并且缓存必须存储这些信息
分在此类别中的首部只对单次转发有效,会因通过缓存或代理而不再转发。
下面列举了HTTP/1.1中的逐跳首部字段。除这8个首部字段之外,其他所有字段都属于端到端首部。
Connection、Keep-Alive、Proxy-Authenticate、Proxy-Authorization、Trailer、TE、Transfer-Encoding、Upgrade
HTTP最重要也是最突出的优点是简单、灵活、易于扩展。
HTTP的协议比较简单,它的主要组成就是header+body,头部信息也是简单的文本格式,而且HTTP的请求报文根据英文也能猜出来个大概的意思,降低学习门槛,能够让更多的人研究和开发HTTP应用。
所以,在简单的基础上,HTTP协议又多了灵活和易扩展的优点。
HTTP协议里的请求方法、URI、状态码、原因短语、头字段等每一个核心组成要素都没有被制定死,允许开发者任意定制、扩充或解释,给予了浏览器和服务器最大程度的信任和自由。
因为过于简单,普及,因此应用很广泛。因为HTTP协议本身不属于一种语言,它并不限定某种编程语言或者操作系统,所以天然具有跨语言、跨平台的优越性。而且,因为本身的简单特性很容易实现,所以几乎所有的编程语言都有HTTP调用库和外围的开发测试工具。
随着移动互联网的发展,HTTP的触角已经延伸到了世界的每一个角落,从简单的Web页面到复杂的JSON、XML数据,从台式机上的浏览器到手机上的各种APP、新闻、论坛、购物、手机游戏,你很难找到一个没有使用HTTP的地方。
无状态其实既是优点又是缺点。因为服务器没有记忆能力,所以就不需要额外的资源来记录状态信息,不仅实现上会简单一些,而且还能减轻服务器的负担,能够把更多的CPU和内存用来对外提供服务。
既然服务器没有记忆能力,它就无法支持需要连续多个步骤的事务操作。每次都得问一遍身份信息,不仅麻烦,而且还增加了不必要的数据传输量。由此出现了Cookie技术。
HTTP协议里还有一把优缺点一体的双刃剑,就是明文传输。明文意思就是协议里的报文(准确地说是header部分)不使用二进制数据,而是用简单可阅读的文本形式。
对比TCP、UDP这样的二进制协议,它的优点显而易见,不需要借助任何外部工具,用浏览器、Wireshark或者tcpdump抓包后,直接用肉眼就可以很容易地查看或者修改,为我们的开发调试工作带来极大的便利。
当然缺点也是显而易见的,就是不安全,可以被监听和被窥探。因为无法判断通信双方的身份,不能判断报文是否被更改过。
HTTP的性能不算差,但不完全适应现在的互联网,还有很大的提升空间。
参考资料:
https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Technical_overview
https://developer.mozilla.org/en-US/docs/Web/HTTP
https://baike.baidu.com/item/WEB服务器/8390210?fr=aladdin
https://baike.baidu.com/item/内容分发网络/4034265
https://baike.baidu.com/item/HTML/97049?fr=aladdin
https://www.jianshu.com/p/3dd8f1879acb
《计算机网络-自顶向下方法》
《图解HTTP》
HTTP协议的内容协商
https://www.w3school.com.cn/tags/att_form_accept_charset.asp
上一篇:什么是有理数(第三节)