梦kWmLG

梦kWmLG 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

梦kWmLG 赞了文章 · 2020-12-31

前端应该知道的http

作为互联网通信协议的一员老将,HTTP 协议走到今天已经经历了三次版本的变动,现在最新的版本是 HTTP2.0,相信大家早已耳熟能详。今天就给大家好好介绍一下 HTTP 的前世今生。

1、http的历史简介

先简单的介绍一下,后面再具体详解

1.1、HTTP/0.9

HTTP 的最早版本诞生在 1991 年,这个最早版本和现在比起来极其简单,没有 HTTP 头,没有状态码,甚至版本号也没有,后来它的版本号才被定为 0.9 来和其他版本的 HTTP 区分。HTTP/0.9 只支持一种方法—— Get,请求只有一行。

GET /hello.html

响应也是非常简单的,只包含 html 文档本身。

<HTML>
Hello world
</HTML>

当 TCP 建立连接之后,服务器向客户端返回 HTML 格式的字符串。发送完毕后,就关闭 TCP 连接。由于没有状态码和错误代码,如果服务器处理的时候发生错误,只会传回一个特殊的包含问题描述信息的 HTML 文件。这就是最早的 HTTP/0.9 版本。

1.2、HTTP/1.0

1996 年,HTTP/1.0 版本发布,大大丰富了 HTTP 的传输内容,除了文字,还可以发送图片、视频等,这为互联网的发展奠定了基础。相比 HTTP/0.9,HTTP/1.0 主要有如下特性:

  • 请求与响应支持 HTTP 头,增加了状态码,响应对象的一开始是一个响应状态行
  • 协议版本信息需要随着请求一起发送,支持 HEAD,POST 方法

支持传输 HTML 文件以外其他类型的内容 一个典型的 HTTP/1.0 的请求像这样:

GET /hello.html HTTP/1.0
User-Agent:NCSA_Mosaic/2.0(Windows3.1)

200 OK
Date: Tue, 15 Nov 1996 08:12:31 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/html

<HTML>
一个包含图片的页面
<IMGSRC="/smile.gif">
</HTML>

1.3、HTTP/1.1

在 HTTP/1.0 发布几个月后,HTTP/1.1 就发布了。HTTP/1.1 更多的是作为对 HTTP/1.0 的完善,在 HTTP1.1 中,主要具有如下改进:

  • 可以复用连接
  • 增加 pipeline
  • chunked 编码传输
  • 引入更多缓存控制机制
  • 引入内容协商机制
  • 请求消息和响应消息都支持 Host 头域
  • 新增了 OPTIONS,PUT, DELETE, TRACE, CONNECT 方法

1.4、 HTTPS

HTTPS 是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版,即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。

HTTPS 协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。 HTTPS 和 HTTP 的区别主要如下:

  • HTTPS 协议使用 ca 申请证书,由于免费证书较少,需要一定费用。
  • HTTP 是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议。
  • HTTP 和 HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。

1.5、SPDY

在 2010 年到 2015 年,谷歌通过实践一个实验性的 SPDY 协议,证明了一个在客户端和服务器端交换数据的另类方式。其收集了浏览器和服务器端的开发者的焦点问题,明确了响应数量的增加和解决复杂的数据传输。在启动 SPDY 这个项目时预设的目标是:

  • 页面加载时间 (PLT) 减少 50%。
  • 无需网站作者修改任何内容。
  • 将部署复杂性降至最低,无需变更网络基础设施。
  • 与开源社区合作开发这个新协议。
  • 收集真实性能数据,验证这个实验性协议是否有效。

为了达到降低目标,减少页面加载时间的目标,SPDY 引入了一个新的二进制分帧数据层,以实现多向请求和响应、优先次序、最小化及消除不必要的网络延迟,目的是更有效地利用底层 TCP 连接。

1.6、 HTTP/2.0

时间来到 2015 年,HTTP/2.0 问世。先来介绍一下 HTTP/2.0 的特点吧:

  • 使用二进制分帧层
  • 多路复用
  • 数据流优先级
  • 服务端推送
  • 头部压缩

