HTTP协议
HTTP协议概述
HTTP是客户端(用户)与服务器(网站)请求应答的标准。
HTTP假定其下层协议提供可靠的传输.
通常HTTP客户端发起一个请求,创建一个到服务器指定端口的TCP连接。HTTP服务器则在那个端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态,比如"HTTP/1.1 200 ok",以及返回的内容,如请求的文件、错误信息或者其他信息。
HTTP工作原理
HTTP协议采用了请求/响应模式。客户端发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。
HTTP请求/响应步骤
-
客户端连接到Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP socket连接。例如,http://www.baidu.com。 -
发送HTTP请求
通过TCP socket,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。 -
服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。 -
释放连接TCP连接
若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求; -
客户端浏览器解析HTML内容
客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
在浏览器地址栏键入URL,按下回车之后会经历以下流程:
- 浏览器向DNS服务器请求解析该URL中的域名所对应的IP地址;
- 请求IP的过程会先搜索本地缓存是否加载过这些数据,依次查询
浏览器缓存
、系统缓存
、路由器缓存
; - 都没找到的话,就开始DNS解析过程,解析过程是的采用迭代查询,依次按照
ISP(运营商)DNS缓存
、根域名服务器
、顶级域名服务器
、主域名服务器
的顺序,逐步读取缓存,直到拿到IP地址; - 解析完IP地址后,根据IP和端口号和服务器建立TCP连接;
- TCP连接建立过程就是三次握手,首先客户端向处于监听状态的服务器发送代表同步的一报文数据,其中syn=1,发送完成后进入同步已发送状态,服务器收到响应后发送SYN+ACK数据,进入同步已接受状态;客户端接收到响应后,再发送ACK数据进入连接已建立状态。这时三次握手就完成了。
- 浏览器发出读取文件的http请求报文;服务器收到后发送http响应报文
- 浏览器接收到HTTP响应报文后,会取出主体部分,进行渲染和显示。
HTTP请求格式(请求协议)
URL中包含:/index?a=1&b=2;路径和参数都在这里。
HTTP响应格式
和请求和响应格式都是由请求/响应行、请求/响应头、请求数据/响应正文三部分组成。
不同的是,请求格式中请求行是由请求方法,url,协议版本组成
而,响应行是由协议版本,状态码,状态码描述组成
常见的状态码
状态码的第一个数字代表当前响应的类型:
- 1xx消息–请求已被服务器接收,继续处理。
- 2xx成功–请求已成功的被服务器接收、理解并接受
- 3xx重定向–需要后续的操作才能完成这一请求
- 4xx请求错误–请求含有词法错误或者无法被执行
- 5xx服务器错误–服务器在处理某个正确请求时发送错误
状态码 | 状态码英文描述 | 中文描述 |
---|---|---|
100 | Continue | 继续,客户端继续其请求 |
101 | Switch Protocals | 切换协议。服务器根据客户端的请求切换协议。 |
200 | OK | 请求成功一般用于GET和POST请求 |
---|---|---|
201 | Create | 已创建。成功请求并创建了新的资源 |
202 | Accepted | 已接受。已经接收请求,但未处理完成 |
204 | No Content | 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 |
205 | Reset Content | 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域 |
206 | Partial Content | 部分内容。服务器成功处理了部分GET请求 |
300 | Multiple Choices | 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于浏览器选择 |
---|---|---|
301 | Moved Permanently | 永久移动,请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 |
302 | Found | 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI |
303 | See Other | 查看其它地址。与301类似。使用GET和POST请求查看 |
304 | Not Modified | 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 |
305 | Use Proxy | 使用代理。所请求的资源必须通过代理访问 |
306 | Unused | 已经被废弃的HTTP状态码 |
400 | Bad Request | 客户端请求的语法错误,服务器无法理解。 |
---|---|---|
401 | Unauthorized | 请求要求用户的身份认证 |
402 | Payment Required | 保留,将来使用 |
403 | Forbidden | 服务器理解客户端的请求,但拒绝执行该请求 |
404 | Not Found | 服务器无法根据客户端的请求找到资源(网页)。 |
405 | Method Not Allowed | 客户端请求中的方法被禁止 |
406 | Not Acceptable | 服务器无法根据客户端请求的内容特性完成请求 |
407 | Proxy Authentication Required | 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权 |
408 | Request Time-out | 服务器等待客户端发送的请求时间过长,超时 |
409 | Conflict | 服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突 |
410 | Gone | 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置 |
411 | Length Required | 服务器无法处理客户端发送的不带Content-Length的请求信息 |
412 | Precondition Failed | 客户端请求信息的先决条件错误 |
413 | Request Entity Too Large | 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息 |
414 | Request-URI Too Large | 请求的URI过长(URI通常为网址),服务器无法处理 |
415 | Unsupported Media Type | 服务器无法处理请求附带的媒体格式 |
416 | Requested range not satisfiable | 客户端请求的范围无效 |
500 | Internal Server Error | 服务器内部错误,无法完成请求 |
---|---|---|
501 | Not Implemented | 服务器不支持请求的功能,无法完成请求 |
502 | Bad Gateway | 作为网关或者代理工作的服务器尝试请求时,从远程服务器接收到了一个无效的响应 |
503 | Service Unavailable | 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 |
504 | Gateway Time-out | 充当网关或代理的服务器,未及时从远端服务器获取请求 |
505 | HTTP Version not supported | 服务器不支持请求的HTTP协议的版本,无法完成处理 |
HTTP请求方法
HTTP/1.1协议中共定义了八种方法(也叫“动作”)来以不同方式操作指定的资源:
GET | 发送请求来获取服务器上的资源,请求体中不包含请求数据,请求数据放在请求行中 |
---|---|
HEAD | 与GET方法类似不过不要求服务器返回响应数据,只需要返回头部信息。主要用来检查资源或超链接的有效性或是否可以可达、检查网页是否被串改或更新,获取头信息等,特别适用在有限的速度和带宽下。 |
POST | 向服务器提交数据让服务器进行处理。请求资源放在请求数据中。这种方法可能导致建立新的资源或者对原有资源的修改 |
PUT | 向指定资源上传其最新内容 |
DELETE | 请求服务器删除Request-URI所标识的资源 |
CONNECT | HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。就是把服务器作为跳板,去访问其他网页然后把数据返回回来,连接成功后,就可以正常的get、post了。 |
OPTIONS | 获取http服务器支持的http请求方法,允许客户端查看服务器的性能,比如ajax跨域时的预检等。 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断。一般禁用,防止被恶意攻击或盗取信息。 |
GET和POST的比较
GET 和 POST 只是 HTTP 协议中两种请求方式,而 HTTP 协议是基于 TCP/IP 的应用层协议,无论 GET 还是 POST,用的都是同一个传输层协议,所以在传输上,没有区别。
GET
GET请求的数据会附在URL后面以?号分割URL和传输数据,参数之间以&相连。对于某些数据需要进行转换。
数组或者字符 | 原样发送 |
---|---|
空格 | 转换为+ |
中文/其他字符 | 字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。 |
GET主要用于信息获取,并不会修改服务器数据是幂等的。
由于GET请求是附在URL后面,所以一般是具有长度限制的,但是这并不是http协议的限制,主要是由于浏览器和服务器共同决定的。
GET请求会被浏览器主动cache,而POST不会,除非手动设置。
POST
POST 表示可能修改服务器上的资源的请求,所以不是幂等的。
POST把提交的数据包放置在HTTP的包体中。
POST不会被主动cache,除非手动设置。
GET一定放URL,POST一定放BODY吗?
这些都是约定好的并不是硬性要求,如果非要把get请求的参数放到http包体当中,post请求放到url上也可以,只要在服务器端做好支持就行。
POST方法比GET方法安全
由于GET方法直接将请求数据放到了URL上,所以相对而言POST方法更加安全些。
但是本质上http都是明文传输的,都容易被抓包获取,所以这一点点安全性的区别基本上没什么影响。
想要安全传输就只有加密的传输,也就是https。
因此只能说GET比POST更不安全。
POST 方法会产生两个 TCP 数据包?
之前知乎上有一篇博客名为99%的人都理解错了HTTP中GET与POST的区别引起了很大的讨论,POST请求是否真的一定是发送2个TCP数据包,将HEADER和BODY分开发送的呢?
随后的一篇博客听说『99% 的人都理解错了 HTTP 中 GET 与 POST 的区别』??仔细趴了一下这个问题。
首先结论是错误的,并不是POST一定发送两个TCP数据包。HTTP 协议中没有明确说明 POST 会产生两个 TCP 数据包,并且实际测试(Chrome)发现,POST请求的header 和 body 也没有分开发送。因此,header 和 body 分开发送是部分浏览器或框架的请求方法,不属于 post 必然行为。
Cookie
为什么要用cookie
由于http本身是无状态保存的,即无状态协议(stateless)。http协议自身不对请求和响应之间的通信状态进行保存。也就是说在HTTP这个 级别,协议对于发送过的请求或响应都不做持久化处理。这种设计是为了能更快的处理大量事务,确保协议的可伸缩性。但是,这种设计带来了一个问题。比如,用户登录功能,登录之后跳转到其他界面也需要保持登录状态。对于这种情况,服务器端需要能分辨出这是谁发送的请求,需要保存用户信息。而HTTP/1.1虽然是stateless的,但是为了实现期望的功能,引入了Cookie技术来管理状态。
什么是cookie
Cookie实际上是一段文本信息(key-vakue格式)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就在response中头部添加Set-Cookie向客户端颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,会把Cookie添加到请求头一同提交给服务器。服务器通过检查Cookie来辨认用户状态。
Cookie机制
当用户第一次访问并登录一个网站时,Cookie的设置和发送会经过如下四个步骤:
- 客户端向服务器发送请求;
- 服务器发送一个HttpResponse响应到客户端,其中包括Set-Cookie的头部;
- 客户端保存Cookie,之后向服务器发送请求会包含一个Cookie头部;
- 服务器返回响应数据。
进行代码测试,看是否设置服务器颁发好Cookie后,客户端下次请求是否带Cookie
新建个JavaWeb工程,在其中写个doGet方法
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
Cookie cookie = new Cookie("mcrwayfun",System.currentTimeMillis()+"");
//设置生命周期
cookie.setMaxAge(Integer.MAX_VALUE);
response.addCookie(cookie);
}
可以看到,cookie已经成功的设置好了,并且Request Headers中也带有设置好的Cookie
Cookie的属性项
属性项 | 属性项描述 |
---|---|
NAME=VALUE | 保存到键值对,注意NAME得唯一 |
Expires | 过期时间,在设置的某个时间点后该Cookie就会失效 |
Domain | 生成该Cookie的域名 |
Path | 该Cookie是在哪个路径下生成的 |
Secure | 如果设置了这个属性,那么只会在SSH连接时才会传回该Cookie |
Expires
该属性用来设置Cookie的有效期。Cookie中的maxAge用来表示该属性,单位为秒。Cookie中通过getMaxAge()和setMaxAge(int maxAge)来读写该属性。maxAge有3种值,分别为正数,负数和0。
浏览器会将正数的Cookie持久化保存(写入到文件中)。只要在有效时间以前都将有效
当maxAge为负时,表示是一个临时Cookie,不会被持久化,仅在本浏览器窗口或者本窗口打开的子窗口中有效,关闭浏览器后该Cookie立即失效。
当maxAge为0时,表示立即删除Cookie
修改或删除Cookie
HttpServletResponse提供的Cookie操作只有一个addCookie(Cookie cookie),所以需要删除或修改的话只能覆盖。
值得注意的是,从客户端读取Cookie时,包括maxAge在内的其他属性都是不可读的,也不会被提交。浏览器提交Cookie时只会提交name和value属性。这些不被提交的属性主要是用于客户端自己判断,没必要再提交给服务器。
Cookie的域名
Cookie是不能跨域名的,隐私安全机制禁止网站非法的获取其他网站的Cookie。
正常情况下,同一个一级域名下的两个二级域名也不能交互使用Cookie,比如test1.mcrwayfun.com和test2.mcrwayfun.com,因为二者的域名不完全相同。如果想要mcrwayfun.com名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数为**.mcrwayfun.com**,这样使用test1.mcrwayfun.com和test2.mcrwayfun.com就能访问同一个cookie
一级域名又称为顶级域名,一般由字符串+后缀组成。熟悉的一级域名有baidu.com,qq.com。com,cn,net等均是常见的后缀。
二级域名是在一级域名下衍生的,比如有个一级域名为mcrfun.com,则blog.mcrfun.com和www.mcrfun.com均是其衍生出来的二级域名。
Cookie的路径
path属性决定允许访问Cookie的路径。比如,设置为"/"表示允许所有路径都可以使用Cookie
Cache
为什么要用Cache
当网络中存在大量用户通过请求的方式获取资源时,大量的请求往返于客户端和服务器之间,使得资源的可用时间已经浏览器可处理他们的时间都有了延时。这种情况下,通过建立缓存(cache)来重用已获取的资源是优化前端性能的一个关键点。
什么是缓存,缓存的优点
缓存就是将已经请求到的内容放到一个就近的仓库存放起来,下次请求可以不向服务器请求,而是直接从缓存仓库里面提取。
Web缓存主要有一下几个优势
- 减少网络延时,加快页面响应速度,增强用户体验
- 减少网络带宽的消耗
- 减轻服务器的压力
Web缓存的种类
web缓存类型 | 描述 |
---|---|
数据库缓存 | 当web应用关系复杂,数据表蹭蹭蹭往上涨时,可以将查询后的数据放到内存中进行缓存,下次再查询时,就直接从内存缓存中获取,从而提高响应速度。 |
CDN缓存 | 我们发送一个web请求时,CDN会帮我们计算去哪得到这些内容的路径短且快。这个是网站管理员部署的,所以他们也可以将大家经常访问的内容放在CDN里,从而加快响应。 |
代理服务器缓存 | 代理服务器缓存,跟浏览器缓存性质类似,但是代理服务器缓存面向的群体更广,规模更大。它不只为一个用户服务,一般为大量用户提供服务,同一个副本会被重用多次,因此在减少响应时间和带宽使用方面很有效。 |
浏览器缓存 | 每个浏览器都实现了 HTTP 缓存,我们通过浏览器使用HTTP协议与服务器交互的时候,浏览器就会根据一套与服务器约定的规则进行缓存工作。当我们在浏览器中点击前进 和后退 按钮时,利用的便是浏览器的缓存机制。 |
http中的Cache机制
- 当新资源第一次被访问时,响应头携带了对当前资源的描述信息
-
最后修改时间:last-modified
-
资源状态唯一标识符: etag
-
资源在客户端缓存过期时间:Expires
同时浏览器会将资源缓存到Cache目录,并保存文件描述信息。
- 当客户端第二次请求资源时,会先检查cache目录中是否含有该资源,如果有,并且还没到Expires设置的时间,
即文件还没有过期,那么此时客户端将直接从Cache目录中读取文件,而不再发送请求。 - 如果资源已经过期,客户端会发送一次http请求到服务器,同时在header携带上次修改的时间:
If-Modified-Since Fri, 10 Sep 2021 03:44:21 GMT
If-None-Match "8fb8b-14-4794674acdcc0"
web服务器接收到请求后,会解析header的信息,如果该资源从上次时间到现在都没有修改或者Etag信息没变化,则返回304状态码(即只返回头部信息,不包含具体响应数据,这是因为服务器认为请求数据未修改)。
这样,就能够很大程度上减少网络带宽以及提升用户的浏览器体验。
当然,如果服务器经过匹配发现文件修改过了,就会将文件资源返回,并带上新文件状态信息。
基本参数
Expires:
文件在本地缓存的过期时间,如果客户端发现缓存中的文件没有过期,则不发送请求
Cache-Control:
Cache-Control指定请求和响应遵循的缓存机制。
请求的缓存指令包括
no-cache
,no-store
,max-age
,max-stale
,min-fresh
,only-if-cached
响应消息中的指令包括
public
,private
,no-cache
,no-store
,no-transform
,must-revalidate
,proxy-revalidate
,max-age
指令 | 指令含义 |
---|---|
public | 响应可被任何缓存区缓存。 |
Private | 对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。 |
no-cache | 请求或响应消息不能缓存。 |
no-store | 用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。 |
max-age | 客户端可以接收生存期不大于指定时间(以秒为单位)的响应。 |
min-fresh | 客户机可以接收响应时间小于当前时间加上指定时间的响应。 |
max-stale | 客户端可以接收超出超时期间的响应消息。 如果指定max-stale消息的值,那么客户端可以接收超出超时期指定值之内的响应消息。 |
参考博客
HTTP协议超级详解
GET 和 POST 的区别
浅谈HTTP中Get与Post的区别
听说『99% 的人都理解错了 HTTP 中 GET 与 POST 的区别』??
99%的人都理解错了HTTP中GET与POST的区别
深入理解Cookie
深入理解HTTP Cache(HTTP Caching译文+理解)
HTTP请求的缓存(Cache)机制