
一HTTP1.1 HTTP是什么HTTP(全称为超文本传输协议)是⼀种应用非常广泛的应用层协议HTTP往往是基于传输层的TCP协议实现的.(HTTP1.0,HTTP1.1,HTTP2.0均为TCP,HTTP3基于 UDP实现)目前我们主要使用的还是HTTP1.1和HTTP2.0我们平时打开⼀个网站就是通过HTTP协议来传输数据的浏览器就相当于http客户端不只是浏览器手机app也用http和服务器通信注意https和http的绝大部分功能是一样的http是基础而https在此基础上添加了额外的加密功能带有安全机制的http当我们在浏览器中个搜输入一个搜索的网址(URL)时浏览器就给搜狗的服务器发送了⼀个HTTP 请求搜狗的服务器返回了⼀个HTTP响应.。这个响应结果被浏览器解析之后就展示成我们看到的页面内容。(这个过程中浏览器可能会给服务器发送多个HTTP请求服务器会对应返回多个响应这些响应里就包含了页面HTMLCSSJavaScript图片字体等信息).所谓超文本的含义就是传输的内容不仅仅是文本(比如htmlcss这个就是文本)还可以是⼀些其他的资源比如图片视频音频等二进制的数据1.2 理解应用层协议我们已经学过TCP/IP 已经知道⽬前数据能从客⼾端进程经过路径选择跨⽹络传送到服务器端进程 IPPort可是仅仅把数据从A点传送到B点就完了吗这就好比在淘宝上买了⼀部手机卖家[客户端]把手机通过顺丰[传送路径选择]送到买家[服务 器]手里就完了吗 当然不是买家还要使用这款产品还要在使用之后给卖家打分评论所以我们把数据从A端传送到B端 TCP/IP 解决的是顺丰的功能而两端还要对数据进行加工处理或者使用所以我们还需要⼀层协议不关心通信细节关心应用细节 这层协议叫做应用层协议。而应用是有不同的场景的所以应用层协议是有不同种类的其中经典协议之⼀的HTTP就是其中的佼佼者顺丰相当于 TCP/IP 的功能那么买回来的手机都附带了说明书【产品介绍使⽤介绍注意事项等】而该说明书指导用户该如何使用手机此时的说明书可以理解为用户层协议1.3 HTTP协议格式HTTP是⼀个文本格式的协议可以通过Chrome开发者工具或者Fiddler抓包分析HTTP请求/响应 的细节1.4 抓包工具的原理Fiddler 相当于⼀个代理浏览器访问sogou.com时就会把HTTP请求先发给FiddlerFiddler再把请求转发给sogou的服务 器。当sogou服务器返回数据时Fiddler拿到返回数据再把数据交给浏览器。因此Fiddler对于浏览器和sogou服务器之间交互的数据细节,都是非常清楚的1.4.1 抓包结果HTTP请求这里的字符串就是完整的HTTP请求数据包如果把这个字符串拷贝下来通过tcp socket写进去此时就相当于发送了一个HTTP请求请求格式如图可以看出这是按照行组织的按行组织的文本格式也称为“行文本”首行[方法] [url] [版本] 这三个之间用空格分割方法描述了这次请求要干什么url描述了要访问哪个资源Header请求的属性冒号空格分割的键值对。每组属性之间使用\n分隔遇到空行表示Header部分结束每一行都是一个键值对用“空格”来分割请求头的键值对都是标准约定好的不能随意修改Body空行后面的内容都是BodyBody允许为空字符串。如果Body存在则在Header中会有⼀个 Content-Length属性来标识Body的长度空行是请求头的结束标记所谓的HTTP协议就是按照特定格式构造了一个字符串客户端如果把这个字符串写入到tcp socket服务器就可以通过tcp socket把它读出来这样的字符串就是HTTP协议服务器还可以构造另一个特定格式的字符串也写入到tcp socket中客户端也可以通过tcp socket把这个字符串读出来这样的字符串就是HTTP响应HTTP响应响应格式首行[版本号] [状态码] [状态码解释]状态码成功还是失败Header请求的属性冒号空格分割的键值对。每组属性之间使用\n分隔。遇到空行表示Header部分结束Body空行后面的内容都是Body。Body允许为空字符串如果Body存在则在Header中会有一个 Content-Length属性来标识Body的长度。如果服务器返回了⼀个html页面那么html页面内容就是在body中.空行为响应头的结束标记其中HTTP传输的是文本字符串而响应中的二进制乱码本质上是HTTP服务器返回的数据进行了压缩压缩软件内部会有一些算法对数据进行重新计算重新编码就可以保证数据含义相同体积缩小fiddler中有解压缩功能即decode按钮可以进行解压缩 原始数据解压如下此处响应的body内容正是搜狗首页的htmlhtml描述结构css描述样式JavaScript描述行为为什么HTTP报文中要存在空行?因为HTTP协议并没有规定报头部分的键值对有多少个空行就相当于是报头的结束标记或者是 报头和正文之间的分隔符。HTTP在传输层依赖TCP协议TCP是面向字节流的如果没有这个空行就会出现粘包问题二HTTP请求(Request)2.1 URLHTTP请求中的URLURL不是http的一部分其实是独立于HTTP存在的URL会给很多种协议提供支持URL全称为唯一资源定位符描述了一个资源在网络上的位置2.2 URL基本格式平时我们俗称的网址其实就是说的URL(UniformResourceLocator统⼀资源定位符).互联网上的每个文件都有⼀个唯一的URL它包含的信息指出文件的位置以及浏览器应该怎么处理它。URL的详细规则由因特网标准RFC1738进行了约定.(https://datatracker.ietf.org/doc/html/rfc1738)举例 https://v.bitedu.vip/personInf/student?userId10000classId100https协议方案名。常见的有http和https也有其他的类型例如访问MySQL时用的是jdbcmysqluser:pass登录信息。现在的网站进行身份认证一般都不再通过url进行了所以现在不会把用户名密码放到url中一般登录专门有一个“登陆界面”v.bitedu.vip服务器地址。此处是一个域名域名会通过DNS系统解析成一个具体的IP地址这个服务器地址可以是域名也可以是ip地址端口号上述的url中端口号被省略了当端口号省略的时候浏览器会根据协议类型自动决定使用哪个端口例如http协议默认使用80端口号http协议默认使用443端口通过浏览器输入url访问http服务器就得知道对方服务器的端口号是多少/personInf/student带层次的文件路径。表示要访问的这个程序管理的哪个资源。服务器组织资源的时候也是按照“目录结构”形式组织的userId10000classId100查询字符串。本质是一个键值对结构键值对之间用分割键和值之间使用 分割查询字符串是携带参数对访问指定资源进行补充说明此处的键值对是程序员自己定义的片段标识此url中省略了片段标识。片段标识主要用于页面内跳转一般是文档类的网站会见到片段标识符2.3 关于URL encodequery string由于里面的数据是程序员自定义的可能会包含各种各样的内容各种各样的字符像/?:等这样的字符已经被url当做特殊意义理解了因此这些字符不能随意出现比如某个参数中需要带有这些特殊字符就必须先对特殊字符进行转义一个中文字符由UTF-8或者GBK这样的编码方式构成虽然在URL中没有特殊含义但是仍然需要进行转义。否则浏览器可能把UTF-8/GBK编码中的某个字节当做URL中的特殊符号把汉字或者特殊符号字符编码的每个字节使用十六进制表示出来使用 % 进行分割转义的规则如下将需要转码的字符转为16进制然后从右到左取4位(不足4位直接处理)每2位做一位前面加上%编码成 %XY 格式三HTTP请求中的方法3.1 GET 方法GET是最常用的HTTP方法常用于获取服务器上的某个资源。在浏览器中直接输入URL此时浏览器就会发送出一个GET请求另外HTML中的linkimgscript等标签也会触发GET请求。使用JavaScript中的ajax也能构造GET请求GET 请求通常情况下没有bodyGET请求的特点• 首行的第一部分为GET• URL的query string可以为空也可以不为空.• header部分有若干个键值对结构.• body部分为空实际URL的长度取决于浏览器的实现和HTTP服务器端的实现。在浏览器端不同的浏览器最大长度是不同的但是现代浏览器支持的长度⼀般都很长。在服务器端⼀般这个长度是可以配置的.3.2 POST 方法POST方法也是⼀种常见的方法多用于提交用户输入的数据给服务器(例如登陆页面和上传文件)。 通过HTML中的form标签可以构造POST请求或者使用JavaScript的ajax也可以构造POST请求POST请求的特点• 首行的第⼀部分为POST• URL的query string⼀般为空(也可以不为空)• header部分有若干个键值对结构.• body部分一般不为空。body内的数据格式通过header中的由header中的 Content-Type 指定。body的长度由header中的 Content-Length 指定3.3 GET 和 POST 的区别get和post没有本质区别主要的区别体现在使用习惯上使用get的时候可以替换成post使用post的时候也可以替换成get• 语义不同GET⼀般用于获取数据POST⼀般用于提交数据.• GET的body⼀般为空需要传递的数据通过url中的query string传递POST的query string⼀般为空需要传递的数据通过body传递• GET请求⼀般是幂等的POST请求⼀般是不幂等的.(如果多次请求得到的结果⼀样,就视为请求是幂等的).• GET可以被缓存POST不能被缓存.(这⼀点也是承接幂等性).补充说明• 关于语义: GET完全可以⽤于提交数据,POST也完全可以⽤于获取数据.• 关于幂等性: 标准建议GET实现为幂等的.实际开发中GET也不必完全遵守这个规则(主流⽹站都有 猜你喜欢功能,会根据⽤⼾的历史⾏为实时更新现有的结果.• 关于安全性: 有些资料上说POST⽐GET请安全.这样的说法是不科学的.是否安全取决于前端在 传输密码等敏感信息时是否进⾏加密,和GET POST⽆关.• 关于传输数据量: 有的资料上说GET传输的数据量⼩,POST传输数据量⼤.这个也是不科学的,标 准没有规定GET的URL的⻓度,也没有规定POST的body的⻓度.传输数据量多少,完全取决于不同浏览器和不同服务器之间的实现区别.• 关于传输数据类型: 有的资料上说GET只能传输⽂本数据,POST可以传输⼆进制数据.这个也是 不科学的.GET的query string虽然⽆法直接传输⼆进制数据,但是可以针对⼆进制数据进⾏url encode3.4 其他方法• PUT 与POST相似只是具有幂等特性⼀般⽤于更新• DELETE 删除服务器指定资源• OPTIONS 返回服务器所⽀持的请求⽅法• HEAD 类似于GET只不过响应体不返回只返回响应头• TRACE 回显服务器端收到的请求测试的时候会⽤到这个• CONNECT 预留暂⽆使⽤这些⽅法的HTTP请求可以使⽤ajax来构造.(也可以通过⼀些第三⽅⼯具)任何⼀个能进⾏⽹络编程的语⾔都可以构造HTTP请求.本质上就是通过TCPsocket写⼊⼀个符合 HTTP协议规则的字符串.其中put 和 delete 往往是和get 和 post 搭配使用的当遇到“Restful”风格的API设计即你写一个HTTP服务器给别人调用你的服务器能支持哪些HTTP请求并返回哪些HTTP响应称为“HTTP的API”而Restful是当前比较流行的HTTP API风格不同的操作通过不同的方法明确语义。其中关于增删查改的约定就有1使用GET 实现查询 2使用POST实现新增 3使用PUT实现修改 4使用DELETE实现删除四请求报头(header)header 的整体的格式也是键值对结构每个键值对占一行键和值之间使用分号分割4.1 HostHost表示服务器主机的地址和端口。描述了要访问的服务器的IP域名和端口号而这两个信息在URL里面也已经有了后续服务器收到数据可以针对HOST进行校验以确认这个请求是不是我这个服务器要收的请求--------------------4.2 Content-Length表示body中的数据长度单位是字节4.3 Content-Type表示请求的body中的数据格式浏览器/服务器会根据这里填写的两个内容理解bodyHTTP需要解决粘包问题如果确实数据格式有误浏览器/服务器试着“猜一下”猜一下body到哪里结束1tcp连接关闭了关闭前的数据就是一个HTTP数据包2tcp连接没有关闭紧接着收到了形如“GET xxxxxxxxxxxHTTP/1.1....”这样的就会认为之前的是一个HTTP数据包4.3.1 常见选项1application/x-www-form-urlencoded form 表单提交的数据格式.此时body的格式形如titletestcontenthello2multipart/form-data form 表单提交的数据格式(在form标签中加上 enctypedmultipart/form-data .通常用于提交图片/文件body格式形如------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; nameusername zhangsan ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; nameage 22 ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; nameavatar; filenamehead.jpg Content-Type: image/jpeg 这里是图片二进制字节流原始文件内容 ------WebKitFormBoundary7MA4YWxkTrZu0gW--3application/json 数据为json格式body格式形如{username:123456789,password:xxxx,code:jw7l,uuid:d110a05ccde64b16}小结请求中的Countent - Type给服务器看的1application/x-www-form-urlencoded2multipart/form-data3application/json响应中的Countent-Type给浏览器看的1text/html2text/css3application/JavaScript4application/json5image/png4.4 User-Agent (简称UA)描述用户使用什么样的设备上网表示浏览器/操作系统的属性形如Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)其中Windows NT 10.0; Win64; x64 表示操作系统版本AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 表示浏览器信息.其中AppleWebKit为浏览器内核Chrome/91.0.4472.77为浏览器版本为苹果系统自带的浏览器4.5 Referer表示这个页面是从哪个页面跳转过来的。如果直接在浏览器中输入URL或者直接通过收藏夹访问页面时是没有Referer的referer可以帮助我们追踪请求的来源4.6 CookieCookie 中存储了⼀个字符串这个数据可能是客户端网页)自行通过JS写入的也可能来自于服务器 (服务器在HTTP响应的header中通过Set-Cookie字段给浏览器返回数据).往往可以通过这个字段实现身份标识的功能.cookie中的值也是键值对cookie本质上是浏览器存储本地数据的一种机制比如浏览器打开一个网站都是现场的从服务器获取代码再执行的一个网页本身是无法进行本地存储的网页不能直接访问硬盘如果可以访问硬盘就太危险了就像很多网站会有夜间模式等等像这样当前页面是哪种模式的这种信息保存在浏览器本地就好了没必要从服务器获取所以浏览器就开了个口子虽然不能直接访问硬盘但是允许按照键值对的格式来存储数据不光是按照键值对存储的还按照不同的网站涉及到的键值对分别分开存储了小结1cookie 是干什么的浏览器本地存储数据的机制2cookie从哪里来服务器返回响应的时候通过响应报头写回到浏览器的服务器的响应中带有特殊的headerSet-Cookie种Cookie每个Set-Cookie对应一个键值对允许有多组3cookie要到哪里去本地存储不是目的真正的目的是后续要发回给服务器本地存储了cookie之后接下来给服务器发的请求中都会在header里带上cookie内容cookie中的键值对数据来自于服务器又要发回给服务器不是多此一举因为服务器会给很多个客户端提供服务cookie典型应用场景 - 登录使用cookie完成用户身份信息存储比如当前登录一个网站一旦登录完成后续访问这个网站的各个子页面都能够获取到我们的登录状态这也是基于cookie机制来实现的1最初注册的时候设置的密码会按照加密的形式保存再数据库中。在查询数据库的时候会拿着传输的密码加密后的效果和数据库里面的密码进行对比看是否正确2Session的保存也是键值对结构一个服务器可以同时有多个session每个客户端都对应一个。服务器给每个session分配一个唯一的sessionId作为key每个session分配一个session对象作为value服务器内存中有一个hash表存储了所有的会话数据一次会话session的多次交互可以是通过一个tcp连接完成的也可以是多个五HTTP响应5.1 状态码状态码用于告诉客户端请求是成功还是失败更重要的是可以告诉失败的原因状态码表示访问⼀个页面的结果.(是访问成功还是失败还是其他的⼀些情况...)以下为常见的状态码200 OK这是⼀个最常见的状态码表示访问成功404 NotFound404 NotFound 表示没有找到资源404一般是客户端的问题代表客户端发来的url中的资源不对403 Forbidden表示访问被拒绝有的页面通常需要用户具有⼀定的权限才能访问(登陆后才能访问)。如果用户没有登陆直接访问就容易见到403405 MethodNot AllowedHTTP中所支持的方法有GETPOSTPUTDELETE等。但是对方的服务器不⼀定都支持所有的方法(或者不允许用户使用⼀些其他的方法).500 Internal Server Error服务器出现内部错误⼀般是服务器的代码执⾏过程中遇到了⼀些特殊情况(服务器异常崩溃)会产⽣这个状态码。咱们平时常⽤的⽹站很少会出现500(但是偶尔也能看到)504 Gateway Timeout当服务器负载⽐较⼤的时候服务器处理单条请求的时候消耗的时间就会很⻓就可能会导致出现超时的情况.302 Movetemporarily302 Found临时重定向理解重定向就相当于⼿机号码中的呼叫转移功能.⽐如我本来的⼿机号是186-1234-5678,后来换了个新号码135-1234-5678,那么不需要让我的朋友知 道新号码, 只要我去办理⼀个呼叫转移业务,其他⼈拨打186-1234-5678,就会⾃动转移到135-1234-5678上.在登陆页面中经常会见到302用于实现登陆成功后自动跳转到主页响应报文的header部分会包含⼀个Location字段表示要跳转到哪个页面以码云为例301 MovedPermanently永久重定向当浏览器收到这种响应时后续的请求都会被自动改成新的地址301 也是通过Location字段来表示要重定向到的新地址301和302会影响到浏览器的缓存如果是用301重定向浏览器就会记住旧域名和新域名的对应关系如果使用302就不能缓存对应关系418 状态码定义HTTP标准协议的时候加入了418这个彩蛋没有任何意义状态码小结5.2 响应报头响应报头的基本格式和请求报头的格式基本⼀致类似于 Content-Type , Content-Length 等属性的含义也和请求中的含义⼀致Content-Type1text/html body数据格式是HTML2text/css body数据格式是CSS3application/JavaScript body数据格式是JavaScript4application/json body数据格式是JSON