【 HTTP 请求 (Request) 】

文章目录

  • 一、请求行属性
    • 1.1 URL
    • 1.2 方法(method)
      • 1.2.1 GET 方法
      • 1.2.2 POST 方法
      • 1.2.3 其他方法
      • 1.2.4 GET 和 POST 的区别
  • 二、常见请求"报头" (header)
    • 2.1 其他报头
    • 2.2 Cookie(重要)
  • 三、请求 "正文" (body)

一、请求行属性

1.1 URL

1.1.1 URL 基本格式

平时我们俗称的 “网址” 其实就是说的 URL (Uniform Resource Locator 统一资源定位符).互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它.URL 的详细规则由 因特网标准RFC1738 进行了约定

【 HTTP 请求 (Request) 】_第1张图片

一个具体的 URL:

https://v.bitedu.vip/personInf/student ? userId=10000&classId=100

  1. https : 协议方案名. 常见的有 http 和 https, 也有其他的类型. (例如访问 mysql 时用的
    jdbc:mysql )
  2. user:pass : 登陆信息. 现在的网站进行身份认证一般不再通过 URL 进行了. 一般都会省略
  3. v.bitedu.vip : 服务器地址. 此处是一个 “域名”, 域名会通过 DNS 系统解析成一个具体的 IP 地址.(通过 ping 命令可以看到, v.bitedu.vip 的真实 IP 地址为 118.24.113.28 )
  4. 端口号: 上面的 URL 中端口号被省略了. 当端口号省略的时候, 浏览器会根据协议类型自动决定使用哪个端口. 例如 http 协议默认使用 80 端口, https 协议默认使用 443 端口.
  5. /personInf/student : 带层次的文件路径.描述了当前要访问的服务器资源文件(/ 也要包括)
  6. userId=10000&classId=100 : 查询字符串(query string). 本质是一个键值对结构. 键值对之间使用 & 分隔. 键和值之间使用 = 分隔. 是客户端给服务器传递的自定义信息,对获取到的服务器资源文件提出了进一步要求
  7. 片段标识: 此 URL 中省略了片段标识. 片段标识主要用于页面内跳转

上述属性比较抽象,举个例子理解下:

好比我去驿站取一张床.服务器地址就告诉我该去哪个驿站,端口号就是对应的哪个工作人员,带层次的文件路径就是取件码,查询字符串就可以是我告诉工作人员这个床太大了,我要分四次来取走等进一步要求

注意:

  1. 虽然URL中写的是一个文件路径,但是不一定服务器上就真实存在一个对应的文件.这个文件可能是磁盘上一个真实的文件,也可能是虚拟的,由服务器代码构造出的一个动态数据
  2. 带层次的文件路径和查询字符串是用 分割
  3. 查询字符串完全是由程序猿自己定义的,外人不认识,可以通过这样的方式来自定制传输我们需要的信息给服务器
  4. 使用 ping 命令查看域名对应的 IP 地址

1.在开始菜单中输入 cmd , 打开 命令提示符
2.在 cmd 中输入 ping v.bitedu.vip , 即可看到域名解析的结果
PS: 有的电脑上 ping 命令会报错 ping 不是内部或外部命令,也不是可运行的程序或批处理文件 . 这
种情况是因为有的 Windows10 默认没有启用 ping 命令


1.1.2 关于 URL encode

像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现.比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.(中文字符同样也需要转义)

转义的规则如下: 将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式,例如(“+” 被转义成了 “%2B”):

【 HTTP 请求 (Request) 】_第2张图片

urldecode就是urlencode的逆过程


1.2 方法(method)

认识 “方法” (method):
【 HTTP 请求 (Request) 】_第3张图片

在HTTP请求中,涉及到的最主要两种方法就是GET 和 POST

1.2.1 GET 方法

GET 是最常用的 HTTP 方法. 常用于获取服务器上的某个资源.在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求.另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求

后面我们还会学习, 使用 JavaScript 中的 ajax 和 form表单来构造 GET 请求

使用 Fiddler 观察 GET 请求

【 HTTP 请求 (Request) 】_第4张图片

选中第一条观察部分:
【 HTTP 请求 (Request) 】_第5张图片

可以看出第一条是通过浏览器地址栏发送的 GET 请求

下面的和 sogou 域名相关的请求, 有些是通过 html 中的 link/script/img 标签产生的, 例如
在这里插入图片描述

