1.1.1 URL 基本格式
平时我们俗称的 “网址” 其实就是说的 URL (Uniform Resource Locator 统一资源定位符).互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它.URL 的详细规则由 因特网标准RFC1738 进行了约定
一个具体的 URL:
https://v.bitedu.vip/personInf/student ? userId=10000&classId=100
上述属性比较抽象,举个例子理解下:
好比我去驿站取一张床.服务器地址就告诉我该去哪个驿站,端口号就是对应的哪个工作人员,带层次的文件路径就是取件码,查询字符串就可以是我告诉工作人员这个床太大了,我要分四次来取走等进一步要求
注意:
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”):
urldecode就是urlencode的逆过程
在HTTP请求中,涉及到的最主要两种方法就是GET 和 POST
GET 是最常用的 HTTP 方法. 常用于获取服务器上的某个资源.在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求.另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求
后面我们还会学习, 使用 JavaScript 中的 ajax 和 form表单来构造 GET 请求
使用 Fiddler 观察 GET 请求
可以看出第一条是通过浏览器地址栏发送的 GET 请求
下面的和 sogou 域名相关的请求, 有些是通过 html 中的 link/script/img 标签产生的, 例如
GET 请求的特点:
扩展:
关于 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 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面).
通过 HTML 中的 form 标签, 或者使用 JavaScript 的 ajax 可以构造 POST 请求
使用 Fiddler 观察 POST 方法:
在比特教务系统的登陆页面, 输入用户名, 密码, 验证码之后, 点击登陆, 就可以看到 POST 请求.
点击这个请求, 查看请求详情
POST 请求的特点:
这些方法的 HTTP 请求可以使用 ajax 来构造. (也可以通过一些第三方工具)
任何一个能进行网络编程的语言都可以构造 HTTP 请求. 本质上就是通过 TCP socket 写入一个符
合 HTTP 协议规则的字符串
注意: GET 和 POST 没有本质区别,细节上有差异.它们的使用场景都是可以相互替换的
补充说明:
关于语义: GET 完全可以用于提交数据, POST 也完全可以用于获取数据.
关于幂等性: 标准建议 GET 实现为幂等的. 实际开发中 GET 也不必完全遵守这个规则(主流网站都有 “猜你喜欢” 功能, 会根据用户的历史行为实时更新现有的结果.
关于安全性: 有些资料上说 “POST 比 GET 请安全”. 这样的说法是不科学的. 是否安全取决于前端在传输密码等敏感信息时是否进行加密, 和 GET POST 无关.
关于传输数据量: 有的资料上说 “GET 传输的数据量小, POST 传输数据量大”. 这个也是不科学的, 标准没有规定 GET 的 URL 的长度, 也没有规定 POST 的 body 的长度. 传输数据量多少,完全取决于不同浏览器和不同服务器之间的实现区别.
关于传输数据类型: 有的资料上说 “GET 只能传输文本数据, POST 可以传输二进制数据”. 这个也是不科学的. GET 的 query string 虽然无法直接传输二进制数据, 但是可以针对二进制数据进行 url encode.
请求行中还涉及到版本问题,在初识篇已经介绍,这里就不过多赘述
header 的整体的格式也是 “键值对” 结构.每个键值对占一行. 键和值之间使用分号分割.报头的种类很多,当前介绍几种常用的,如下
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 的.
浏览器给页面提供的一种能够持久化储存数据的机制方便后续访问完网站.Cookie 中存储了一个字符串, 这个数据可能是客户端(网页)自行通过 JS 写入的, 也可能来自于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回一些数据和 SessionID,往往可以通过这个SessionID 实现 “身份标识” 的功能).
Cookie的组织形式: 先按照域名来组织,针对每个域名分别分配一个Cookie,如我访问百度,浏览器会给百度域名分配一个cookie.在每个Cookie中又会按照键值对的当时来组织数据,如下:
PS:每个不同的域名下都可以有不同的 Cookie, 不同网站之间的 Cookie 并不冲突.
通过抓包观察页面登陆的过程(以码云为例):
可以看到, 响应中包含了 3 个 Set-Cookie 属性.其中我们重点关注第三个. 里面包含了一个 gitee-session-n 属性(即SessionID), 属性值是一串很长的加密之后的信息. 这个信息就是用户当前登陆的身份标识. 也称为 “令牌(token)”
请求中的 Cookie 字段也包含了一个 gitee-session-n 属性, 里面的值和刚才服务器返回的值相同. 后续只要访问 gitee 这个网站, 就会一直带着这个令牌, 直到令牌过期/下次重新登陆
理解上述过程:
这个过程和去医院看病很相似.
关于Session会话:
上述讲到的Cookie可以存储数据,但是保存的数据量有限,所以这些数据真正的保存在服务器的Session中,每个服务器管理者很多Session会话,每个Session里面存储着很多关键信息,并且每个Session都有一个SessionID,而我们的Cookie中最主要就是存储着这些SessionID.后续访问该服务器的其他页面时就会带上这个SessionID,从而让服务器知道当前用户的关键信息
PS:服务器通过响应中的Set-Cookie字段将SessionID返回给Cookie
正文中的内容格式和 header 中的 Content-Type 密切相关.
罗列了三种常见的情况:
title=test&content=hello
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–
{“username”:“123456789”,“password”:“xxxx”,“code”:“jw7l”,“uuid”:“d110a05ccde64b16a861fa2bddfdcd15”}