

简述HTTP协议
source link: https://www.tuicool.com/articles/Mv2q2qj
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

身为开发人员除了应该对我们所写的项目需求要了解,以及基本的语言知识,对于 HTTP
协议应该也是应该了解一下的,因为这些东西与我们是密不可分的,每天都在和 HTTP
打交道然而却不知道它到底是什么?这样说出去是不是很可悲?简直可歌可泣有没有...
http协议 :HTTP是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII码形式给出;而消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使得开发和部署是那么的直截了当。超文本传输协议( HTTP
)是用于传输诸如 HTML
的超媒体文档的应用层协议。它被设计用于 Web
浏览器和 Web
服务器之间的通信,但它也可以用于其他目的。 HTTP
遵循经典的客户端-服务端模型,客户端打开一个连接以发出请求,然后等待它收到服务器端响应。 -- 百度百科
HTTP
是无状态协议,意味着服务器不会在两个请求之间保留任何数据(状态)。在同一个连接中,两个执行成功的请求之间是没有关系的。这就带来了一个问题,用户没有办法在同一个网站中进行连续的交互,比如在一个电商网站里,用户把某个商品加入到购物车,切换一个页面后再次添加了商品,这两次添加商品的请求之间没有关联,浏览器无法知道用户最终选择了哪些商品。而使用 HTTP
的头部扩展, HTTP Cookies
就可以解决这个问题。把 Cookies
添加到头部中,创建一个会话让每次请求都能共享相同的上下文信息,达成相同的状态。通过上述得出结论, http
特点是:无状态,无连接,简单快速。
HTTP交互流程
一个连接是由传输层来控制的,这从根本上不属于 HTTP
的范围。 HTTP
并不需要其底层的传输层协议是面向连接的,只需要它是可靠的,或不丢失消息的(至少返回错误)。在互联网中,有两个最常用的传输层协议: TCP
是可靠的,而 UDP
不是。因此, HTTP
依赖于面向连接的 TCP
进行消息传递,但连接并不是必须的。
- TCP:面向连接(如打电话要先拨号建立连接)
- UDP:是无连接的,即发送数据之前不需要建立连接
关于 TCP
和 UDP
这里不做多余赘述,如果想要深入了解两者之间的优缺点以及区别的话,有时间再详细的介绍一下。
其实 HTTP
交互流程就是基于 TCP
连接进行消息传递的,然而这个连接可有可无,具体交互流程如下图:
结合上图详细说明经历的过程:
- 打开一个TCP连接:TCP连接被用来发送一条或多条请求,以及接受响应消息。客户端可能打开一条新的连接,或重用一个已经存在的连接,或者也可能开几个新的TCP连接连向服务端
- 发送一个HTTP报文:HTTP报文(在HTTP/2之前)是语义可读的。在HTTP/2中,这些简单的消息被封装在了帧中,这使得报文不能被直接读取,但是原理仍是相同的
- 读取服务端返回的报文信息,服务器端接收到请求后,进行处理,然后将处理结果响应客户端(HTTP协议)
- 关闭连接或者为后续请求重用连接,关闭客户端和服务器端的连接(HTTP1.1后不会立即关闭)
当 HTTP
流水线启动时,后续请求都可以不用等待第一个请求的成功响应就被发送。然而 HTTP
流水线已被证明很难在现有的网络中实现,因为现有网络中有很多老旧的软件与现代版本的软件共存。因此, HTTP
流水线已被在有多请求下表现得更稳健的 HTTP/2
的帧所取代。
HTTP报文
在 Linux
系统下有一个 curl
指令可以通过这个命令来观测一下 HTTP
的请求过程。
curl -v https://segmentfault.com/
输入完之后回车就会看到下面这些信息:
图中 >
开始的是客服端发送给服务端的信息,以 <
开始的为服务端返回给客户端的一些信息。当客户端发起一个 Ajax
请求时,浏览器会携带一些信息发送给服务端, HTTP
请求头提供了关于请求,响应或者其他的发送实体的信息。请求报文分为以下几个部分:
- General(请求行)
- Response Headers(请求头)
- Request Headers(响应头)
这三个部分分别承载了服务端以及客户端所需要的信息,在浏览器中种 NetWork
中可以查看到其信息内容,接下来就一一介绍一下:
General
这部分主要提供的是一些公用的请求头信息:
Request URL: https://segmentfault.com/search?q=search Request Method: GET Status Code: 200 Remote Address: 112.126.83.219:443 Referrer Policy: no-referrer-when-downgrade
- Request URL:请求地址
- Request Method:请求方式
- Status Code:状态码
- Remote Address:请求的远程地址
- Referrer Policy: 过滤 Referrer 报头内容
上述信息表明,客户端向服务器发送一个 http
请求,其请求地址为 https://segmentfault.com/search?q=search
,使用 GET
方式发起这个请求,请求返回状态为 200
,连接的远程地址为 112.126.83.219:443
,过滤报头采用的是不传递 Referrer
。
向前面几个应该都比较熟悉也通俗易懂,当看到的这的时候心里有一些些的小疑惑 Remote Address
是什么? Referrer Policy
过滤报头的规则有哪些?
Remote Address
关于 Remote Address
远程连接地址, Remote Address
代表客户端的 IP
,但它的值不是由客户端提供的,而是服务端根据客户端的 IP
指定的,当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的 web
服务器( Nginx,Apache
等)就会把 Remote Address
设为你的机器IP,如果你用了某个代理,那么你的浏览器会先访问这个代理,然后再由这个代理转发到网站,这样web服务器就会把 Remote Address
设为这台代理机器的 IP
。以至于后面的 443
端口,也简单的看了一下, 443
端口即网页浏览端口,主要是用于 HTTPS
服务,是提供加密和通过安全端口传输的另一种 HTTP
。在一些对安全性要求较高的网站,比如银行、证券、购物等,都采用 HTTPS
服务,这样在这些网站上的交换信息,其他人抓包获取到的是加密数据,保证了交易的安全性。我也没有做深入的了解,大概就是这个样子吧。
Referrer Policy
Referrer-Policy
的作用就是为了控制请求头中 referrer
的内容,目前是一个候选标准,不过已经有部分浏览器支持该标准。目前 Referrer-Policy
只包含以下几种值:
Referrer-Policy
值不是固定不变的,而是可是通过程序手动设置,一般都会不会去手动更改除非网页中不存在一些敏感信息,那就默认使用 no-referrer-when-downgrade
。这里就多说了,如果有兴趣的可以调研一下。
Response Headers
这部分存储的是响应头信息,当服务端接受到请求,并处理完成之后需要向客户端做出应答。
cache-control: no-store, no-cache, must-revalidate content-encoding: gzip content-type: text/html; charset=UTF-8 date: Fri, 28 Jun 2019 09:32:09 GMT expires: Thu, 19 Nov 1981 08:52:00 GMT pragma: no-cache status: 200 strict-transport-security: max-age=15768000; preload x-hit: web1
- cache-control:响应输出到客户端后,服务端通过该报文头告诉客户端如何控制响应内容的缓存
- content-encoding:文档编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型
- content-type:文档类型
- date:当前的GMT时间,可以用setDateHeader来设置
- expires:文档过期时间,文档到期后则不再缓存
- pragma:设置消息头,(no-cache)强制清除缓存
- status:服务器响应状态码
- strict-transport-security:安全功能,它告诉浏览器只能通过HTTPS访问当前资源,而不是HTTP
Request Headers
这部分承载的是请求头的信息,当客户端向服务端发送请求时,需要传递给服务端的信息内容。
:authority: segmentfault.com :method: GET :path: /search?q=1 :scheme: https accept: text/html,application/xhtml+xml,application/xml; accept-encoding: gzip, deflate, br accept-language: zh-CN,zh;q=0.9 cookie: e23800c454aa573c0ccb16b52665ac26=1561712973 referer: https://segmentfault.com/ user-agent: Chrome/75.0.3770.100 Safari/537.
- :authority:请求权限(HTTP2.0)
- :method:请求方式(HTTP2.0)
- :path:请求地址(HTTP2.0)
- :scheme:请求协议(HTTP2.0)
- accept:指定客户端可以接受的内容类型,比如文本,图片,应用等等,内容的先后排序表示客户端接收的先后次序,每种类型之间用逗号隔开。
- accept-encoding:客户端接收编码类型,一些网络压缩格式:Accept-Encoding: gzip, deflate, sdch。相对来说,deflate是一种过时的压缩格式,现在常用的是gzip
- accept-language:客户端可以接受的语⾔言类型,参数值规范和 accept的很像。一般就接收中文和英文,有其他语言需求自行添加。
- cookie:同样是一个比较关键的字段,Cookie是 client 请求服务器时,服务器会返回一个键值对样的数据给浏览器,下一次浏览器再访问这个域名下的网页时,就需要携带这些键值对数据在 Cookie中,用来跟踪浏览器用户的访问前后路径。
- referer:浏览器上次访问的网页url,uri。由于http协议的无记忆性,服务器可从这里了解到客户端访问的前后路径,并做一些判断,如果⼀一次访问的 url 不能从前一次访问的页面上跳转获得, 在一定程度上说明了请求头有可能伪造。
- user-agent:中文名用户代理,服务器从此处知道客户端的操作系统类型和版本,电脑CPU类型,浏览器 种类版本,浏览器渲染引擎,等等。
accept-language
共分为下列几种:
zh-CN:中文简体大陆 zh:其他中文 en-US:英语美语 en:其他英语
Cookie
就是存储在客户端的一小段文本,因为 cookie
是存储在客户端浏览器中的, Cookie
不能作为代码执行,也不会传送病毒,且为你所专有,并只能由提供它的服务器来读取。保存的信息片断以 名/值
对( name-value
)的形式储存,一个 名/值
对仅仅是一条命名的数据。一个网站只能取得它放在你的电脑中的信息,它无法从其它的 cookie
文件中取得信息,也无法得到你的电脑上的其它任何东西。
const express = require('express'); const cookieParser = require('cookie-parser'); var app = express(); app.use(cookieParser('sign')); app.get('/set', function(req, res) { res.cookie('name', 'TracyYu', {maxAge: 9999999, httpOnly: true, signed: true}); res.send('cookie设置成功'); }) app.get('/get', function(req, res) { console.log(req.signedCookies); res.send('success') }) app.listen('3000', function() { console.log('3000成功'); })
通过上面代码中对 cookie
进行设置之后,用户访问 /set
路由的是时候已经把 cookie
设置到了浏览器的头部,当用户访问 /get
路由的时候,由于在浏览器中已经设置好 cookie
,在同属于一个服务的情况下是可以直接获取到 cookie
的。当然除了上述所说,通过 document
也是可以手动设置 cookie
的,在客户端设置的 cookie
在服务端同样是也可以获取到的。
document.cookie="userId=929";
这样就将名为 userId
的 cookie
值设置为了 929
,现在访问 /get
同样就能拿到在客户端设置的 cookie
值了。
请求方式
http
中经常用的到的就是 get
和 post
两种,在开发过程中会遵循 RESTful
接口风格,这是一种现在比较流行的接口风格,使用这种接口风格需要用到一些其他的请求方式, http
请求方式一共有 8
种。
HTTP
定义了与服务器交互的不同方法,最基本的方法是 GET
和 POST
(开发关心的只有 GET
请求和 POST
请求)。
GET和POST长度的限制问题
GET POST GET是通过URL提交数据,因此GET可提交的数据量就跟URL所能达到的最大长度有直接关系 HTTP协议没有对POST进行任何限制,一般是受服务器配置限制或者内存大小 HTTP协议对URL长度是没有限制的;限制URL长度大多数是浏览器或者服务器的配置参数 PHP下可以修改php.conf的postmaxsize来设置POST的大小 其实这里有一个很大的误区, http
协议并未规定 GET
和 POST
的长度限制, GET
的最大长度限制是因为浏览器和 web
服务器限制了 URL
的长度,不同的浏览器和 web
服务器,限制的最大长度不一样,要支持 IE
,则最大长度为 2083byte
,若支持 Chrome
,则最大长度 8182byte
,首先即使 GET
有长度限制,也是限制的整个 URL
的长度,而不仅仅是参数值数据长度。
GET和POST的安全性
- GET是通过URL方式请求,可以直接看到,明文传输
- POST是通过请求header请求,可以开发者工具或者抓包可以看到,同样也是明文的
- GET请求会保存在浏览器历史纪录中,还可能会保存在Web的日志中
GET
请求指定资源的表示形式。注意, GET
不应该用于产生副作用的操作,比如在 web
应用程序中使用它执行操作。原因之一是 GET
可能被机器人或爬行器任意使用,它们不需要考虑请求应该引起的副作用。 POST
将要处理的数据(例如,从 HTML
表单)提交给标识的资源。数据包含在请求体中。这可能会导致创建新资源或更新现有资源,或者两者兼而有之。使用 HTTP
协议的服务不应该使用基于 GET
的表单来提交敏感数据,因为这会导致这些数据在 Request-URI
中编码。许多现有服务器,代理和用户代理会将请求 URI
记录在第三方可能看到的某个位置。服务器可以使用基于 POST
的表单提交。
GET与POST请求过程
POST
请求的过程:
- 浏览器请求tcp连接(第一次握手)
- 服务器答应进行tcp连接(第二次握手)
- 浏览器确认,并发送post请求头(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)
- 服务器返回100 Continue响应
- 浏览器发送数据
- 服务器返回200 OK响应
GET
请求的过程:
- 浏览器请求tcp连接(第一次握手)
- 服务器答应进行tcp连接(第二次握手)
- 浏览器确认,并发送get请求头和数据(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)
- 服务器返回200OK响应
总结
原本想说一写状态码相关的东西,但是简单的看了一下,好像又没有什么好说的,百度百科说的也很清楚,就不在文章里面赘述了。
简单的对 http
协议做了一些小的介绍与总结,如果文章中有哪些地方有问题,请在下方留言指正,我会尽快做出改正。
Recommend
-
103
翻译:赵菁菁(轩语轩缘)审校:李笑达(DDBC4747)简介嗨,我是baldurk。我已经做了几年的图形程序员,所以虽然我不是一名专家,但我想我对图形工作有一点了解。这一系列的文章的想法已经在我的脑海
-
72
入门 | 简述迁移学习在深度学习中的应用
-
56
Meltdown 简简述 近日现代 CPU 的 Meltdown & Spectre 漏洞沸沸扬扬,最早是 Google 研究员发现
-
44
-
79
dom转image原理简述
-
64
前言 看到 TJ 大神 star了dom-to-image,也一直很好奇html怎么转 image 那么就翻下源码,看下是如何实现的,其实一共就不到800行代码,还蛮容易读懂的 工作原理 使用svg的一个特性,允许在<foreignobject>标
-
41
-
6
Kademlia协议简述 1 基本介绍 分布式哈希表(DHT )是一类去中心化的技术,提供了节点之间的查找服务。 通常在一个中心化系统中,中心节点可以负责管理子...
-
22
http://http://http://@http://http://?http://#http:// | daniel.haxx.se
-
5
简述网络协议与 iOS 下的网络请求 在学习网络协议过程中, 我一直很迷惑各个协议之间的关...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK