Skip to content

实际上,HTTP 就是基于请求响应的模式来完成通信的,即每次通信都是由客户端发送请求,服务器收到请求之后,根据请求进行处理,然后将数据相应给客户端,这就完成了一次通信。

HTTP 协议有以下规定

  • 每次请求响应都是独立的,相互之间互不干扰,这种模式我们也称为无状态协议
  • 每次请求响应传递的消息都必须是字符串(纯文本),而且字符串的格式必须按照 HTTP 规定的格式来书写。

https 实际上就是更加安全的 http 协议

既然响应和请求都要按照 HTTP 规定的格式,那 HTTP 规定了什么格式呢?

HTTP 规定请求的格式如下:

![Pasted image 20240514031305](/notes-assets/06.AJAX/assets/Pasted image 20240514031305.png)

显然,一次请求虽然是一个字符串,但也包含了三个部分,分别是请求行,请求头,请求体,我们从这也能看出他的规则,首先,请求行只有一行,请求行和请求头是用过一个换行符进行分割,请求头又可以有很多项,每一项通过一个换行分割,请求头和请求体通过两个换行分割,这就构成了一个 HTTP 请求所要求的格式。

  • 请求行:告诉客户端我想要干什么
  • 请求头:描述本次请求和业务本身无关的一些额外信息
  • 请求体:存放必要的业务信息,一次请求是可以没有请求体的,但请求行和请求头必须要有

这几个概念比较抽象,现在看不懂是很正常的,读者需要在以后的学习中不断加深对齐理解。

这里以上面的例子介绍请求行,请求头,请求体是干什么的

首先,在上面的例子中,POST /api/user/login HTTP/1.1 这个就是请求行,很显然,请求行里面包含三个部分,分别是 POST, /api/user/login, HTTP/1.1 这三个部分,其中 POST 为请求方法,/api/user/login 就是我们本次请求 URL 地址中的路径+参数+哈希,HTTP/1.1 就是协议和版本,由于我们是学习前端,所以对于 HTTP 请求的版本我们不涉及。而对于 URL 地址中的路径+参数+哈希,这也很好理解,当我们要给这个服务器发送一个请求的时候,我们一定是已经找到这个服务器了,所以我们就没必要再把 URL 地址中的服务器地址和后面的端口号再传过去,我们只需要将服务器地址后面的路径,参数,哈希传过去即可。

我们主要关注第一个,也就是请求方法,请求方法就是一个单词,表示了我这次请求想要干什么,请求方法主要有以下几个

序号方法描述
1GET用于请求服务器发送某个资源。GET 请求不应该对服务器上的资源做出任何更改,并且应该是幂等的(即多次重复的请求应该产生相同的结果)。例如,当你在浏览器中输入 URL 地址时,浏览器会发送一个 GET 请求来获取该 URL 对应的网页。
2HEAD类类似于 GET 请求,但服务器不返回请求的资源主体,只返回响应头。HEAD 请求通常用于获取资源的元信息,如资源的大小、类型等,而不需要获取资源的实际内容。
3POST用于向服务器提交数据,通常用于提交表单或上传文件。POST 请求可能会导致服务器上的状态更改,并且不一定是幂等的。例如,在提交注册表单时,浏览器通常会发送一个 POST 请求,将用户提供的信息发送到服务器进行处理。
4PUT用于向服务器上传资源,通常用于更新已存在的资源或创建新的资源。PUT 请求应该是幂等的,即多次执行相同的 PUT 请求应该产生相同的结果。
5DELETE用于请求服务器删除指定的资源。DELETE 请求应该是幂等的,即多次执行相同的 DELETE 请求应该产生相同的结果。
6CONNECT用于建立到服务器上指定端口的隧道,通常用于代理服务器。
7OPTIONS用于请求服务器返回支持的 HTTP 方法和其他选项。例如,客户端可以发送 OPTIONS 请求来确定服务器支持哪些 CORS(跨域资源共享)策略。
8TRACE回显服务器收到的请求,主要用于测试或诊断。
9PATCH用于在请求-响应链上的每个节点获取传输路径。TRACE 请求通常用于调试和测试,以查看请求在经过各种代理服务器和中间件时如何被修改。

我们比较常用的是以下四个

  • GET:获取
  • DELETE:删除
  • POST:提交
  • PUT:更新(修改)

上面四个方法可以囊括增删改查四个场景,作为一个前端开发者,了解者四个方法即可,如果我们要获取一个数据,就用 GET 方法,如果我们要提交一个数据,就用 POST 方法,如果我们要删除一个数据,就是用 DELETE 方法,如果我们要修改一个数据,就是用 PUT 方法。这里一个一个举例,例如我这里有一个电商网站,我要登录,实际上就是一个提交用户的账号和密码的操作,就要使用 POST 请求,登录后我要查看我的购物车,这是一个获取操作,就使用 GET 请求,我要将我的购物车中的一件商品删除,这就要用 DELETE 请求,此时我看上了一个商品,要把他加到购物车,注意,这个使用的应该是 POST 请求,而如果我要修改我购物车内某个商品的数量,就是要给更新操作,就使用 PUT 请求。

从语义化的角度来看,GET 请求和 DELETE 请求一般是不包含请求体的,POST 请求可以用来上传数据,比如登录的账号密码,上传文件,这些都要使用 POST 请求,而 PUT 请求则需要提交修改的数据,而 DELETE 请求和 GET 请求一般都不应该包含请求体。有的读者可能有疑问,如果我要删除我的购物车,那起码要让服务器知道要删除的是我的购物车,而不是别人的购物车对吧,也就是说要把我的身份信息传递进去,这些身份信息一般被包含在请求头里。

由于 GET 和 DELETE 请求没有请求体,我们如果需要传递数据,只有两种解决方案,其一是将数据放到 URL 的参数中,其二就是使用动态路由。我们通过浏览器访问一个网页,实际上就是向服务器发送了一个 GET 请求,获取到了该网站的 HTML 文件信息。

接下来是请求头,请求头包含的所有内容均为键值对,格式为 键:值,多个键值对使用换行来分割,主要包含了和请求业务本身无关的额外信息,比如我发出请求的服务器是哪一个,比如我请求体的格式是什么,实际上,浏览器在发送请求的时候自动就会给你带上一大堆请求头,这些请求头信息在大多数场景下都用不到,但偶尔也会用到,所以如果真的服务器需要用,也可以拿到这些信息,以下是浏览器自动附带的一些信息

  1. Host:url 地址中的主机
  2. User-Agent:客户端的信息描述
  3. Content-Type: 请求体的消息是什么格式,如果没有请求体,这个字段无意义

而请求体就是具体内容,GET 请求和 DELETE 请求一般是不附带请求体的,请求体的格式必须和 Content-Type 中指定的格式一致,否则可能导致服务器无法识别。至于请求体的具体内容,我们需要查看接口文档。

接下来是响应的内容,响应也可以分为响应行,响应头,响应体,如下所示

f25830ecf76a6daddc9acddb7007ab47_MD5

可见,这和请求非常类似,响应行中也可以分为两部分,分别为 HTTP 版本,响应的状态码+状态消息,这里的状态码要单独介绍一下,就是服务器收到我们的请求之后,可能会有一些不同的结果,比如用户尝试获取一个不存在的资源,我服务器找不到,这个时候就必须要告诉客户端这个出错了,这种消息就是通过响应行告诉客户端的,我们可以将状态码看做服务器对当前请求的一种态度,客户端可以通过这个状态码判断本次请求是否成功。

状态消息通常就是状态码的一种更加友好的表达,比如我们看到 200 可能不知道是什么意思,但是如果看到 OK,就很清楚本次请求是成功的

关于状态码,这里会出现很多情况,如下所示:

分类分类描述
1**信息,服务器收到请求,需要请求者继续执行操作
2**成功,操作被成功接收并处理
3**重定向,需要进一步的操作以完成请求
4**客户端错误,请求包含语法错误或无法完成请求
5**服务器错误,服务器在处理请求的过程中发生了错误

以上为状态码的分类,接下来是一些常见的状态码:

  1. 200 OK:一切正常。
  2. 301 Moved Permanently:资源已被永久重定向。 你的请求我收到了,但是呢,你要的东西不在这个地址了,我已经永远的把它移动到了一个新的地址,麻烦你取请求新的地址,地址我放到了响应头的Location中了
  3. 302 Found:资源已被临时重定向。 你的请求我收到了,但是呢,你要的东西不在这个地址了,我临时的把它移动到了一个新的地址,麻烦你取请求新的地址,地址我放到了请求头的Location中了
  4. 304 Not Modified:文档内容未被修改。 你的请求我收到了,你要的东西跟之前是一样的,没有任何的变化,所以我就不给你结果了,你自己就用以前的吧。啥?你没有缓存以前的内容,关我啥事
  5. 400 Bad Request:语义有误,当前请求无法被服务器理解。 你给我发的是个啥啊,我听都听不懂
  6. 403 Forbidden:服务器拒绝执行。 你的请求我已收到,但是我就是不给你东西
  7. 404 Not Found:资源不存在。 你的请求我收到了,但我没有你要的东西
  8. 500 Internal Server Error:服务器内部错误。 你的请求我已收到,但这道题我不会,解不出来,先睡了

关于 301 和 302 的区别,一个是永久重定向,一个是临时重定向,当浏览器在请求一个 URL 的时候,如果返回 301,那么表示已经被永久重定向,此时浏览器会直接将新地址进行缓存,下次访问该地址的时候就会直接使用缓存内的新地址而不发送请求,而临时重定向由于是临时的,所以浏览器不会进行缓存。

响应头也是由键值对组成的,其中响应头中也有一个叫 Content-Type 的响应头,表示响应体的格式。响应体则表示响应的主体内容。

实际上,当我们在浏览器请求一个图片的时候,浏览器会直接打开这张图片,这就是由于浏览器识别到了响应体的 Content-Type ,发现这是一张图片,所以就会按照图片来展示。

以笔记为镜,可以知得失