HTTP面试题笔记
了解从输入url到看见页面,发生了什么?
1、首先,在浏览器地址栏中输入url
2、浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。
3、在发送http请求前,需要域名解析(DNS解析),解析获取相应的IP地址。
4、浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。
5、握手成功后,浏览器向服务器发送http请求,请求数据包。
6、服务器处理收到的请求,将数据返回至浏览器
7、浏览器收到HTTP响应
8、读取页面内容,浏览器渲染,解析html源码
9、生成Dom树、解析css样式、js交互
10、客户端和服务器交互
11、ajax查询
GET 和 POST 的区别有哪些?
区别一:幂等性
- 由于 GET 是读,POST 是写,所以 GET 是幂等的,POST 不是幂等的。
- 由于 GET 是读,POST 是写,所以用浏览器打开网页会发送 GET 请求,想要POST 打开网页要用 form 标签。
- 由于 GET 是读,POST 是写,所以 GET 打开的页面刷新是无害的,POST 打开的页面刷新需要确认。
- 由于 GET 是读,POST 是写,所以 GET 结果会被缓存,POST 结果不会被缓存。
- 由于 GET 是读,POST 是写,所以 GET 打开的页面可被书签收藏,POST 打开的不行。
区别二:请求参数
- 通常,GET 请求参数放在 url 里,POST 请求数据放在 body(消息体)里。
- GET 比 POST 更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
- GET 请求参数放在 url 里是有长度限制的,而 POST 放在 body 里没有长度限制。
区别三:TCP packet
-
GET 产生一个 TCP 数据包;POST 产生两个或以上 TCP 数据包。
注意:
根据技术规格文档,GET 和 POST 最大的区别是语义;但面试官一般问的是 实践过程中二者的区别,因此你需要了解服务器和浏览器对 GET 和 POST 的常见实现方法。
HTTP 缓存有哪些方案?
什么是HTTP缓存?
- 当我们访问一个网站时,第一次访问就需要加载各种资源(如js,html,css等等),为了之后再次访问该网站,不再重复加载各种资料,就需要通过HTTP缓存策略来缓存一些资料,这样下次访问就直接从缓存获取,不再需要从服务器中获取,从而提高网站的访问速度,达到快速渲染效果。
请求缓存的类别
强缓存
第一次访问网站,就会向服务器发送请求,服务器则响应请求内容。如请求内容需要缓存下来,当下次再起请求该内容时,浏览器会先去检查这个时间有没有过期,没有过期则从缓存中获取,过期了则重新向服务器获取该资源。
如何设置(强缓存)
1、HTTP1.1的强缓存设置:设置方法是在响应头设置Cache-Control:max-age=3600
(则浏览器就会在本地缓存中保存这些文件,时间是自动缓存3600秒),检查max-age有没有过期。
2、HTTP1.0的强缓存设置:设置过期时间Expires: Wed, 21 Oct 2015 02:30:00 GMT
,检查Expires的值是否过期
内容协商(弱缓存)
如果使用了协商缓存的话,当浏览器访问网站的时候,服务器就会返回资源和资源标识,浏览器可以把资源和资源标识缓存到浏览器,当后续再次访问网站的时候,浏览器会把请求和资源标识一起发给服务器,这样服务器就会根据资源标识判断当前本地缓存的版本是否跟服务器的版本一致:
如果一致,服务器就会返回304状态码
,浏览器就可以直接从缓存中拿资源文件。
如果不一致,服务器就会返回200状态码
,同时会把新的资源和资源标识一起返回浏览器,浏览器再进行重新缓存。
如何设置(弱缓存)
1、HTTP1.1的弱缓存:Etag
(资源文件唯一字符串)
浏览器下次请求的时候就会将资源标识(if-None-Match
)这个值(就是上一次从服务器获得的Etag值)放在请求头里发送给服务器,服务器会将资源标识(Etag)放在响应头中返回,通过对比这两个唯一字符串来判断本地缓存的资源文件是否一致,从而选择从哪里获取资源。
2、HTTP1.0的弱缓存:Last-Modified
(上次修改时间)
浏览器下次请求的时候就会将资源标识(if-Modified-Since
)这个值(就是上一次从服务器获得的Last-Modified值)放在请求头里发送给服务器,服务器会将资源标识(Last-Modified)放在响应头中返回,通过对比这两个修改时间来判断本地缓存的资源文件是否一致,从而选择从哪里获取资源。
**注意:**应该优先使用HTTP1.1方案,对比HTTP1.0的强缓存,HTTP1.0如果用户自身时间错乱,可能导致缓存时间过期,对比HTTP1.0弱缓存,Last-Modified只能精确到秒,但是我们前端都是精确到毫秒级的,我们应该优先使用Etag。
**注意:**Pragma ,但 MDN 已经明确不推荐使用它。
HTTP 和 HTTPS 的区别有哪些?
区别列表
- HTTP 是明文传输的,不安全;HTTPS 是加密传输的,非常安全。
- HTTP 使用 80 端口,HTTPS 使用 443 端口。
- HTTP 较快,HTTPS 较慢。
- HTTPS 的证书一般需要购买(但也有免费的),HTTP 不需要证书。
看到比较好的文章链接
HTTP/1.1 和 HTTP/2 的区别有哪些?
区别列表
- HTTP/2 使用了二进制传输,而且将 head 和 body 分成帧来传输;HTTP/1.1 是字 符串传输。
- HTTP/2 支持多路复用,HTTP/1.1 不支持。多路复用简单来说就是一个 TCP 连接 从单车道(不是单行道)变成了几百个双向通行的车道。
- HTTP/2 可以压缩 head,但是 HTTP/1.1 不行。
- HTTP/2 支持服务器推送,但 HTTP/1.1 不支持。(实际上没多少人用)
TCP 三次握手和四次挥手是什么?
建立 TCP 连接时 server 与 client 会经历三次握手
- 浏览器向服务器发送 TCP 数据:SYN(seq=x)
- 服务器向浏览器发送 TCP 数据:ACK(seq=x+1) SYN(y)
- 浏览器向服务器发送 TCP 数据:ACK(seq=y+1)
关闭 TCP 连接时 server 与 client 会经历四次挥手
- 浏览器向服务器发送 TCP 数据:FIN(seq=x)
- 服务器向浏览器发送 TCP 数据:ACK(seq=x+1)
- 服务器向浏览器发送 TCP 数据:FIN(seq=y)
- 浏览器向服务器发送 TCP 数据:ACK(seq=y+1)
为什么 2、3 步骤不合并起来呢?
因为2、3 中间服务器很可能还有数据要发送,不能提前发送 FIN。
说说同源策略和跨域
同源策略是什么?
如果两个 URL 的协议、端口和域名都完全一致的话,则这两个 URL 是同源的。
http://www.baidu.com/s
http://www.baidu.com:80/ssdasdsadad
同源策略怎么做?
只要在浏览器里打开页面,就默认遵守同源策略。
**优点:**保证用户的隐私安全和数据安全。
缺点:
很多时候,前端需要访问另一个域名的后端接口,会被浏览器阻止其获取响应。 比如甲站点通过 AJAX 访问乙站点的 /money 查询余额接口,请求会发出,但是响应会被浏览器屏蔽。
**怎么解决缺点:**使用跨域手段。
有一下几种方式
JSONP方式解决跨域
**基本原理:**主要就是利用了 script
标签的src
没有跨域限制来完成的。
执行过程
- 前端定义一个解析函数(如:
jsonpCallback = function (res) {}
) - 通过
params
的形式包装script
标签的请求参数,并且声明执行函数(如cb=jsonpCallback
) - 后端获取到前端声明的执行函数(
jsonpCallback
),并以带上参数且调用执行函数的方式传递给前端 - 前端在
script
标签返回资源的时候就会去执行jsonpCallback
并通过回调函数的方式拿到数据了。
**缺点:**只能进行GET请求
**优点:**兼容性好,在一些古老的浏览器中毒可以运行
CORS方式解决
CORS(Cross-origin resource sharing) “跨域资源共享”
在出现CORS标准之前, 我们还只能通过jsonp(jsonp跨域请求详解)的形式去向“跨源”服务器去发送 XMLHttpRequest 请求,这种方式吃力不讨好,在请求方与接收方都需要做处理,而且请求的方式仅仅局限于GET。所以 ,CORS标准必然是大势所趋,并且市场上绝大多数浏览器都已经支持CORS。(IE10以上)
CORS概念
支持CORS请求的浏览器一旦发现ajax请求跨域,会对请求做一些特殊处理,对于已经实现CORS接口的服务端,接受请求,并做出回应。
有一种情况比较特殊,如果我们发送的跨域请求为“非简单请求”,浏览器会在发出此请求之前首先发送一个请求类型为OPTIONS的“预检请求”,验证请求源是否为服务端允许源,这些对于开发这来说是感觉不到的,由浏览器代理。
总而言之,客户端不需要对跨域请求做任何特殊处理。
简单请求与非简单请求
浏览器对跨域请求区分为“简单请求”与“非简单请求”
“简单请求”满足以下特征:
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:
application/x-www-form-urlencoded、 multipart/form-data、text/plain
不满足这些特征的请求称为“非简单请求”,例如:content-type=applicaiton/json , method = PUT/DELETE...
简单请求
浏览器判断跨域为简单请求时候,会在Request Header中添加 Origin **(协议 + 域名 + 端口)**字段 , 它表示我们的请求源,CORS服务端会将该字段作为跨源标志。
CORS接收到此次请求后 , 首先会判断Origin是否在允许源(由服务端决定)范围之内,如果验证通过,服务端会在Response Header 添加 Access-Control-Allow-Origin、Access-Control-Allow-Credentials等字段。
//必须字段:
Access-Control-Allow-Origin:表示服务端允许的请求源,*标识任何外域,多个源 , 分隔
//可选字段
Access-Control-Allow-Credentials:false 表示是否允许发送Cookie,设置为true同时,ajax请求设置withCredentials = true,浏览器的cookie就能发送到服务端
Access-Control-Expose-Headers:调用getResponseHeader()方法时候,能从header中获取的参数
浏览器收到Respnose后会判断自己的源是否存在 Access-Control-Allow-Origin允许源中,如果不存在,会抛出“同源检测异常”。
总结:简单请求只需要CORS服务端在接受到携带Origin字段的跨域请求后,在response header中添加Access-Control-Allow-Origin等字段给浏览器做同源判断
非简单请求
进行非简单请求时候 , 浏览器会首先发出类型为OPTIONS的“预检请求”,请求地址相同 ,
CORS服务端对“预检请求”处理,并对Response Header添加验证字段,客户端接受到预检请求的返回值进行一次请求预判断,验证通过后,主请求发起。
例如:发起 content-type=application/json 的非简单请求,这时候传参要注意为json字符串
这里可以看到,浏览器连续发送了两个jsonp.do请求 , 第一个就是“预检请求”,类型为OPTIONS,因为我们设置了content-type这个属性,所以预检请求的Access-Control-Expose-Headers必须携带content-type,否则预检会失败。
总结:非简单请求需要CORS服务端对OPTIONS类型的请求做处理,其他与简单请求一致
CORS不必关心发出的请求是否跨域,浏览器会帮我们处理这些事情,但是服务端需要支持CORS,服务端实现CORS的原理也很简单,在服务端完全可以对请求做上下文处理,已达到接口允许跨域访问的目的。
. Nginx 代理 / Node.js 代理
前端 ⇒ 后端 ⇒ 另一个域名的后端
详情参考MDN CORS 文档
Session、Cookie、LocalStorage、SessionStorage 的区别
• Cookie V.S. LocalStorage
- 主要区别是 Cookie 会被发送到服务器,而 LocalStorage 不会
- Cookie 一般最大 4k,LocalStorage 可以用 5Mb 甚至 10Mb(各浏览器不 同)
• LocalStorage V.S. SessionStorage
- LocalStorage 一般不会自动过期(除非用户手动清除)
- SessionStorage 在回话结束时过期(如关闭浏览器之后,具体由浏览器自行 决定)
• Cookie V.S. Session
- Cookie 存在浏览器的文件里,Session 存在服务器的文件里
- Session 是基于 Cookie 实现的,具体做法就是把 SessionID 存在 Cookie 里