有些是通过 ajax 的方式产生的, 例如
在这里插入图片描述

GET 请求的特点:

  1. 首行的第一部分为 GET
  2. URL 的 query string 可以为空, 也可以不为空.
  3. header 部分有若干个键值对结构.
  4. 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 服务器端的实现. 在浏览器端, 不同的浏览器最大长
度是不同的, 但是现代浏览器支持的长度一般都很长; 在服务器端, 一般这个长度是可以配置的.


1.2.2 POST 方法

POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面).
通过 HTML 中的 form 标签, 或者使用 JavaScript 的 ajax 可以构造 POST 请求

使用 Fiddler 观察 POST 方法:
在比特教务系统的登陆页面, 输入用户名, 密码, 验证码之后, 点击登陆, 就可以看到 POST 请求.

【 HTTP 请求 (Request) 】_第6张图片

点击这个请求, 查看请求详情

【 HTTP 请求 (Request) 】_第7张图片

POST 请求的特点:

  1. 首行的第一部分为 POST
  2. URL 的 query string 一般为空 (也可以不为空)
  3. header 部分有若干个键值对结构.
  4. body 部分一般不为空. body 内的数据格式通过 header 中的 Content-Type 指定. body 的长度由header 中的 Content-Length 指定.

1.2.3 其他方法

  1. PUT 与 POST 相似,只是具有幂等特性,一般用于更新
  2. DELETE 删除服务器指定资源
  3. OPTIONS 返回服务器所支持的请求方法
  4. HEAD 类似于GET,只不过响应体不返回,只返回响应头
  5. TRACE 回显服务器端收到的请求,测试的时候会用到这个
  6. CONNECT 预留,暂无使用

这些方法的 HTTP 请求可以使用 ajax 来构造. (也可以通过一些第三方工具)

任何一个能进行网络编程的语言都可以构造 HTTP 请求. 本质上就是通过 TCP socket 写入一个符
合 HTTP 协议规则的字符串

1.2.4 GET 和 POST 的区别

注意: GET 和 POST 没有本质区别,细节上有差异.它们的使用场景都是可以相互替换的

  1. 语义不同: GET 一般用于获取数据, POST 一般用于提交数据.反之当然也可以
  2. GET 的 body 一般为空, 需要传递的数据通过 query string 传递, POST 的 query string 一般
    为空, 需要传递的数据通过 body 传递
  3. GET 请求一般是幂等的, POST 请求一般是不幂等的. (如果多次请求得到的结果一样, 就视为
    请求是幂等的).
  4. GET 可以被缓存, POST 不能被缓存. (这一点也是承接幂等性).

补充说明:

关于语义: GET 完全可以用于提交数据, POST 也完全可以用于获取数据.
关于幂等性: 标准建议 GET 实现为幂等的. 实际开发中 GET 也不必完全遵守这个规则(主流网站都有 “猜你喜欢” 功能, 会根据用户的历史行为实时更新现有的结果.
关于安全性: 有些资料上说 “POST 比 GET 请安全”. 这样的说法是不科学的. 是否安全取决于前端在传输密码等敏感信息时是否进行加密, 和 GET POST 无关.
关于传输数据量: 有的资料上说 “GET 传输的数据量小, POST 传输数据量大”. 这个也是不科学的, 标准没有规定 GET 的 URL 的长度, 也没有规定 POST 的 body 的长度. 传输数据量多少,完全取决于不同浏览器和不同服务器之间的实现区别.
关于传输数据类型: 有的资料上说 “GET 只能传输文本数据, POST 可以传输二进制数据”. 这个也是不科学的. GET 的 query string 虽然无法直接传输二进制数据, 但是可以针对二进制数据进行 url encode.


请求行中还涉及到版本问题,在初识篇已经介绍,这里就不过多赘述

二、常见请求"报头" (header)

header 的整体的格式也是 “键值对” 结构.每个键值对占一行. 键和值之间使用分号分割.报头的种类很多,当前介绍几种常用的,如下

2.1 其他报头

Host: 表示服务器主机的地址和端口.域名可以通过DNS转换成IP地址

Content-Length: 表示 body 中的数据长度. 可以明确包和包之间的界限,粘包问题

Content-Type: 表示请求的 body 中的数据格式.具体格式如下文


User-Agent (简称 UA): 表示浏览器/操作系统的属性(自报家门,方便区分浏览器). 形如

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/91.0.4472.77 Safari/537.36
其中 Windows NT 10.0; Win64; x64 表示操作系统信息
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 表示浏览器
信息

Referer: 表示这个页面是从哪个页面跳转过来的. 形如

https://v.bitedu.vip/login

注意: 如果直接在浏览器中输入URL, 或者直接通过收藏夹访问页面时是没有 Referer 的.


2.2 Cookie(重要)

浏览器给页面提供的一种能够持久化储存数据的机制方便后续访问完网站.Cookie 中存储了一个字符串, 这个数据可能是客户端(网页)自行通过 JS 写入的, 也可能来自于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回一些数据和 SessionID,往往可以通过这个SessionID 实现 “身份标识” 的功能).

