❣️关注专栏: JavaEE
HTTP (全称为 “超文本传输协议”) 是一种应用非常广泛的 应用层协议。我们平时通过浏览器获取到相关的页面,就是基于http。HTTP 往往是基于传输层的 TCP 协议实现的。(HTTP1.0, HTTP1.1, HTTP2.0 均为TCP, HTTP3 基于 UDP实现)。目前我们主要使用的还是 HTTP1.1 和 HTTP2.0。这里讨论的 HTTP 以 1.1 版本为主。
HTTP 是一个文本格式的协议。http协议的交互过程可以借助第三方工具看到。第三方工具就被称为“抓包工具”。可以通过 Chrome 开发者工具或者 Fiddler(该抓包工具专注于http,使用起来更方便) 抓包, 分析 HTTP 请求/响应的细节。
去官网下载好 fiddler 并且安装好之后,我们打开它就可以看到当前电脑上某个程序使用http和服务器交互的过程:
fiddler 本质上是一个代理程序,使用的时候要注意:
(1)可能与别的代理程序冲突,所以在使用的时候要关闭其他的代理程序(包括一些浏览器的插件)。
那说到这里,什么是代理呢?通俗的讲,代理就是找别人帮你干活。
(2)要向正确抓包,还需要开启 HTTPS 功能。https 是基于 http 的进化版协议,当下的互联网的绝大多数的服务器都是 https 的,fiddler 默认是不能抓 https 的包,需要我们手动启动 https 并且安装证书。
步骤如下:
点击之后选择第一项 Options:
在此过程中会弹出一个提示,问你是否要安装证书,一定要选 是(yes)。
产生的那些结果就是浏览器在访问一个页面的时候,产生的 http 请求,浏览器打开一个页面,对应的 http 可能是一个,也可能是多个。
当我们双击左侧请求列表,就可以查看到请求的详细情况:
观察抓包结果,可以看到 http 请求是一个行文本格式的数据,相比于 TCP 的二进制数据来说更易用户来直接观察。响应数据本来也是文本,但是有时候服务器对响应进行压缩,就变成了二进制。
学习一个协议,就是要学习它的报文格式。
点中一个查看它的报文格式。报文格式可以展示为下图:
首行包括三部分,彼此之间使用空格区分:
GET https://www.nowcoder.com/ HTTP/1.1
1、GET :是HTTP的方法(method)
2、https://www.nowcoder.com/ :是 URL(俗称的网址)
3、HTTP/1.1 :版本号
URL 是唯一资源定位符,就是标识互联网的唯一的资源的位置,定位符定位到资源位置(在哪个服务器的哪个目录下的哪个文件)。URI是唯一资源标识符,进行身份标识,实际上经常将 URL 和 URI 进行混用。
首先先认识一下 URL:
URL 最关键的四部分:
(1)域名
(2)端口号
(3)带层次的路径
(4)查询字符串
举一个通俗易懂的栗子吧:我去学校餐厅买煎饼果子 ~ 我要去榴鑫苑餐厅的一楼15号窗口买一个原味的煎饼果子,正常辣,不要葱,要生菜。
榴鑫苑餐厅:一楼15窗口号/原味的煎饼果子?辣度=正常辣&葱=不要葱&生菜=要
IP:榴鑫苑餐厅
端口号:一楼15窗口号
带层次的路径:原味的煎饼果子
查询字符串(以键值对的方式来组织):辣度=正常辣&葱=不要葱&生菜=要
URL 的这几个部分有些是可以省略的,比如
https://www.csdn.net/
省略了 端口号,此时浏览器会提供默认的端口,对于 http 来说,默认的端口号是 80,对于 https ,默认是 443.
其中 / 也是路径,只是有点短而已。
一个HTTP服务器提供的资源是很多的,不同的路径,拿到的资源不同。
GET 是最常用的 HTTP 方法. 常用于获取服务器上的某个资源。
1、在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求。
2、HTML 中的 link, img, script 等标签, 也会触发 GET 请求。
3、通过 js 也可以来构造 get 请求。
POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面).通过 HTML 中的 form 标签可以构造 POST 请求, 或者使用 JavaScript 的 ajax 也可以构造 POST 请求
(1)典型的就是登录,登录跳转的时候就会涉及到 POST。(2)另一个典型的就是上传文件
HTTP请求可以认为是四个部分:
(1)首行
(2)请求头(header)
(3)空行
(4)正文(body)
如果是 GET请求,没有 body。如果是 POST请求,一般有body。
其实 GET 和 POST 没有本质上的区别,在大部分场景下,二者是可以相互替换的,但是在使用习惯上,还是存在差异的
(1)GET 也可以给服务器传递一些信息,GET 传递信息的时候一般是放在 query string。(这只是一个习惯用法,GET 也不是不能有 body,POST也不是不能有 query string,但是这种很少见)
(2)语义上的差异:GET 请求一般是用于服务器获取数据,POST一般是用于服务器提交数据。(由于习惯用法所以这样写。但是也可以使用GET提交,POST获取,只是很少见)
(3)GET 通常会被设计成幂等的,POST 不要求幂等。幂等就是相同的输入,得到的结果也是确定的。一旦有一次输入相同的输出的结果和之前不同那就不是幂等。(由于习惯用法所以这样写。但是也可以把 POST 设定为幂等,GET 不幂等)
(4)GET 可以被缓存,POST一般不能被缓存。通过缓存就可以把请求的结果保存下来,下次请求就不用再请求了,直接取出缓存的结果就行。
小知识1:form 标签的用途就是构造 HTTP 请求,要构造 GET 还是 POST 通过 form 标签的属性来描述。
小知识2:POST 比 GET 更安全?其实说法不是非常准确的。大部分人认可这种说法的依据是:如果使用 GET 请求进行登录,此时用户密码通过 query string 来传递,就会出现在浏览器中,就会被别人看到。
但是安全指的是如果黑客窃取你的数据,你的敏感信息是不会被泄露的,安全的核心要素是加密。
将传输层和应用层 http协议 连接起来:
通过 socket 拿到里边的 outputstream,然后把 http格式 的这个字符串 write 进去就行了。
请求 “报头” (header)
header 的整体的格式也是 “键值对” 结构.每个键值对占一行. 键和值之间使用分号分割。
表示服务器主机的地址和端口。Host 这里的地址和端口,用来描述你最终要访问的目标。
前者表示 body 中的数据长度,后者表示表示请求的 body 中的数据格式。如果是 GET 请求,没有 body,请求中没有这两个字段,如果是 POST 请求,有 body,就有这两个字段。
表示浏览器/操作系统的属性,描述了浏览器和操作系统的版本。
表示这个页面是从哪个页面跳转过来的。就是当前页面的“来源”,如果直接在浏览器中输入URL, 或者直接通过收藏夹访问页面时是没有 Referer 的。
referer 是 http 层次的,交换机和路由器正常情况下是不会干涉的。
是一个非常重要的 header 属性。本质上是浏览器给网页提供的本地存储数据的机制。cookie 就相当于是浏览器对于访问硬盘做出了明确的限制,cookie 就是通过键值对的方式来组织数据的。cookie 中具体存什么是程序员自己定义的。
Cookie 中存储了一个字符串, 这个数据可能是客户端(网页)自行通过 JS 写入的, 也可能来自于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据).
在浏览器中我们可以看到cookie:
(1)cookie 从哪来?
cookie 中的数据来自于服务器,服务器会通过 http 响应的报头部分(Set-Cookie字段),服务器来决定浏览器的 cookie 要存储什么。
(2)cookie 是在哪存的?
可以认为是存在浏览器,也可以存在硬盘中。
cookie 在存储的时候,是按照 浏览器+域名 维度来进行细分的。不同的浏览器各自存储各自的 cookie,同一个浏览器不同的域名,对应不同的 cookie。
cookie 里边的内容不光是键值对,同时还有 过期时间。比如:有很多网站,登陆一次之后就自动记录登录状态。当时隔一段时间之后,如果没有超过过期时间,那就不需要再次登录了;如果超过了过期时间再登录就需要重新进行登录。
(3)cookie 要到哪里去?
当然是回到服务器里,客户端通过 cookie 来保存当前用户使用中间状态,相当于存储了“上下文”这样的状态。当客户端访问浏览器的时候,就会自动把 cookie 的内容带入到请求中,服务器就能知道现在客户端是什么样子了。
描述了这次响应的结果(成功?失败?原因?)
以下为常见的状态码:
没有找到资源。浏览器输入一个 URL, 目的就是为了访问对方服务器上的一个资源. 如果这个 URL 标识的资源不存在, 那么就会出现 404。
表示访问被拒绝(用户没有权限). 有的页面通常需要用户具有一定的权限才能访问(登陆后才能访问). 如果用户没有登陆直接访问, 就容易见到 403。
临时重定向。"重定向"就相当于手机号码中的 “呼叫转移” 功能。比如你换了一个手机号码,只需要办理一个呼叫转移业务就可以了,不需要告诉别人你换手机号了,当别人拨打原来的手机号,此时会呼叫转移到你的新手机号上。
302这样的响应报文中,会在 header 里带有一个 Location 属性,通过这个属性来描述要跳转到哪个新的地址。
3xx 都是类似的效果,都是重定向。重定向只是为了网站迁移。
服务器出现内部错误。 一般是服务器的代码执行过程中遇到了一些特殊情况(服务器异常崩溃)会产生这个状态码。
响应时间太久,浏览器等不及了。
当服务器负载比较大的时候, 服务器处理单条请求的时候消耗的时间就会很长, 就可能会导致出现超时的情况。这种情况在双十一等 “秒杀” 场景中容易出现, 平时不太容易见到。
gateway:网关。一个网络的入口/出口。通常也用来指一个机房的入口服务器。
HTTP协议的很多东西都是可以程序猿自己定义的。比如: