一、What is HTTP ?
1. 协议概述
HTTP (HyperText Transfer Protocol,超文本传输协议) 是互联网上应用最为广泛的一种网络协议,设计 HTTP 最初的目的是为了提供一种发布和接收HTML页面的方法
HTTP 协议中现今广泛使用的一个版本是1999年6月公布的 HTTP1.1 ,而2015年5月发表的HTTP/2 取代 HTTP1.1 成为 HTTP 新的实现标准
通常,由 HTTP 客户端发起一个请求,创建一个到服务器指定端口(默认是80端口 )的 TCP 连接。HTTP 服务器则在那个端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态,比如 HTTP/1.1 200 OK ,以及返回的内容,如请求的文件、错误消息、或者其它信息
二、请求信息 (Request Message)
发出的请求信息包括以下几个:
- 请求行
例如GET /images/logo.gif HTTP/1.1,表示从/images目录下请求logo.gif这个文件 - 请求头
例如Accept-Language: en - 空行
- 其他消息体
请求行和标题必须以<CR><LF>作为结尾
空行内必须只有<CR><LF>而无其他空格
在HTTP/1.1协议中,所有的请求头,除Host外,都是可选的
1. 请求方法
HTTP/1.1 中共定义了8种方法(动作)来以不同方式操作指定的资源
-
GET:向指定的资源发出“显示”请求,使用GET方法应该只用在读取数据 -
POST:向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)
数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有 -
HEAD:与GET方法一样,都是向服务器发出指定资源的请求
只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据) -
OPTIONS:这个方法可使服务器传回该资源所支持的所有HTTP请求方法。
用'*'来代替资源名称,向Web服务器发送OPTIONS请求,可以测试服务器功能是否正常运作 -
PUT:向指定资源位置上传其最新内容 -
DELETE:请求服务器删除Request-URI所标识的资源 -
TRACE:回显服务器收到的请求,主要用于测试或诊断 -
CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
通常用于SSL加密服务器的链接(经由非加密的HTTP代理服务器)
** 方法名称是区分大小写的 **:
- 当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码
405(Method Not Allowed) - 当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码
501(Not Implemented)
- HTTP服务器至少应该实现
GET和HEAD方法,其他方法都是可选的- 安全超文本连接协议使用
https://代替http://
2. 状态码
所有HTTP响应的第一行都是状态行,依次是当前 HTTP 版本号,3位数字组成的状态代码,以及描述状态的短语,彼此由空格分隔。
状态代码的第一个数字代表当前响应的类型:
-
1xx消息 —— 请求已被服务器接收,继续处理 -
2xx成功 —— 请求已成功被服务器接收、理解、并接受 -
3xx重定向 —— 需要后续操作才能完成这一请求 -
4xx请求错误 —— 请求含有词法错误或者无法被执行 -
5xx服务器错误 —— 服务器在处理某个正确请求时发生错误
3. 举个栗子
下面是一个HTTP客户端与服务器之间会话的例子,运行于 www.google.com,端口 80
客户端请求:
GET / HTTP/1.1
Host: www.google.com
末尾有一个空行
第一行:指定方法、资源路径、协议版本
第二行:在1.1版里必带的一个header作用指定主机
服务器响应:
HTTP/1.1 200 OK
Content-Length: 3059
Server: GWS/2.0
Date: Sat, 11 Jan 2003 02:44:04 GMT
Content-Type: text/html
Cache-control: private
Set-Cookie: PREF=ID=73d4aef52e57bae9:TM=1042253044:LM=1042253044:S=SMCc_HRPCQiqy
X9j; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
Connection: keep-alive
(紧跟着一个空行,并且由HTML格式的文本组成了Google的主页)
- 在
HTTP1.0,单一TCP连接内仅执行一个“客户端发送请求—服务器发送应答”周期,之后释放TCP连接。 - 在
HTTP1.1优化支持持续活跃连接:客户端连续多次发送请求、接收应答;批量多请求时,同一TCP连接在活跃Keep-Live间期内复用,避免重复TCP初始握手活动,减少网络负荷和响应周期。此外支持应答到达前继续发送请求(通常是两个),称为“流线化”(stream)。
4. 通用头域
通用头域包含请求和响应消息都支持的头域,通用头域包含:
-
Cache-Control头域:指定请求和响应遵循的缓存机制
在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程 -
请求时的缓存指令包括:
-
no-cache:指示响应可被任何缓存区缓存 -
no-store:在请求消息中发送将使得请求和响应消息都不使用缓存,可防止重要的信息被无意的发布 -
max-age:指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应 -
max-stale:指示客户机可以接收超出超时期间的响应消息。
如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息 -
min-fresh:指示客户机可以接收响应时间小于当前时间加上指定时间的响应 only-if-cached
-
-
响应消息中的指令包括:
-
public:指示响应可被任何缓存区缓存 privateno-cacheno-storeno-transformmust-revalidateproxy-revalidatemax-age
-
-
Connection -
DateDate头域:头域表示消息发送的时间,时间的描述格式由rfc822定义 -
例如,
Date:Mon,31Dec200104:25:57GMT -
Date描述的时间表示世界标准时,换算成本地时间,需要知道用户所在的时区。 -
Pragma头域:用来包含实现特定的指令 -
最常用的是
Pragma:no-cache -
在 HTTP/1.1 协议中,它的含义和
Cache- Control:no-cache相同 -
Transfer-Encoding头域 -
Upgrade头域 -
Via头域
上面总结的是“通用头域”,我们先来看下一个典型的请求信息:
GET / HTTP/1.1
Host: baidu.com
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.103 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
Cookie: BDUSS=aaaaa; BAIDUID=bbbbb:FG=1; PSTM=1459694957; BDRCVFR[loys_9vxHFf]=mk3SLVN4HKm; BIDUPSID=ccccc; pgv_pvi=9192257536; pgv_si=s6465831936; H_PS_PSSID=ddddd
上面的第一行表示HTTP客户端(可能是浏览器、下载程序)通过GET方法获得指定URL下的文件。接下来,我们来分析下“ 请求头域 ”
5. 请求头域
-
Host头域:指定请求资源的Intenet主机和端口号 - 必须表示请求url的原始服务器或网关的位置
- HTTP/1.1请求必须包含主机头域,否则系统会以400状态码返回
-
Referer头域:允许客户端指定请求uri的源资源地址 - 这可以允许服务器生成回退链表,可用来登陆、优化cache等
- 也允许废除的或错误的连接由于维护的目的被追踪
- 如果请求的uri没有自己的uri地址,Referer不能被发送
- 如果指定的是部分uri地址,则此地址应该是一个相对地址
-
Range头域:请求实体的一个或者多个子范围 - 例如
- 表示头500个字节:bytes=0-499
- 表示第二个500字节:bytes=500-999
- 表示500字节以后的范围:bytes=500-
- 第一个和最后一个字节:bytes=0-0,-1
- 同时指定几个范围:bytes=500-600,601-999
- 但是服务器可以忽略此请求头,如果无条件
GET包含Range请求头,响应会以状态码206(PartialContent)返回而不是以200 (OK) -
User-Agent头域:内容包含发出请求的用户信息
三、响应消息(Response Message)
1. 响应头
我们先来看一个“请求百度首页”的响应头:
HTTP/1.1 200 OK
Date: Sun, 03 Apr 2016 15:44:32 GMT
Content-Type: text/html;charset=utf-8
Transfer-Encoding: chunked
Connection: Keep-Alive
Cache-Control: private
Expires: Sun, 03 Apr 2016 15:44:32 GMT
Content-Encoding: gzip
Server: BWS/1.1
X-UA-Compatible: IE=Edge,chrome=1
BDPAGETYPE: 2
BDQID: 0xb2584dee0005f8ac
BDUSERID: 801624962
Set-Cookie: BDSVRTM=147; path=/
Set-Cookie: BD_HOME=1; path=/
Set-Cookie: H_PS_PSSID=aaaaa; path=/; domain=.baidu.com
-
响应头的第一行为右边的格式:
HTTP-Version Status-Code Reason-Phrase -
HTTP- Version:表示支持的HTTP版本
例如为HTTP/1.1 -
Status- Code:是一个三个数字的结果代码(可参考前面总结的“状态码”部分)
主要用于机器自动识别,第一个数字定义响应的类别 -
Reason-Phrase:给Status-Code提供一个简单的文本描述
主要用于帮助用户理解 -
Location响应头:用于重定向接收者到一个新URI地址 -
Server响应头:包含处理请求的原始服务器的软件信息。
此域能包含多个产品标识和注释,产品标识一般按照重要性排序
2. 实体
请求消息 和 响应消息 都可以包含实体信息,实体信息一般由 实体头域 和 实体 组成
实体头包括:
| Allow | Content- Base | Content-Encoding | |
| Content-Language | Content-Length | Content-Location | |
| Content-MD5 | Content-Range | Content-Type | |
| Etag | Expires | Last-Modified | |
| extension-header |
-
Content-Type实体头:向接收方指示实体的介质类型 - 指定
HEAD方法送到接收方的实体介质类型 - 或
GET方法发送的请求介质类型 -
Content-Range实体头:指定整个实体中的一部分的插入位置,也指示了整个实体的长度 - 在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度
- 一般格式:
Content-Range:bytes-unit first-byte-pos-last-byte-pos/entity-legth - 例如,传送头500个字节次字段的形式:
Content-Range:bytes0- 499/1234 -
Content-Range表示传送的范围,Content-Length表示实际传送的字节数 -
Last-modified实体头:指定服务器上保存内容的最后修订时间
3. 响应头
-
Allow:服务器支持哪些请求方法(如GET、POST等) -
Content-Encoding:文档的编码(Encode)方法 -
只有在解码之后才可以得到
Content-Type头指定的内容类型 -
利用
gzip压缩文档能够显著地减少HTML文档的下载时间 -
Java的
GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。 -
因此,
Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept- Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。 -
Content-Length:表示内容长度 -
只有当浏览器使用持久HTTP连接时才需要这个数据
-
Content-Type:表示后面的文档属于什么MIME类型 -
Servlet默认为text/plain,但通常需要显式地指定为text/html -
由于经常要设置
Content-Type,因此HttpServletResponse提供了一个专用的方法setContentTyep -
Date:当前的GMT时间 -
你可以用
setDateHeader来设置这个头以避免转换时间格式的麻烦。 -
Expires:应该在什么时候认为文档已经过期,从而不再缓存它? -
Last-Modified:文档的最后改动时间。 -
客户可以通过
If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。 -
Last-Modified也可用setDateHeader方法来设置。 -
Location:表示客户应当到哪里去提取文档 -
Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。 -
Refresh:表示浏览器应该在多少时间之后刷新文档,以秒计 -
除了刷新当前文档之外,你还可以通过
setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。 注意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的 HTML编写者十分重要 -
但是,对于
Servlet来说,直接设置Refresh头更加方便 -
注意
Refresh的意义是“N秒之后刷新本页面或访问指定页面”,而不是“每隔N秒刷新本页面或访问指定页面”。 -
因此,连续刷新要求每次都发送一个
Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTP-EQUIV="Refresh" ...> -
注意:
Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它 -
Server:服务器名 -
Servlet一般不设置这个值,而是由Web服务器自己设置 -
Set-Cookie:设置和页面关联的Cookie -
Servlet不应使用response.setHeader("Set-Cookie", ...),而是应使用HttpServletResponse提供的专用方法addCookie
四、Cookie
某些网站为了辨别用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)
1. 分类
Cookie 总是保存在客户端中,按在客户端中的存储位置可分为
内存Cookie-
内存Cookie由浏览器维护,保存在内存中,浏览器关闭后就消失了,其存在时间是短暂的 硬盘Cookie-
硬盘Cookie保存在硬盘里,有一个过期时间,除非用户手工清理或到了过期时间,硬盘Cookie不会被删除,其存在时间是长期的
所以,按存在时间,可分为 非持久Cookie 和 持久Cookie
2. 用途
因为 HTTP 协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式 Web 应用程序的实现。Cookie就是用来绕开 HTTP 的无状态性的“额外手段”之一。服务器可以设置或读取 Cookies 中包含信息,借此维护用户跟服务器会话中的状态
3. 应用场景:
- 当登录一个网站时,网站往往会请求用户输入用户名和密码,并且用户可以勾选“下次自动登录”
- 如果勾选了,那么下次访问同一网站时,用户会发现没输入用户名和密码就已经登录了
- 这正是因为前一次登录时,服务器发送了包含登录凭据(用户名加密码的某种加密形式)的
Cookie到用户的硬盘上 - 第二次登录时,(如果该
Cookie尚未到期)浏览器会发送该Cookie,服务器验证凭据,于是不必输入用户名和密码就让用户登录了
4. Cookie的缺陷
-
Cookie会被附加在每个HTTP请求中,所以无形中增加了流量 - 由于在HTTP请求中的
Cookie是明文传递的,所以安全性成问题(除非用HTTPS) -
Cookie的大小限制在4KB左右。对于复杂的存储需求来说是不够用的
5. 识别功能
- 如果在一台计算机中安装多个浏览器,每个浏览器都会以独立的空间存放
Cookie - 因为
Cookie中不但可以确认用户信息,还能包含计算机和浏览器的信息,所以一个用户使用不同的浏览器登录或者用不同的计算机登录,都会得到不同的Cookie信息 - 另一方面,对于在同一台计算机上使用同一浏览器的多用户群,
Cookie不会区分他们的身份,除非他们使用不同的用户名登录。
参考文章:
[1] 维基百科:超文本传输协议
[2] 维基百科:Cookie
[2] madfrag:HTTP响应头信息和请求头信息详解








网友评论