Cookie的组织形式: 先按照域名来组织,针对每个域名分别分配一个Cookie,如我访问百度,浏览器会给百度域名分配一个cookie.在每个Cookie中又会按照键值对的当时来组织数据,如下:

【 HTTP 请求 (Request) 】_第8张图片

PS:每个不同的域名下都可以有不同的 Cookie, 不同网站之间的 Cookie 并不冲突.

通过抓包观察页面登陆的过程(以码云为例):

  1. 为了方便观察, 先清除掉之前登陆的 cookie(如上述图片即可找到清除)
  2. 登陆操作:准备好登录页面,将fiddler中的抓包清除后点击登录,观察抓包情况

登录请求:
【 HTTP 请求 (Request) 】_第9张图片

登录响应:
【 HTTP 请求 (Request) 】_第10张图片

可以看到, 响应中包含了 3 个 Set-Cookie 属性.其中我们重点关注第三个. 里面包含了一个 gitee-session-n 属性(即SessionID), 属性值是一串很长的加密之后的信息. 这个信息就是用户当前登陆的身份标识. 也称为 “令牌(token)

  1. 访问其他码云页面
    登陆成功之后, 此时可以看到后续访问码云的其他页面(比如个人主页), 请求中就都会带着刚才获取到的Cookie 信息

请求中的 Cookie 字段也包含了一个 gitee-session-n 属性, 里面的值和刚才服务器返回的值相同. 后续只要访问 gitee 这个网站, 就会一直带着这个令牌, 直到令牌过期/下次重新登陆

理解上述过程:

【 HTTP 请求 (Request) 】_第11张图片

这个过程和去医院看病很相似.

  1. 到了医院先挂号. 挂号时候需要提供身份证, 同时得到了一张 “就诊卡”, 这个就诊卡就相当于
    患者的 “令牌”.
  2. 后续去各个科室进行检查, 诊断, 开药等操作, 都不必再出示身份证了, 只要凭就诊卡即可识别
    出当前患者的身份.
  3. 看完病了之后, 不想要就诊卡了, 就可以注销这个卡. 此时患者的身份和就诊卡的关联就销毁
    了. (类似于网站的注销操作)
  4. 又来看病, 可以办一张新的就诊卡, 此时就得到了一个新的 “令牌”

关于Session会话:

上述讲到的Cookie可以存储数据,但是保存的数据量有限,所以这些数据真正的保存在服务器的Session中,每个服务器管理者很多Session会话,每个Session里面存储着很多关键信息,并且每个Session都有一个SessionID,而我们的Cookie中最主要就是存储着这些SessionID.后续访问该服务器的其他页面时就会带上这个SessionID,从而让服务器知道当前用户的关键信息

PS:服务器通过响应中的Set-Cookie字段将SessionID返回给Cookie


三、请求 “正文” (body)

正文中的内容格式和 header 中的 Content-Type 密切相关.

罗列了三种常见的情况:

  1. application/x-www-form-urlencoded: form 表单提交的数据格式. 此时 body 的格式形如:

title=test&content=hello

  1. multipart/form-data: form 表单提交的数据格式(在 form 标签中加上enctyped=“multipart/form-data” . 通常用于提交图片/文件. body 格式形如:

Content-Type:multipart/form-data; boundary=----
WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name=“text”
title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name=“file”; filename=“chrome.png”
Content-Type: image/png
PNG … content of chrome.png …
------WebKitFormBoundaryrGKCBY7qhFd3TrwA–

  1. application/json: 数据为 json 格式. body 格式形如:

{“username”:“123456789”,“password”:“xxxx”,“code”:“jw7l”,“uuid”:“d110a05ccde64b16a861fa2bddfdcd15”}


你可能感兴趣的:(HTTP,协议,http)