http全称是“超文本传输协议”是一种应用非常广泛的应用层协议。http是基于于TCP协议实现的(http1.0,http1.1,http2.0均以tcp实现,http3.0基于udp实现),目前我们主要使用http1.1和http2.0,本篇文章以http1.1为主。
超文本协议:传输的内容不仅仅是文本(html,css这些是文本)还可以是一些其他资源,如图片,视频,音频等二进制数据。
咱们平时打开一个网站,就是通过http协议传输数据。例如咱们在浏览器输入百度网址http://www.baidu.com
,浏览器就该百度的服务器发送一个http请求,百度的服务器返回一个http响应。这个响应被浏览器解析以后,就展示出我们看到的页面。(这个过程中浏览器可能给服务器发送多个http请求,服务器会对应返回多个响应,这些响应中包含了页面html,css,js,图片,字体等信息)
咱们可以借助抓包工具,如fiddler来分析http协议格式。
:
来分割键和值:
来分割键和值url就是我们俗称的“网址”,是唯一资源定位符(用来找到网络上的资源)。另外一个相近的概念的是uri,唯一资源标识符(用来区分一个网络上的资源)
域名和Ip地址是等价关系,域名要经过dns解析,帮我们自动把域名转换成Ip地址
ip+port就能确定是互联网上的哪个主机的哪个进程
url中写的路径,不一定完全和服务器上的某个硬盘上的目录一一对应。例如服务器上的目录是
D:/source/index.html
,把D:/source
这个目录映射成http的跟目录/
,因此要访问index.html
文件,就要写作http://127.0.0.1:80/index.html
.
上面index.html
是一个真实存在的文件,服务器也可以提供“虚拟出来的文件”。例如,可以在http服务器中,加入一些特殊逻辑,比如请求的url的路径是/test
,在http服务器中,直接在内存中构造出一个html,返回给浏览器,此时并没有访问硬盘的真实文件,而是直接在内存中拼一个html出来
?key1=value1&key2=value2
查询字符串(query string),浏览器给服务器传递一些必要参数,这些键值对是由业务决定的,完成由程序员自定义。例如http://xxx大学2餐厅:6号窗口/骨汤麻辣烫?口味=微辣&是否放香菜=放&是否放葱=放
.个性化需求是由查询字符串传递的。url中可能包含一些特殊含义的符号,如/ ? @等
,万一query string的value中,也包含这些特殊字符,可能导致浏览器错误识别url,服务器也可能错误的解析url.(类似于变量名不能是关键字)。因此需要对特殊字符进行转义,还包括汉字。
转义规则:把待转义的字符串的每个字符按照16进制表示,每个字节前面加上%
。
具体可以查看这个网站:encode网站
简单来说可以把方法理解成你这个请求想做什么
在咱们开发中,主要使用get和post方法,因此这里只介绍这两个
link
,a
,img
,script
会触发get请求如果需要给服务器传递一些信息,在get请求中,通常通过querystring来传递。
在post请求中url通常是没有query string的,在传递信息给服务器,通常把消息放到body中
幂等:输入是确定的,输出结果也是确定的。
当然有的get请求不是幂等,因此要通过特殊的技巧不让浏览器产生缓存,典型做法就是让每次get请求的url都不相同,可以通过quert string来保证url不同
请求头中的键值对,都是标准规定的,有特定含义。
这里以访问百度网站为例www.baidu.com
,进行抓包
表示服务器主机的地址和端口,确定是互联网上哪个主机上的哪个进程。
这里是域名,域名经过dns解析后就是ip。此处没有显示port,表示默认。http的默认端口是80,https的默认端口是443.
问url中也有这个ip+port,为什么还要有Host?
url中的Ip和端口,和host里的ip和端口,不一定完全相同。当请求是经过代理来访问的时候,有可能不一样。
如果是get请求,没有body,就没有这两个字段。如果是post请求,有body一定有这两个字段。
为什么需要content-type?
body中的数据类型有很多种格式,对于接收方来说,采取的解析方式是不同的。
为什么需要content-length?
http是基于tcp的,而tcp是面向字节流,存在粘包问题。解决方法有两种1. 约定一个分割符,也就是header和body之间的空行;2. 约定报文长度
有哪些格式?
application/x-www-form-urlencoded
,像html的form表单构造的请求,使用的就是这个格式。格式和query string一样,可以放很多键值对,键值对之间用&分割,键和值之间用=分割。例如title=test&content=hello
,并且这里也需要urlencode。
multipart/form-data
该格式主要用于上传文件application/json
数据为json格式,body格式如下
UA主要是浏览器信息和操作系统信息,描述了用户用什么设备上网
早期的浏览器,只支持文字,后来开始支持图片,再后来支持js,后面支持音频。在同一时间段内,用户使用多种浏览器。因此开发者就利用收集到的浏览器/操作系统信息,个性化的返回不同的页面。UA的作用大大降低
随着时间推移,浏览器都趋于一致,开发者不再需要纠结浏览器兼容问题。而现在设备主要有PC,平板,手机需要开发出不同版本的页面,后面又推出”响应式页面“能感知浏览器窗口大小,根据不同尺寸,重新排列布局。UA的作用又被削弱了
而现在UA主要用来在服务器端统计用户的设备情况
Referer指的是当前页面,是从哪个页面跳转过来的。所以直接在浏览器地址输入地址,没有referer;点收藏夹,也没有referer。
例如在百度上投放广告,采用点击计费(CPC广告)和广告主结算广告费。统计点击次数时,百度自己会统计,广告主也会统计服务器中收到的请求,有多少referer来自百度的。
cookie也是请求头的一个重要字段,是浏览器在本地存储数据的一种机制,但是只能存一些简单的键值对信息,比如存上次访问页面的时候,当前页面的访问次数,当前访问页面的身份信息。
浏览器为了安全,禁止网页js访问电脑的硬盘,浏览器专门提供了特殊的api给网页使用,可以让网页存储一些简单的数据。浏览器提供持久化存储的方案,有好几种,例如:cookie最经典的一种方案,LocalStorage和indexDB是比较新的方案。
cookie存在于浏览器,来源于服务器。
像上图,cookie是咱们浏览器访问了bing服务器之后,服务器返回的响应报文中,在响应header中包含一个或多个set-cookie这样的资源。浏览器看到set-cookie就会把这样的数据保存到浏览器本地。
cookie来自于服务器,存储于浏览器,还要再回到服务器。当浏览器保存了cookie之后,下次浏览器访问同一个网站,就会把之前本地存储的cookie,通过http请求的header的cookie带过去。
cookie最常用的场景就是客服端维持登陆状态。
在某个网站上登陆成功后,浏览器就会记住当前登入用户的身份信息。然后接下来访问网站的其他页面时,服务器也能知道是谁在登入。
1开头的表示等等
2开头的表示正常访问
3开头的表示重定向
4开头的表示客服端出现问题
5开头的表示服务端出现问题
响应中常见的content-type
x-www-form-urlencoded
<form action="https://www.baidu.com" method="get">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="提交">
form>
<form action="https://www.baidu.com" method="post">
<input type="text" name="username"> <br>
<input type="password" name="password"> <br>
<input type="submit" value="提交">
form>
form构造的http请求一定会触发页面跳转,而ajax默认发起的请求不会引起跳转,可以达到“局部刷新”的效果
ajax的全称是Asynchronous JavaScript And Xml
。
类似于餐馆吃饭,点完单以后,如果煮好了,自己去端是同步,等服务员帮你端过来是异步
<script src="../jquery-1.12.4.js">script>
<script>
//$是jquery的全局变量,通过这个对象,可以调用里面的一些方法
$.ajax({
// 访问地址
url: "https://www.baidu.com",
type: "post", //访问方法
data: "http请求的body", // 传给后端的数据
contentType: 'x-www-form-urlencoded', // 构造http请求的方式
// 后端给前端推送的结果,异步的表现
// 使用回调函数,根据返回结果的不同执行不同的方案
success:function(body) {
console.log("成功")
},
error:function(body) {
console.log("失败")
}
})
script>