2、http原理详解

HTTP协议是构建在TCP/IP协议之上的,是TCP/IP协议的一个子集,所以要理解HTTP协议,有必要先了解下TCP/IP协议相关的知识。

2.1 TCP/IP协议

TCP/IP协议族是由一个四层协议组成的系统,这四层分别为:应用层、传输层、网络层和数据链路层
图片描述

分层的好处是把各个相对独立的功能解耦,层与层之间通过规定好的接口来通信。如果以后需要修改或者重写某一个层的实现,只要接口保持不变也不会影响到其他层的功能。接下来,我们将会介绍各个层的主要作用。
1) 应用层
应用层一般是我们编写的应用程序,其决定了向用户提供的应用服务。应用层可以通过系统调用与传输层进行通信。
处于应用层的协议非常多,比如:FTP(File Transfer Protocol,文件传输协议)、DNS(Domain Name System,域名系统)和我们本章讨论的HTTP(HyperText Transfer Protocol,超文本传输协议)等。
2) 传输层
传输层通过系统调用向应用层提供处于网络连接中的两台计算机之间的数据传输功能。
在传输层有两个性质不同的协议:TCP(Transmission Control Protocol,传输控制协议)和UDP(User Data Protocol,用户数据报协议)。
3) 网络层
网络层用来处理在网络上流动的数据包,数据包是网络传输的最小数据单位。该层规定了通过怎样的路径(传输路线)到达对方计算机,并把数据包传输给对方。IP协议
4) 链路层
链路层用来处理连接网络的硬件部分,包括控制操作系统、硬件设备驱动、NIC(Network Interface Card,网络适配器)以及光纤等物理可见部分。硬件上的范畴均在链路层的作用范围之内。

数据包封装
上层协议数据是如何转变为下层协议数据的呢?这是通过封装(encapsulate)来实现的。应用程序数据在发送到物理网络之前,会沿着协议栈从上往下传递。每层协议都将在上层协议数据的基础上加上自己的头部信息(链路层还会加上尾部信息),以为实现该层功能提供必要的信息.
图片描述
发送端发送数据时,数据会从上层传输到下层,且每经过一层都会被打上该层的头部信息。而接收端接收数据时,数据会从下层传输到上层,传输前会把下层的头部信息删除.

由于下层协议的头部信息对上层协议是没有实际的用途,所以在下层协议传输数据给上层协议的时候会把该层的头部信息去掉,这个封装过程对于上层协议来说是完全透明的。这样做的好处是,应用层只需要关心应用服务的实现,而不用管底层的实现。

TCP三次握手
从上面的介绍可知,传输层协议主要有两个:TCP协议和UDP协议。TCP协议相对于UDP协议的特点是:TCP协议提供面向连接、字节流和可靠的传输。

图片描述

  • 第一次握手:客户端发送带有SYN标志的连接请求报文段,然后进入SYN_SEND状态,等待服务端的确认。
  • 第二次握手:服务端接收到客户端的SYN报文段后,需要发送ACK信息对这个SYN报文段进行确认。同时,还要发送自己的SYN请求信息。服务端会将上述的信息放到一个报文段(SYN+ACK报文段)中,一并发送给客户端,此时服务端将会进入SYN_RECV状态。
  • 第三次握手:客户端接收到服务端的SYN+ACK报文段后,会想服务端发送ACK确认报文段,这个报文段发送完毕后,客户端和服务端都进入ESTABLISHED状态,完成TCP三次握手。

当三次握手完成后,TCP协议会为连接双方维持连接状态。为了保证数据传输成功,接收端在接收到数据包后必须发送ACK报文作为确认。如果在指定的时间内(这个时间称为重新发送超时时间),发送端没有接收到接收端的ACK报文,那么就会重发超时的数据。

2.2、 DNS 域名解析

