超文本传输协议 HTTP(Hypertext Transfer Protocol)是一种用于在网络上传输超文本数据的应用层协议。它是万维网(World Wide Web)的基础,用于在客户端和服务器之间传输和交换信息,允许浏览器从Web服务器请求网页,并将服务器响应的网页呈现给用户。
Web页面 (也叫文档)是由对象组成。一个对象只是一个文件,诸如一个HTML文件,一个JPEG图形,一个JavaScript文件,一个CCS样式表文件,它们可通过一个URL寻址。Web浏览器实现了HTTP客户端;Web服务器实现了HTTP的服务器端,它用于储存Web对象,每个对象由URL寻址。HTTP定义了Web客户向Web服务器请求Web的方式,以及服务器向客户传送Web页面的方式。
HTTP报文格式
HTTP响应报文:
空行作用:因为 HTTP 协议并没有规定报头部分的键值对有多少个. 空行就相当于是 "报头的结束标记", 或者 是 "报头和正文之间的分隔符". HTTP 在传输层依赖 TCP 协议, TCP 是面向字节流的. 如果没有这个空行, 就会出现 "粘包问题".
响应报文首行:
状态码:对这次相应的定性
常见的几种状态码:
HTTP请求报文
http请求报文首行
格式:
URL基本格式
*https : 协议方案名. 常见的有 http 和 https, 也有其他的类型. (例如访问 mysql 时用的
jdbc:mysql).可以省略, 省略后默认为 http://
*user:pass : 登陆信息. 现在的网站进行身份认证一般不再通过 URL 进行了. 一般都会省略
*服务器地址. 此处可以是一个 “IP”地址,也可以是一个"域名", 域名会通过 DNS 系统解析成一个具体的 IP 地址。服务器地址也可以省略,省略时表示访问当前服务器。比如我此时在和b站首页,我要在b站进行下一步操作,这时就可以省略服务器地址。
*服务器端口号:用来区分应用程序。 URL 中端口号可以被省略. 当端口号省略的时候, 浏览器会根据协议类型自动决定使用哪个端口. 例如 http 协议默认使用 80 端口, https 协议默认使用 443 端口.
*带层次的文件路径:可以省略,省略后相当于 / . 相当于访问根目录(网站首页之类的)。
*查询字符串(query string). 访问网站时携带的参数。本质是一个键值对结构. 键值对之间使用 & 分隔. 键和值之间使用 = 分隔. 键值对的含义由开发者自定义 根据需要设定,可以省略。
*片段标识: 此 URL 中省略了片段标识. 片段标识主要用于页面内跳转.(可以省略并且不太常见,大都在文档类网站出现)
URL编码(URL encoding):
一种将特殊字符和非ASCII字符转换为特定格式的过程,以便在 URL 中进行安全传输和处理的操作。在 URL 中,某些字符具有特殊含义,如问号(?)、等号(=)、斜杠(/)、百分号(%)等,或者某些字符不被允许直接出现,比如空格、汉字等。
URL 编码的目的是保证 URL 的正确性和安全性。它使用一种特定的编码规则来将这些特殊字符转换为一些特定的字符序列.
比如c++就会被URL编码成:C%2B%2B
HTTP请求的方法:
GET方法和Post方法有什么区别?
1.语义不同:HTTP设计初,GET方法的语义是:向服务器获取资源,POST方法的语义是向服务器传输数据。但是慢慢的这种语义的要求被打破了。即GET方法和POST方法不一定遵守最初设定的语义。
2.GET请求一般是幂等的,POST请求一般是不幂等的:
RFC标准文档是这么建议的,但是后面逐渐的也慢慢不遵守这个约定了(猜你喜欢的功能)
3.自定义字符串的存放位置(主要区别):GET方法通常把自定义数据存储在quary string(查询字符串)当中,其body部分通常是空的(普遍和规范,没有规则规定)。查询字符串位于 URL 的问号(?)后面,参数则以键值对的形式表示。
虽然 HTTP 规范允许 GET 请求包含请求体,但这种使用方式很少见,并且不符合通常的约定。实际上,许多服务器和应用程序会忽略 GET 请求中的请求体,因为它们主要关注 URL 中的查询参数。
POST方法通常把自定义数据放在body中,quary string通常为空。
本质上它们都能实现传输数据给服务器,没有根本上的区别。但是:
进行登录操作时,通常涉及到密码和账户等敏感信息,如果使用GET方法将这些数据存储在URL的quary string 当中(可以直接看到)会造成一种不安全的错觉。
进行上传操作时,数据通常会很长,如果使用GET方法,将这些数据存储在URL当中,显得非常不优雅。
所以,POST方法通常在登录和上传时使用。其它大部分HTTP请求报文都是在使用GET方法。
注意,这里只是一个普遍和规范,并没有硬性要求和规定(RFC标准文档没有要求),GET方法也能实现POST的应用场景。三个字:”约定成俗“。
补充说明(针对网上一些关于二者区别的补充说明):
*关于语义: GET 完全可以用于提交数据, POST 也完全可以用于获取数据.
*关于幂等性: 标准建议 GET 实现为幂等的. 实际开发中 GET 也不必完全遵守这个规则(主流网站都有 "猜你喜欢" 功能, 会根据用户的历史行为实时更新现有的结果.
*关于安全性: 有些资料上说 "POST 比 GET 请安全". 这样的说法是不科学的. 是否安全取决于 前端在传输密码等敏感信息时是否进行加密, 和 GET POST 无关.
*关于传输数据量: 有的资料上说 "GET 传输的数据量小, POST 传输数据量大". 这个也是不科学 的, 标准没有规定 GET 的 URL 的长度, 也没有规定 POST 的 body 的长度. 传输数据量多少, 完全取决于不同浏览器和不同服务器之间的实现区别.
*关于传输数据类型: 有的资料上说 "GET 只能传输文本数据, POST 可以传输二进制数据". 这个 也是不科学的. GET 的 query string 虽然无法直接传输二进制数据, 但是可以针对二进制数据进行 url encode
*关于请求是否被缓存:这一点承接于幂等,幂等的请求一般会直接被缓存,于GET POST无直接关系。
请求报头(header部分):
HOST:表示服务器主机的地址和端口。
为什么在URL里面已经有这个信息了,这里还要再表示一遍? 在大部分情况这俩出的信息都是一样的,但是如果我们使用了代理。这俩处的情况就会存在差异:抓包时使用的Fiddler,一些加速工具等等。所以需要在这里再表示一遍。
Cotent-length:描述了body的长度。如果有的请求没有body,比如上面的截图,Cotent-length值为2,body部分只有一个括号。如果body不为空,这里就必须写上body的长度,否则就是一个非法请求。
解决粘包问题:要么使用分隔符要么设置字段保存长度。对于GET请求报文,body部分一般为空,所以使用分隔符。对于body部分不为空的请求报文,就设置Cotent-length记录长度。
Cotent-Type:主要包含以下三种情况:
*body的格式形如quary string:
*一般为上传图片或者文件数据时:
*body是json形式:
如果是响应,情况更复杂。
User-Agent(简称UA):
以登录b站的请求为例:
UA中主要包含了操作系统和浏览器的版本。对于我们当前设备来说,这一字段已经不太重要了,因为浏览器之间的功能和操作系统之间的功能已经大差不差了。但是在以前,浏览器和系统版本不同,支持的功能天差地别,比如是否支持视频等,而为了兼容更多的用户,开发者针对不同的设备的用户给他对应的响应。 现在,我们主要使用UA来区分用户是移动端和PC端。
Referer :描述了当前页面从哪个页面跳转过来。
上图是从浏览器首页跳转到b站的抓包。此时的Referer就是浏览器首页的URL。
可以使用这一字段来进行广告的点击来源的统计(你是从百度还是搜狗点击到这个广告,进而进行相关的利益统计。
Cookie:
保存一些浏览器访问时产生的临时数据,用于在多个请求之间维护会话状态。比如:你登陆某个页面时只要第一次输入了密码,后续的访问就不需要再输入账户密码了。但是你换个电脑就还是得重新登陆。
Cookie是按照键值对的方式来存储一些字符串信息,这些键值对往往是通过服务器返回产生,浏览器按照”域名“维度分类进行存储。即:不同的网站有其对应的Cookie。
为什么要设置一个Cookie来保存这些临时系统,不直接创建个文件?
让网站直接访问电脑的硬盘是一件很危险的事情,可能会引起很多安全问题(病毒等)。
Cookie中有一个很重要的键值对:表示用户的身份标识。刚才提到的登陆网站的例子就是通过这个身份标识来实现的。你第一次登陆网站时,网站就会返回给你一个表示身份标识的键值对,保存在Cookie当中,等你下次在登陆时,网站看到这个键值对就知道你是谁了,实现了自动登录。当你换个电脑时,新电脑浏览器没有这个身份标识,自然就需要重新登陆。
实现这种身份识别,除了浏览器的Cookie要有对应的身份标识,服务器方还要维护一个Session系统,每个用户都有自己的Session,里面记录着这个用户的各种信息,通过Cookie里的身份标识服务器就会从Session中调取出对应用户信息(有点类似于hash),二者配合实现了自动登录这个功能。
总结:
*Cookie从哪来? 服务器返回给浏览器。
*Cookie保存在哪里? 保存在浏览器当中,按照域名的方式存储。
*Cookie里的内容是啥? Cookie中保存了各种键值对,具体意义是由开发者规定,其中有一个非常重要的键值对表示用户身份。
*Cookie的内容到哪里去? 后续再访问这个网站,请求里就会带着这个网站的域名对应的Cookie。服务器就可以知道这个客户端的详细情况。