一、HTTP 是什么
HTTP 诞生与 1991 年 . 目前已经发展为最主流使用的一种应用层协议 .
HTTP 协议目前有三个大版本:
HTTP / 1 和 HTTP / 2 都是基于TCP 传输控制协议传输数据。最新版本的 HTTP / 3 是基于 UDP 协议的。当前互联网上传输数据大部分使用的版本是 HTTP / 1.1
HTTP 协议具体是什么? ——应用层协议又是什么?
应用层协议可以理解为是组织数据的一种格式,需要发送方和接收方约定相应的格式.
如何看到 HTTP 的报文格式呢?
我们可以借助一些 “抓包工具” 来获取设备交互的数据,可以抓取 http 协议的数据包。
如果只是针对 HTTP/HTTPS 协议的数据进行抓包,可以使用 Fiddler 这个工具,如果需要抓取 UDP / TCP / IP / mac 地址 …… 可以使用 wireshark 这个工具。
Fiddler (下载地址: https://www.telerik.com/fiddler/)
抓包工具的原理:数据在网络中传输,会经过许多中转设备,比如:路由器寻址,数据会经过这些设备传输,抓包工具就可以认为是一个中转设备,当数据经过该设备时自然可以进行“捕获”,数据传输又是按照标准的协议来传输,也就能按照一定的格式来解析,当然https 会对数据进行加密传输,虽然也可以捕获https 的数据包,如果没有一定的“手段”是看不懂数据的,只有数据传输的双端通过约定好的密文解析。、
二、HTTP 协议的请求
如:使用搜狗搜索引擎搜索一个 “小狗” , 那么浏览器就会自动将这条搜索记录打包成一条 http 数据包,作为请求发给搜狗地服务器,搜狗的服务器,拿到 客户端的i请求,解析后可以得到“小狗” 这个关键字,服务器就能将小狗作为关键字对数据库的进行模糊匹配,从数据库拿到数据后,就可以根据拿到的数据继续处理,比如说构建一个页面啊,最后将数据打包为 http 格式,作为响应返回给客户端,于是我们就可以页面上看到关于小狗的信息。
http 的请求分为四个部分: 1. 请求首行,2. 请求头, 3. 空行,4. 请求正文(body),根据不同的请求格式,不一定有。
请求首行
首行包含三个部分:
2.1.1 HTTP的方法,方法
HTTP定义了一些方法(也称为动作或动词),用于描述客户端与Web服务器之间的通信类型。
以下是常见的一些方法。
请求中的方法大概描述了这个请求数据报想干什么,比如说,GET 请求:想要从服务器上获取某些资源,很自然的想象到了搜索框这个场景。
HTTP协议的方法有很多种,最常用的是 GET 和 POST 方法
2.1.2 URL(统一资源定位符)
URL代表统一资源定位符,详细的描述了要访问的网络上的资源具体在哪里,
既要明确资源主机是谁,也要明确主机上的资源,通过浏览器,打开网页搜索的时候,地址栏里填写的这个“网址”。
1. 协议方案名
描述当前 URL 是在那个协议的组织下的格式,通过指定协议,用户的浏览器或者其他应用程序可以根据协议规定的方式,正确地打开和加载资源。例如,如果URL的协议方案是HTTP,则浏览器会使用HTTP协议与服务器建立连接,获取资源并呈现到用户屏幕上。如果协议方案是FTP,则浏览器会使用FTP协议访问资源。URL中的协议方案名对于正确访问和加载资源非常重要。
2. 登录信息
在早期的 http 格式中,会在URL 中显示用户名,密码,用于验证身份,现在基本上都使用了 https 协议,针对传输的数据进行ssl 加密。
3. 服务器地址
在网络中传递资源,实实在在的少不了 IP 地址, IP 地址是设备在网络中的唯一身份标识,两个设备建立连接就需要在茫茫网络世界中找到彼此。一般情况下我们看到的都是域名,比如:www.baidu.com , 这是百度服务器的 IP 地址,这涉及到DNS域名解析,本质上将域名(一定的格式) 跟 IP 地址(192.168.255.255)形成映射 ,因为使用域名对于用户来讲友好一点,方便记忆,从某种角度来看,相较于 IP 那一串数字,也更显得美观,域名最终还是会被 DNS 翻译成 IP 地址使用的。
4. 端口号
端口号表示当前设备上的那个应用程序,例如:http 服务器的端口号:80,http 服务器本质上也是代码编辑的应用程序,方便发送和解析 http 格式的数据报,Java 这一块较为常用的是 tomcat,他就是Java代码编写的http 服务器,默认绑定端口号是 8080,提供的一组操作 http 协议的 API(接口)——servlet
5.带层次的文件路径
服务器作为一个应用程序,存储资源的方式可以是硬盘,或者数据库,就比如说,百度浏览器搜索“小狗”, 百度服务器,就从本地寻找关于小狗的相关信息,或者是从硬盘?—— 文件路径:D:/ 图片/ 小狗.jpg ,或者是从数据库?数据库/ 数据表/ 字段(小狗)。
上述的 IP地址 + 端口 + 带层次的文件路径,其实就可以描述一个网络上具体的资源。
6. 查询字符串
本质上是浏览器/ 客户端,给服务器传递的自定义的信息,常用于描述想要进一步获取资源,例如:上述实例中的搜索小狗,小狗就会作为查询关键字,由服务器决定将那些数据响应给客户端,查询字符串的内容,是键值对的结构——key : value 例如:姓名 = 张三,根据键可以获取相应的值,这些键值对的结构,完全是程序猿自定义决定。
比如说:登录界面总会由:用户账号,密码
程序员就可以针对这个登录界面设置一组键值对,username = ?, password = ?
当用户输入数据后,程序就可以拿到用户数据来构造这个键值对,服务器那边有一种获取数据的方式就是通过写死的键值(key)username ,来获取 value 值 "张三", password = 123456。
查询字符串的内容,是键值对的结构,键和值之间用 “=” 分割,键值对之间由 “ & ”分割, 查询字符串与 路径之间采用 “?” 分割。
7. 片段标识符
用于标识资源中的特定位置或片段,通常是在网页内部使用,能控制浏览器滚动到相关的位置。
URL 小结:
按照标准的URL 的结构来看确实比较复杂,但是跟程序开发关系最紧密的有四个部分:
1. IP 地址/ 域名
2. 端口号(一般不显示)
3. 带层次结构的路径
4. queryString (查询字符串)
1~3 描述了网络中具体的资源,4 描述的在此资源基础上提出进一步的要求
当queryString 中包含了特殊字符,例如:/ , : ,?,&,= 这些字符都是在 URL 中具有特殊含义的,所以就需要对特殊字符进行转义,避免服务器解析错误,转义的过程我们可以使用 url encode的编码方式。在解析的时候针对查询字符串使用 url decode 进行反转义。
一个中文字符由 UTF-8 或者 GBK 这样的编码方式构成, 虽然在 URL 中没有特殊含义, 但是仍然需 要进行转义. 否则浏览器可能把 UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号.转义的规则如下: 将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一 位,前面加上%,编码成%XY格式例如:对于 http 的 GET 方法请求,其实就是利用 URL 中的 queryString 给服务器传递一些信息,所以在开发中一定要有对特殊字符进行转义的意识。
2.1.3 版本号
HTTP协议的版本号是在请求和响应中出现的,用于表示请求或响应所使用的HTTP协议的版本。这是因为不同的HTTP协议版本采用不同的协议规范,因此请求及响应头部的格式、支持的方法、状态码等都有可能不同,因此指定HTTP协议版本可以确保客户端和服务器使用的HTTP协议版本一致,避免因版本不同导致的错误。此外,通过在请求和响应中包含协议版本号也可以方便地识别出所使用的协议版本,便于协议的维护和演化。
在HTTP/1.1中,请求和响应头部中都包含了HTTP版本号信息。
举个简单的例子,HTTP 协议有个三个版本, HTTP1 和 HTTP2 基于 TCP 协议实现,HTTP3 基于 TCP 协议实现,所以一个 http 数据报中包含 版本号是很有必要的
GET 方法
- 首行的第一部分为 GET
- URL 的 query string 可以为空, 也可以不为空.
- header 部分有若干个键值对结构.
- body 部分为空.
关于 GET 请求的 URL 长度问题网上有些资料上描述 : get 请求长度最多 1024kb 这样的说法是错误的 .HTTP 协议由 RFC 2616 标准定义 , 标准原文中明确说明 : "Hypertext Transfer Protocol --HTTP/1.1," does not specify any requirement for URL length.没有对 URL 的长度有任何的限制 .实际 URL 的长度取决于浏览器的实现和 HTTP 服务器端的实现 . 在浏览器端 , 不同的浏览器最大长度是不同的, 但是现代浏览器支持的长度一般都很长 ; 在服务器端 , 一般这个长度是可以配置的 .
POST 方法
- 首行的第一部分为 POST
- URL 的 query string 一般为空 (也可以不为空)
- header 部分有若干个键值对结构.
- body 部分一般不为空. body 内的数据格式通过 header 中的 Content-Type 指定. body 的长度由header 中的 Content-Length 指定
- 语义不同: GET 一般用于获取数据, POST 一般用于提交数据.
- GET 的 body 一般为空, 需要传递的数据通过 query string 传递, POST 的 query string 一般为空, 需要传递的数据通过 body 传递
- GET 请求一般是幂等的, POST 请求一般是不幂等的. (如果多次请求得到的结果一样, 就视为请 求是幂等的).
- GET 可以被缓存, POST 不能被缓存. (这一点也是承接幂等性)
URL 中的可省略部分
- 协议名: 可以省略, 省略后默认为 http://
- ip 地址 / 域名: 在 HTML 中可以省略(比如 img, link, script, a 标签的 src 或者 href 属性). 省略后表示服务器的 ip / 域名与当前 HTML 所属的 ip / 域名一致.
- 端口号: 可以省略. 省略后如果是 http 协议, 端口号自动设为 80; 如果是 https 协议, 端口号自 动设为 443.
- 带层次的文件路径: 可以省略. 省略后相当于 / . 有些服务器会在发现 / 路径的时候自动访问 /index.html
- 查询字符串: 可以省略
- 片段标识: 可以省略
2.2 请求头(header)
请求头中包含了很多行,每一行都是一个键值对,键和值之间使用 “ :”
HTTP协议的请求头是客户端发给服务端的一种键值对的结构,它包含了客户端发送请求的一些相关信息,如请求方式、请求的资源地址、HTTP版本、请求时的时间、请求的编码方式等。这些请求头信息能够帮助服务器更好地理解客户端请求的意图和需要,对应的回复也会更加精准和高效。这里的键值对个数是不固定的,不同的键值对表示的含义也不同。
Host : www.baidu.com Host 描述 IP地址+ 端口号
域名通过 DNS 解析转换成 IP 地址, IP 跟 域名是映射关系。
Content-Length : 描述了 正文body 中的数据长度, 根据这条信息,就能够精确的从 body 中读取完整的数据,涉及到 IO 流的处理,采用 TCP 协议传输,是建立在字节流的基础之上。(解决粘包问题)
TCP 是一个面向字节流的协议,解决粘包问题 -> 合理设计应用层协议,来明确包和包之间的边界。
1.使用分隔符
2.使用长度
如果当前有若干个 GET 请求,到了 TCP 接收缓冲区中了,
应用程序读取请求的时候就以 空行 为分隔符。
如果当前是有若干个 POST 请求,到了 TCP 缓冲区了~~
这个时候,空行后面还有body ~~ 当应用程序读到了空行之后,就需要按照 Content-Length 表明的长度,继续读取若干个长度的数据~~
Content-Type:表示请求的body 中的数据格式,常用的是 json 格式,或者是前端的 form 表单提交,也可以同时指定 字符集: UTF-8
- 常见选项: application/x-www-form-urlencoded: form 表单提交的数据格式. 此时 body 的格式形如:
title=test&content=hello
- multipart/form-data: form 表单提交的数据格式(在 form 标签中加上enctyped="multipart/form-data" . 通常用于提交图片/文件. body 格式形如
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA------WebKitFormBoundaryrGKCBY7qhFd3TrwAContent-Disposition: form-data; name="text"title------WebKitFormBoundaryrGKCBY7qhFd3TrwAContent-Disposition: form-data; name="file"; filename="chrome.png"Content-Type: image/pngPNG ... content of chrome.png ...------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
- application/json: 数据为 json 格式. body 格式形如:
{"username":"123456789","password":"xxxx","code":"jw7l","uuid":"d110a05ccde64b16a861fa2bddfdcd15"}
User-Agent( UA):
表示的是,当前用户使用啥样的设备来上网的,主要描述了操作系统的信息和浏览器的信息(区分移动端和PC端)
Referer : 描述当前的页面是从拿个页面跳转过来的
Referer : 这个键值对不一定有,如果是从地址栏直接输入地址,或者是点击收藏夹,这个时候就没有 Referer 。
如果在搜狗的搜索引擎中搜索 “小狗” ,此时的请求中 referer 字段就可以完美展示出该请求来自 搜狗
那这个键值对有什么用呢?有一个很常用的功能,广告系统,按照点击来计费,浏览页面有广告链接,点击之后,就会触发请求,服务器就可以根据收到请求的 Referer 键值对来识别,是从那个平台发来的请求,从而达到计数的功能。比如说,搜狗的平台,我投放的广告,被多少用户看到了,点击了,统计出来后我需要给搜狗平台交钱~
当然 http 的请求有没有可能被别人截获了,并篡改了 Referer 中的内容呢,这个是可以的,毕竟一次点击可都是钱~ 但是如今都使用 https 协议来传输数据,就难以实现了,https 会对数据进行加密,可以被截获,几乎不可能被篡改。
Cookie 是浏览器给页面提供的一种持久化存储数据的机制,浏览器为了用户数据安全,默认不允许前端的代码访问用户设备上的数据,防止恶意代码,爬取用户数据,或者植入病毒,恶意删除数据等情况,但是有时候需要页面持久化存储一些数据,方便以后访问网页,比如:账户信息,细心的朋友可以发现,一些网站登录过一次之后,下次访问就不需要登录,直接就进入的主页,其实这个验证的过程是一直存在的,只是在用户看不到的地方,发送的验证请求,免去了用户重复登录的繁杂,提高了用户体验感。
首先不同浏览器有不同的 Cookie , Cookie 会针对每一个 域名(例:www.baidu.com)在硬盘上分配一块空间,这一块空间是以键值对的方式来组织数据,也与其他硬盘空间具有一定的隔离性,保证代码只能够对 Cookie 中的数据进行处理。
Cookie 的数据从哪里来,用户登录网页,发出请求,网站服务器就可以拿到用户的账号信息,首先会判断账户是否存在,其次校验账号密码的正确性,校验成功后,就可以反馈一些用户私有的信息,例如,头像,昵称,详细信息,历史记录等,账户信息的背后是一个键值对,账户信息为键,其他与用户相关的信息为值。这个键值对就是 session(会话) ,服务器管理着很多的 session。
初次登录服务器会根据账号创建一个新的会话,键值对,账户信息为 key , 然后服务器会将账户信息返回客户端, 客户端将数据存储在 Cookie 中存储, 从此以后,用户通过该域名(例如百度)发送的请求,都会附带账户信息,服务器这边就可以直接拿到用户账号信息自动进行校验,就免去了每次都需要用户登录验证的过程。通过 session(会话),就可以拿到用户的个人信息。
登录实例
登陆请求
POST https://gitee.com/login HTTP/1.1
Host: gitee.com
Connection: keep-alive
Content-Length: 394
Cache-Control: max-age=0
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
Origin: https://gitee.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/91.0.4472.101 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,imag
e/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://gitee.com/login
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
encrypt_key=password&utf8=%E2%9C%93&authenticity_token=36ZqO9tglSN6EB6pF6f2Gt%2B
dalgkbpTDUsJC5OER7w8%3D&redirect_to_url=%2FHGtz2222&user%5Blogin%5D=HGtz2222&enc
rypt_data%5Buser%5Bpassword%5D%5D=Hy2gjJ60312Ss12jSe21GMLPEb766tAhCygL281FLRMpiz
xJVaWGOPlQF7lZhelab1HS2vBiwfBo5C7BnR5ospoBiK1hR6jNXv1lesaYifv9dP1iRC6ozLLMszo%2F
aRh5j5DeYRyKcE0QJjXRGEDg4emXEK1LHVY4M1uqzFS0W58%3D&user%5Bremember_me%5D=0
HTTP/1.1 302 Found
Date: Thu, 10 Jun 2021 04:15:58 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Keep-Alive: timeout=60
Server: nginx
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-UA-Compatible: chrome=1
Expires: Sun, 1 Jan 2000 01:00:00 GMT
Pragma: must-revalidate, no-cache, private
Location: https://gitee.com/HGtz2222
Cache-Control: no-cache
Set-Cookie: oschina_new_user=false; path=/; expires=Mon, 10 Jun 2041 04:16:00
-0000
Set-Cookie: gitee_user=true; path=/
Set-Cookie: gitee-sessionn=M1Rhbk1QUUxQdWk1VEZVQ1BvZXYybG13ZUJFNGR1V0pSYTZyTllEa21pVHlBUE5QU2Qwdk44NXdEam
11T3FZYXFidGNYaFJxcTVDRE1xU05GUXN0ek1Uc08reXRTay9ueTV3OGl5bTdzVGJjU1lUbTJ4bTUvN1
l3RFl4N2hNQmI1SEZpdmVJWStETlJrdWtyU0lDckhvSGJHc3NEZDFWdHc5cjdHaGVtNThNcEVOeFZlaH
c0WVY5NGUzWjc2cjdOcCtSdVJ0VndzdVNxb3dHK1hPSDBDSFB6WlZDc3prUVZ2RVJyTnpTb1c4aFg1Mm
UxM1YvQTFkb1EwaU4zT3hJcmRrS3dxVFZJNXoxaVJwa1liMlplbWR5QXQxY0lvUDNic1hxN2o0WDg1Wk
E9LS10N0VIYXg4Vm5xdllHVzdxa0VlUEp3PT0%3D-
-2f6a24f8d33929fe88ed19d4dea495fbb40ebed6; domain=.gitee.com; path=/; HttpOnly
X-Request-Id: 77f12d095edc98fab27d040a861f63b1
X-Runtime: 0.166621
Content-Length: 92
<html><body>You are being <a href="https://gitee.com/HGtz2222">redirected</a>.
</body></html>
可以看到 , 响应中包含了 3 个 Set-Cookie 属性 .其中我们重点关注第三个 . 里面包含了一个 gitee - session - n 这样的属性 , 属性值是一串很长的加 密之后的信息. 这个信息就是用户当前登陆的身份标识 . 也称为 " 令牌 (token)
GET https://gitee.com/HGtz2222 HTTP/1.1
Host: gitee.com
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/91.0.4472.101 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,imag
e/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
sec-ch-ua-mobile: ?0
Referer: https://gitee.com/login
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: oschina_new_user=false; user_locale=zh-CN; yp_riddler_id=1ce4a551-a160-
4358-aa73-472762c79dc0; visit-gitee--2021-05-06%2010%3A12%3A24%20%2B0800=1;
sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%22726826%22%2C%22first_id%22%3
A%22175869ba5888b6-0ea2311dc53295-303464-2073600-
175869ba5899ac%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E
7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%
9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%2
4latest_referrer%22%3A%22%22%7D%2C%22%24device_id%22%3A%22175869ba5888b6-
0ea2311dc53295-303464-2073600-175869ba5899ac%22%7D; remote_way=svn;
tz=Asia%2FShanghai;
Hm_lvt_24f17767262929947cc3631f99bfd274=1622637014,1622712683,1622863899,1623298
442; Hm_lpvt_24f17767262929947cc3631f99bfd274=1623298550; gitee_user=true; giteesessionn=M1Rhbk1QUUxQdWk1VEZVQ1BvZXYybG13ZUJFNGR1V0pSYTZyTllEa21pVHlBUE5QU2Qwdk44NXdEam
11T3FZYXFidGNYaFJxcTVDRE1xU05GUXN0ek1Uc08reXRTay9ueTV3OGl5bTdzVGJjU1lUbTJ4bTUvN1
l3RFl4N2hNQmI1SEZpdmVJWStETlJrdWtyU0lDckhvSGJHc3NEZDFWdHc5cjdHaGVtNThNcEVOeFZlaH
c0WVY5NGUzWjc2cjdOcCtSdVJ0VndzdVNxb3dHK1hPSDBDSFB6WlZDc3prUVZ2RVJyTnpTb1c4aFg1Mm
UxM1YvQTFkb1EwaU4zT3hJcmRrS3dxVFZJNXoxaVJwa1liMlplbWR5QXQxY0lvUDNic1hxN2o0WDg1Wk
E9LS10N0VIYXg4Vm5xdllHVzdxa0VlUEp3PT0%3D-
-2f6a24f8d33929fe88ed19d4dea495fbb40ebed6
请求你中的 Cookie 字段也包含了一个 gitee - session - n 属性 , 里面的值和刚才服务器返回的值相同. 后续只要访问 gitee 这个网站 , 就会一直带着这个令牌 , 直到令牌过期 / 下次重新登陆
这个过程和去医院看病很相似 .1. 到了医院先挂号 . 挂号时候需要提供身份证 , 同时得到了一张 " 就诊卡 ", 这个就诊卡就相当于患者的 " 令牌 ".2. 后续去各个科室进行检查 , 诊断 , 开药等操作 , 都不必再出示身份证了 , 只要凭就诊卡即可识别出当前患者的身份.3. 看完病了之后 , 不想要就诊卡了 , 就可以注销这个卡 . 此时患者的身份和就诊卡的关联就销毁了. ( 类似于网站的注销操作 )4. 又来看病 , 可以办一张新的就诊卡 , 此时就得到了一个新的 " 令牌 "
三、 HTTP 的响应
3.1 首行
HTTP 协议的响应首行包含了三个部分:1. 版本号:HTTP/1.1, HTTP/2, HTTP/3.0 …… 描述了协议的版本
2. 状态码:(这个一般人是不认识的)表示请求页面的结果,是成功了,还是失败了,还是其他的一些原因……
3. 状态码的描述:一段英文单词,简单的向用户描述了状态。
3.1.1 状态码及其描述
200 OK
浏览器获取到了想要的信息
302 Move temporarily (临时重定向)
重定向就描述了接下来要跳转到哪里,常常用在登录界面,用于实现登录成功后自动跳转到主页
响应报文的 header 部分会包含一个 Location 字段,表示要跳转到那个页面
相当于手机号通信中的 “呼叫转移” 功能,比如我换号,但是来不及提醒之前我通讯录的好友,为了避免,好友给我打电话联系不上,于是我就去营业厅办理了一个 呼叫转移,当我的好友给我旧号码打电话的时候,就自动的转接到我新的手机号上。
3.2 响应头(header)
- 响应中的 Content-Type 常见取值有以下几种:
- text/html : body 数据格式是 HTML
- text/css : body 数据格式是 CSS
- application/javascript : body 数据格式是 JavaScript
- application/json : body 数据格式是 JSON‘
Server: nginx/1.17.3
Date: Thu, 10 Jun 2021 07:25:09 GMT
Content-Type: text/html; charset=utf-8
Last-Modified: Thu, 13 May 2021 09:01:26 GMT
Connection: keep-alive
ETag: W/"609ceae6-3206"
Content-Length: 12806
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible
content="IE=edge,chrome=1"><meta name=renderer content=webkit><meta name=viewport
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,userscalable=no"><link rel=icon href=/favicon.ico><title id=bodyTitle>比特教务管理系统
</title><link href=https://cdn.bootcss.com/jquerydatetimepicker/2.5.20/jquery.datetimepicker.css rel=stylesheet><script
src=https://cdn.bootcss.com/highlight.js/9.1.0/highlight.min.js></script><script
src=https://cdn.bootcss.com/highlightjs-line-numbers.js/2.5.0/highlightjs-linenumbers.min.js></script><style>html,
body,
#app {
height: 100%;
margin: 0px;
padding: 0px;
}
.chromeframe {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}
#loader-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999999;
}
......
HTTP/1.1 200 OK
Server: nginx/1.17.3
Date: Thu, 10 Jun 2021 07:25:09 GMT
Content-Type: text/css
Last-Modified: Thu, 13 May 2021 09:01:26 GMT
Connection: keep-alive
ETag: W/"609ceae6-3cfbe"
Content-Length: 249790
@font-face{font-family:element-icons;src:url(../../static/fonts/elementicons.535877f5.woff) format("woff"),url(../../static/fonts/elementicons.732389de.ttf) format("truetype");font-weight:400;font-style:normal}
[class*=" el-icon-"],
......
HTTP/1.1 200 OK
Server: nginx/1.17.3
Date: Thu, 10 Jun 2021 07:25:09 GMT
Content-Type: application/javascript; charset=utf-8
Last-Modified: Thu, 13 May 2021 09:01:26 GMT
Connection: keep-alive
ETag: W/"609ceae6-427d4"
Content-Length: 272340
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["app"],
{0:function(t,e,n){t.exports=n("56d7")},"00b3":function(t,e,n){},"
......
HTTP/1.1 200
Server: nginx/1.17.3
Date: Thu, 10 Jun 2021 07:25:10 GMT
Content-Type: application/json;charset=UTF-8
Connection: keep-alive
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
vary: accept-encoding
Content-Length: 12268
{"msg":"操作成功","code":200,"permissions":[] }