当你在浏览器的地址栏输入 https://juejin.im 后会发生什么,大家在心中肯定是有一个大概的,这里我将 DNS 域名解析 这个步骤详细的讲一遍。在讲概念之前我先放上一张经典的图文供大家思考一分钟。
图片描述
查找域名对应的 IP 地址的具体过程

  1. 浏览器搜索自己的 DNS 缓存(浏览器维护一张域名与 IP 地址的对应表);如果没有命中,进入下一步;
  2. 搜索操作系统中的 DNS 缓存;如果没有命中,进入下一步;
  3. 搜索操作系统的 hosts 文件( Windows 环境下,维护一张域名与 IP 地址的对应表);如果没有命中,进入下一步;
  4. 列表项目

    • 操作系统将域名发送至 LDNS (本地区域名服务器),LDNS 查询自己的 DNS 缓存(一般命中率在 80% 左右),查找成功则返回结果,失败则发起一个迭代 DNS 解析请求:
    • LDNS向 Root Name Server(根域名服务器,如com、net、im 等的顶级域名服务器的地址)发起请求,此处,Root Name Server 返回 im 域的顶级域名服务器的地址;
    • LDNS 向 im 域的顶级域名服务器发起请求,返回 juejin.im 域名服务器地址;
    • LDNS 向 juejin.im 域名服务器发起请求,得到 juejin.im 的 IP 地址;
    • LDNS 将得到的 IP 地址返回给操作系统,同时自己也将 IP 地址缓存起来;操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起来。

http工作的简单过程

  • 地址解析: 这一步比较重要的是上面的DNS解析
  • 封装HTTP请求数据包: 把以上部分结合本机自己的信息,封装成一个HTTP请求数据包
  • 封装成TCP包,建立TCP连接(TCP的三次握手)
  • 客户机发送请求命令
  • 服务器响应
  • 服务器关闭TCP连接

2.3、http请求方法

一些常见的http请求方法。

  • GET: 用于获取数据
  • POST: 用于将实体提交到指定的资源,通常导致状态或服务器上的副作用的更改
  • HEAD: 与GET请求的响应相同的响应,但没有响应体
  • PUT: 用于创建或更新指定资源
  • DELETE: 删除指定的资源

关于get与post的一些区别。可以看我的另一篇文章面试经典之http中get与post的区别

2.4、 http缓存

http很重要的一点还有他的缓存机制。关于这部分的内容可以看一下我之前的文章浏览器缓存看这一篇就够了。这里就不在赘述了。

2.5、状态码

这里主要讲一些常用的状态码

1、 301 永久转移
当你想换域名的时候,就可以使用301,如之前的域名叫www.renfed.com,后来换了一个新域名fed.renren.com,希望用户访问老域名的时候能够自动跳转到新的域名,那么就可以使用nginx返回301:

server {
    listen       80;
    server_name  www.renfed.com;
    root         /home/fed/wordpress;
    return       301 https://fed.renren.com$request_uri;
}

浏览器收到301之后,就会自动跳转了。搜索引擎在爬的时候如果发现是301,在若干天之后它会把之前收录的网页的域名给换了。

还有一个场景,如果希望访问http的时候自动跳转到https也是可以用301,因为如果直接在浏览器地址栏输入域名然后按回车,前面没有带https,那么是默认的http协议,这个时候我们希望用户能够访问安全的https的,不要访问http的,所以要做一个重定向,也可以使用301,如:

server {
    listen       80; 
    server_name  fed.renren.com;

    if ($scheme != "https") {
         return 301 https://$host$request_uri;
    }   
}

2、302 Found 资源暂时转移
很多短链接跳转长链接就是使用的302,如下图所示:
图片描述
3、304 Not Modified 没有修改
这个主要在上面的缓存哪里出现的比较多。如果服务器没有修改。就会使用浏览器的缓存。

图片描述
4、400 Bad Request 请求无效
当必要参数缺失、参数格式不对时,后端通常会返回400,如下图所示:
图片描述

5、403 Forbidden 拒绝服务
服务能够理解你的请求,包括传参正确,但是拒绝提供服务。例如,服务允许直接访问静态文件,但是不允许访问某个目录:
图片描述
否则,别人对你服务器上的文件就一览无遗了。
403和401的区别在于,401是没有认证,没有登陆验证之类的错误。

6、500 内部服务器错误
如业务代码出现了异常没有捕获,被tomcat捕获了,就会返回500错误:
图片描述
如:数据库字段长度限制为30个字符,如果没有判断直接插入一条31个字符的记录,就会导致数据库抛异常,如果异常没有捕获处理,就直接返回500。

当服务彻底挂了,连返回都没有的时候,那么就是502了。

7、502 Bad Gateway 网关错误
图片描述
这种情况是因为nginx收到请求,但是请求没有打过去,可能是因为业务服务挂了,或者是打过去的端口号写错了

8、504 Gateway Timeout 网关超时
通常是因为服务处理请求太久,导致超时,如PHP服务默认的请求响应最长处理时间为30s,如果超过30s,将会挂掉,返回504,如下图所示:
图片描述

2.6、HTTP的基本优化

影响一个HTTP网络请求的因素主要有两个:带宽延迟

  • 带宽
    如果说我们还停留在拨号上网的阶段,带宽可能会成为一个比较严重影响请求的问题,但是现在网络基础建设已经使得带宽得到极大的提升,我们不再会担心由带宽而影响网速,那么就只剩下延迟了。
  • 延迟
    1、浏览器阻塞(HOL blocking):浏览器会因为一些原因阻塞请求。浏览器对于同一个域名,同时只能有 4 个连接(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞。
    2、DNS 查询(DNS Lookup):浏览器需要知道目标服务器的 IP 才能建立连接。将域名解析为 IP 的这个系统就是 DNS。这个通常可以利用DNS缓存结果来达到减少这个时间的目的。
    3、建立连接(Initial connection):HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大

http的发展也就是在不断地优化这些方向上的问题。

3、http1.1

HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较为简单的网页上和网络请求上,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使用最为广泛的HTTP协议。 主要区别主要体现在:

  • 缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
  • 带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
  • 错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
  • Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
  • 长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

虽然 HTTP/1.1 已经优化了很多点,作为一个目前使用最广泛的协议版本,已经能够满足很多网络需求,但是随着网页变得越来越复杂,甚至演变成为独立的应用,HTTP/1.1 逐渐暴露出了一些问题:

  • 在传输数据时,每次都要重新建立连接,对移动端特别不友好
  • 传输内容是明文,不够安全
  • header 内容过大,每次请求 header 变化不大,造成浪费
  • keep-alive 给服务端带来性能压力 为了解决这些问题,HTTPS 和 SPDY 应运而生。

4、HTTPS

HTTPS 是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版,即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。
图片描述

  • HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。
  • HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。
  • HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  • HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。

5、SPDY:HTTP1.x的优化

2012年google如一声惊雷提出了SPDY的方案,优化了HTTP1.X的请求延迟,解决了HTTP1.X的安全性,具体如下:

  • 降低延迟,针对HTTP高延迟的问题,SPDY优雅的采取了多路复用(multiplexing)。多路复用通过多个请求stream共享一个tcp连接的方式,解决了HOL blocking的问题,降低了延迟同时提高了带宽的利用率。
  • 请求优先级(request prioritization)。多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY允许给每个request设置优先级,这样重要的请求就会优先得到响应。比如浏览器加载首页,首页的html内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。
  • header压缩。前面提到HTTP1.x的header很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量。
  • 基于HTTPS的加密协议传输,大大提高了传输数据的可靠性。
  • 服务端推送(server push),采用了SPDY的网页,例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。

SPDY构成图:

图片描述
SPDY位于HTTP之下,TCP和SSL之上,这样可以轻松兼容老版本的HTTP协议(将HTTP1.x的内容封装成一种新的frame格式),同时可以使用已有的SSL功能。

6、HTTP2.0

HTTP2.0可以说是SPDY的升级版(其实原本也是基于SPDY设计的),但是,HTTP2.0 跟 SPDY 仍有不同的地方,如下:
HTTP2.0和SPDY的区别:

  • HTTP2.0 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS
  • HTTP2.0 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DEFLATE

HTTP/2 新特性

6.1、二进制传输

HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。 HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。

接下来我们介绍几个重要的概念:

  • 流:流是连接中的一个虚拟信道,可以承载双向的消息;每个流都有一个唯一的整数标识符(1、2…N);
  • 消息:是指逻辑上的 HTTP 消息,比如请求、响应等,由一或多个帧组成。
  • 帧:HTTP 2.0 通信的最小单位,每个帧包含帧首部,至少也会标识出当前帧所属的流,承载着特定类型的数据,如 HTTP 首部、负荷,等等

图片描述

HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装。

6.2、多路复用

在 HTTP/2 中引入了多路复用的技术。多路复用很好的解决了浏览器限制同一个域名下的请求数量的问题,同时也接更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度。

在 HTTP/2 中,有了二进制分帧之后,HTTP /2 不再依赖 TCP 链接去实现多流并行了,在 HTTP/2中:

  • 同域名下所有通信都在单个连接上完成。
  • 单个连接可以承载任意数量的双向数据流。
  • 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。

这一特性,使性能有了极大提升:

  • 同个域名只需要占用一个 TCP 连接,使用一个连接并行发送多个请求和响应,消除了因多个 TCP 连接而带来的延时和内存消耗。
  • 并行交错地发送多个请求,请求之间互不影响。
  • 并行交错地发送多个响应,响应之间互不干扰。
  • 在HTTP/2中,每个请求都可以带一个31bit的优先值,0表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。

图片描述
如上图所示,多路复用的技术可以只通过一个 TCP 连接就可以传输所有的请求数据。

6.3、Header 压缩

在 HTTP/1 中,我们使用文本的形式传输 header,在 header 携带 cookie 的情况下,可能每次都需要重复传输几百到几千的字节。

为了减少这块的资源消耗并提升性能, HTTP/2对这些首部采取了压缩策略:

  • HTTP/2在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;
  • 首部表在HTTP/2的连接存续期内始终存在,由客户端和服务器共同渐进地更新;
  • 每个新的首部键-值对要么被追加到当前表的末尾,要么替换表中之前的值

例如下图中的两个请求, 请求一发送了所有的头部字段,第二个请求则只需要发送差异数据,这样可以减少冗余数据,降低开销
图片描述

6.4、服务端推送(Server Push)

Server Push即服务端能通过push的方式将客户端需要的内容预先推送过去,也叫“cache push”。

可以想象以下情况,某些资源客户端是一定会请求的,这时就可以采取服务端 push 的技术,提前给客户端推送必要的资源,这样就可以相对减少一点延迟时间。当然在浏览器兼容的情况下你也可以使用 prefetch。

例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。
图片描述

服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行。

后续更多文章将在我的github第一时间发布,欢迎关注。

参考

查看原文

赞 13 收藏 12 评论 2

梦kWmLG 赞了文章 · 2020-12-31

面试经典之http中get与post的区别

GETPOSTHTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二。
最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数。

你可能自己写过无数个GETPOST请求,或者已经看过很多权威网站总结出的他们的区别,你非常清楚知道什么时候该用什么。

1、常规答案

当你在面试中被问到这个问题,你的内心充满了自信和喜悦。你轻轻松松的给出了一个“标准答案”:

-GETPOST
后退按钮/刷新无害数据会被重新提交(浏览器应该告知用户数据会被重新提交)。
书签可收藏为书签不可收藏为书签
缓存能被缓存不能缓存
编码类型application/x-www-form-urlencoded 只能进行url编码application/x-www-form-urlencodedmultipart/form-data。为二进制数据使用多重编码。
历史参数保留在浏览器历史中。参数不会保存在浏览器历史中。
对数据长度的限制是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。无限制。
对数据类型的限制只允许 ASCII 字符。没有限制。也允许二进制数据。
安全性与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。在发送密码或其他敏感信息时绝不要使用 GET !POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。
可见性数据在 URL 中对所有人都是可见的。数据不会显示在 URL 中。

“很遗憾,这不是我们要的回答!”

请告诉我真相。。。

2、本质区别

如果我告诉你GET和POST本质上没有区别你信吗?

让我们扒下GET和POST的外衣,坦诚相见吧!

GET和POST是什么?HTTP协议中的两种发送请求的方法。

HTTP是什么?HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议。

HTTP的底层是TCP/IP。所以GET和POST的底层也是TCP/IP,也就是说,GET/POST都是TCP链接。GET和POST能做的事情是一样一样的。你要给GET加上request body,给POST带上url参数,技术上是完全行的通的。

2.1 那么,“标准答案”里的那些区别是怎么回事?

在我大万维网世界中,TCP就像汽车,我们用TCP来运输数据,它很可靠,从来不会发生丢件少件的现象。但是如果路上跑的全是看起来一模一样的汽车,那这个世界看起来是一团混乱,送急件的汽车可能被前面满载货物的汽车拦堵在路上,整个交通系统一定会瘫痪。为了避免这种情况发生,交通规则HTTP诞生了。HTTP给汽车运输设定了好几个服务类别,有GET, POST, PUT, DELETE等等,HTTP规定,当执行GET请求的时候,要给汽车贴上GET的标签(设置method为GET),而且要求把传送的数据放在车顶上(url中)以方便记录。如果是POST请求,就要在车上贴上POST的标签,并把货物放在车厢里。当然,你也可以在GET的时候往车厢内偷偷藏点货物,但是这是很不光彩;也可以在POST的时候在车顶上也放一些数据,让人觉得傻乎乎的。HTTP只是个行为准则,而TCP才是GET和POST怎么实现的基本。

但是,我们只看到HTTP对GET和POST参数的传送渠道(url还是requrest body)提出了要求。

2.2、“标准答案”里关于参数大小的限制又是从哪来的呢?

在我大万维网世界中,还有另一个重要的角色:运输公司。不同的浏览器(发起http请求)和服务器(接受http请求)就是不同的运输公司。 虽然理论上,你可以在车顶上无限的堆货物(url中无限加参数)。但是运输公司可不傻,装货和卸货也是有很大成本的,他们会限制单次运输量来控制风险,数据量太大对浏览器和服务器都是很大负担。业界不成文的规定是,(大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。超过的部分,恕不处理。如果你用GET服务,在request body偷偷藏了数据,不同服务器的处理方式也是不同的,有些服务器会帮你卸货,读出数据,有些服务器直接忽略,所以,虽然GET可以带request body,也不能保证一定能被接收到哦。

好了,现在你知道,GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。

2.3、最终boss

你以为本文就这么结束了?
我们的大BOSS还等着出场呢。。。
这位BOSS有多神秘?当你试图在网上找“GET和POST的区别”的时候,那些你会看到的搜索结果里,从没有提到他。他究竟是什么呢。。。

GET和POST还有一个重大区别,简单的说:

GET产生一个TCP数据包;POST产生两个TCP数据包。
也就是说,GET只需要汽车跑一趟就把货送到了,而POST得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。

因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为什么?

  1. GET与POST都有自己的语义,不能随便混用。
  2. 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。
  3. 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

好了,看到这里之后再也不怕面试官问get与post请求的区别了。

查看原文

赞 13 收藏 5 评论 0

梦kWmLG 赞了回答 · 2020-11-25

如何在react.js 中利用for循环之类的输出html

var doms = [];
for (var i = 0; i < 24; i++) {
  doms.push(<a>{i}</a>);
}
return doms;

我一般结合 underscore.js 的 map 方法:

return _.map(persons, function (p) {
  return <div>{p.name} | {p.age}</div>;
});

关注 8 回答 7

梦kWmLG 赞了回答 · 2020-11-25

如何在react.js 中利用for循环之类的输出html

render() {
    return (
      <div>
        {this.state.comments.map((comment) => (
          <Comment comment={comment} key={comment.id} />
        ))}
      </div>
    );
  }

关注 8 回答 7

梦kWmLG 赞了文章 · 2020-08-12

Vue中的computed

引言

使用vue框架已经一年多的时间了,虽然踩了不少的坑,但是 有些错误是经常性的。正好利用现在的空余时间,对自己所学的,所用的东西进行整理,总结。避免下次在采坑,也希望自己的总结,能够带给别人一些启发。

computed的定义

当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值。

为什么要使用computed

首先,通过vue官方文档的案例,来解释一下,为什么要使用computed。我们都知道,在模板内的表达式非常遍历的,但是,有时候,我们会在模板内的放入太多逻辑的东西。会让模板变重,且难于维护。

<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

在这模板中的代码中,其实,我们需要花费上一小段时间去理解,这块渲染的是什么---message的翻转字符串。然而,当初模板中使用表达式的初衷时为了简单运算的。所以,从这点出发,我们是不是就不建议在模板中使用过于复杂的表达式了。此时,计算属性就横空出世了。计算属性就是当依赖的属性的值发生变化的时候,才会触发他的更改,如果依赖的值,不发生变化的时候,使用的是缓存中的属性值。

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>


var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    }
  }
})

computed的getter函数

在vue中,computed的属性可以被视为是data一样,可以读取和设值。因此,在computed中可以分为getter(读取)和setter(设值),一般情况下,是没有setter的,computed只是预设了getter,也就是只能读取,不可以改变设值。所以,computed默认格式(是不表明getter函数的):
html:

    <div>
     message: {{message}}
    </div>

    <!-- 计算属性 -->
    <div>
     计算属性: {{updateMessage}}
   </div>
computed: {
    updateMessage(): {
            console.log('计算属性', this.message)
            return this.message
    }
}

等价于

computed: {
    
    updateMessage: {
      get: function() {
        console.log('计算属性', this.message)
        return this.message
      }
    }
  },

发现了一个小小的惊喜:当模板中不使用updateMessage,即使message发生改变之后,也不会走computed。神奇不神奇??哈哈哈

在这里,就需要我们注意一下,不是说我们更改了getter中使用的变量(即依赖的属性),就会触发computed的更新,他有一个前提是computed里的值必须要在模板中使用才可以。但是会触发生命周期的updated()

computed中的setter函数

当赋值给计算属性的时候,将调用setter函数。多用于在模板组件中需要修改计算属性自身的值的时候。

computed: {
    updateMessage: {
      get: function() {
        console.log('计算属性', this.message)
        return this.message
      },
      set: function(newVal) {
        this.message = newVal
        console.log('newVal', newVal)
      }
    }
  },
 mounted () {
    this.updateMessage = '222'
    console.log('测试:', this)
 },

只有当计算属性中的属性被直接赋值的时候,才会走setter函数,而且,setter函数和getter函数是相互独立的,不是说,走setter函数,就必须走getter函数。上面的案例,打印结果是

newVal: 222,
计算属性: 222

是因为,在setter中触发了message的更改,当message发生改变的时候,getter函数中就会改变。

computed: {
    updateMessage: {
      get: function() {
        console.log('计算属性', this.message)
        return this.message
      },
      set: function(newVal) {
        console.log('newVal', newVal)
      }
    }
  },
 mounted () {
    console.log('测试:', this)
 },

这种情况下,打印结果是:

newVal 222

此时,就只是单单的走了setter的函数,而没有走getter函数。

总结

这篇文章呢,主要是介绍一下关于computed的基本构成和使用,也算是,自己对computed的一个简单的总结把。不会让自己在做项目的过程中,遇见关于类似的问题,而无法解决。不知道如何使用。然后呢,等撸vue的源码的时候,在深入的写一篇关于computed的原理的文章。因为有些神奇的现象是必须要通过原理来解释的。

发现好博

https://juejin.im/post/5a6f21...
https://knownsec-fed.com/2018...
https://www.jianshu.com/p/56f...

很感谢大家利用这么长时间来读这篇文章,文章中若有错误请在下方留言,会尽快做出修改。

查看原文

赞 13 收藏 4 评论 3

梦kWmLG 回答了问题 · 2020-07-03

koa2 上传文件如何不限制大小?

俺也一样~~~~

关注 2 回答 2

认证与成就

  • 获得 0 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2020-07-03
个人主页被 97 人浏览