(建议收藏)前端面试必问的十六条HTTP网络知识体系

588次阅读  |  发布于3年以前

一、什么是URI?

URI, 全称为(Uniform Resource Identifier), 也就是统一资源标识符。它并不是我们常说的网址URL, 实际上URI = URN+URL

1.URI的结构

它主要由以下几个结构组成:

scheme 表示协议名,比如http,httpsuser:passwd@ 表示登录主机时的用户信息 host 主机名 port 端口 path 资源路径 query 表示查询参数,通常以?开头多个值之间以&连接 fragment 页面资源锚点位置,常见为:https://www.baidu.com/path/index.html#name

2.URI编码

URI只能使用ASCII, ASCII之外的字符是不支持显示的。此外,URI引入了编码机制,将所有非ASCII码字符和界定符转为十六进制字节值,然后在前面加个%,例如:空格被转义成了%20

二、HTTP状态码你能记住哪些?

HTTP状态码总体分为五类:

整体范围 已定义范围 含义
100~199 100~101 信息提示
200~299 200~206 成功
300~399 300~305 重定向
400~499 400~415 客户端错误
500~599 500~505 服务器错误

接下来详细看下每个状态码的含义:

1xx相关

100 请求中间状态,客户端需要继续下一步请求。 101 协议切换。例如当HTTP请求升级到websocket服务的时候,如果服务端同意升级,则会返回101状态码。

2xx相关

200 请求成功。请求中最常见的状态码,也是开发最喜欢的状态,表示请求一切正常。 201 成功请求并创建了新的资源。 202 服务端已接受请求,但未完成处理。 204 没有内容。表示只返回head头信息,主体内容没返回。 206 表示部分内容。常见于大型文件上传或下载的过程。

3xx相关

301 永久重定向。将资源永远的移到新的域名下。 302 临时重定向。将资源临时移到新地方,以后还有可能再移回来。 备注:301、302常见于SEO优化或http缓存。以http缓存为例:若永久重定向到新资源,则浏览器会缓存新资源,并抛弃老域名的缓存。若临时重定向则不做缓存优化。 304 常见于http缓存。例如 max-age时间过期,命中协商缓存的时候,浏览器会携带相关信息到服务端,服务器对比信息后发现文件没更新可以继续使用的情况下就会返回304状态码,意思是告诉客户端文件可以继续使用。 305 使用代理。表示当前请求的资源必须通过代理访问。 307 临时重定向,与302类似。

4xx相关

400 开发者请求错误。比较粗糙的提示,具体错误原因不明。 401 要求请求方,也就是用户需要进行身份认证。 403 服务器拒绝访问。因法律、敏感词汇等原因,服务器拒绝客户端的请求。 404 资源未找到。这个很容易理解,也比较常见,服务端没有对应的资源内容的时候会返回此状态码。 405 请求方法错误。比较常见于服务端只支持POST请求,但是开发者用GET方式请求了接口,就会返回这个错误。反之亦然。 406 服务端资源因某种原因无法满足客户端的请求条件。 407 与401类似,要求代理的身份认证。 408 客户端发送请求时间超时,服务器没有时间继续等待了。 409 服务器处理内容的时候发生了冲突。 410 类似404,表示资源以前可能存在,现在被删除了。 413 客户端请求体过大,服务器因无法处理而拒绝。 414 请求的URL地址太长,服务器无法处理。

5xx相关

500 服务器内部错误,具体啥错误咱也不知道,只知道是出错了。 501 表示服务器不支持客户端的请求功能。 502 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应。 503 服务器内部较忙,暂时无法相应。 504 充当网关或代理的服务器,未及时从远端服务器获取请求。 505 服务器不支持请求的HTTP协议的版本,无法完成处理。

三、GET与POST的区别

  1. GET请求会被浏览器留下访问记录,而POST不会留下记录;
  2. GET请求参数携带在URL后面,不太安全,而POST参数会放到请求体重,适合传输敏感数据;
  3. GET只能发送 ASCII 字符,而POST没限制。
  4. 发送数据时机不同。GET请求会一次性将数据发送出去,而POST发送分两部分,先发送header头部分,如果服务端相应100状态码(继续),然后再发送body部分。
  5. 受URL长度限制,GET传输数据较少,而POST传输数据量较大,一般默认为不受限制。
  6. 幂等性的角度来说,GET是幂等的(只要参数不变,返回的结果总是相等的),而POST不是。
  7. GET在浏览器回退时是无害的,而POST会再次发起请求。

四、COOKIE相关

1.什么是cookie

从本质上来说,cookie就是存储在客户端的一小段文本,以键值对的方式存储在浏览器里。通常浏览器只会分配4KB的空间给cookie,所以存储内容较少。通常js可以设置、读取、删除cookie,服务端也可以通过Set-Cookie头字段对浏览器进行Cookie写入。若服务端设置属性为http-only,客户端js脚本则无法读取到Cookie值。

以下是百度网站的一段Cookie截图:

属性说明:

Name Cookie名称

Value Cookie内容

Domain 可以读取当前Cookie的有效域名

Path 可以读取当前Cookie的有效路径

Expires/Max-Age Cookie有效绝对时间/过期相对时间(Session代表当前会话期间,网页关闭即失效)

Size Cookie大小

HttpOnly 当前Cookie是否只能通过http获取,携带到服务端,js脚本无法获取

Secure 是否只能通过https传输Cookie

SameParty Cookie安全模式,支持三个值:1、None,默认模式,http请求默认会带上Cookie值。2、Lax模式,只能再GET方法中携带Cookie。3、Strict,严格模式,只能在当前域名下访问Cookie,其他域名均无法访问。

Priority 优先级,chrome的提案,定义了三种优先级,Low/Medium/High,当cookie数量超出时,低优先级的cookie会被优先清除

2.Cookie的生命周期

我们通常通过ExpiresMax-Age这两个属性来设置Cookie的过期时间。前者指定过期的具体时间,后者是过期的相对时间。若过期,浏览器不会主动删除Cookie内容,只是无法被读取到或者无法发送到服务端。

3.Cookie的作用域

涉及到两个关键词汇:1、域名(Domain)。2、路径(Path)。不同域名或路径下无法相互访问Cookie内容,当然顶级域名下的Cookie在子域名之间是共享的,以百度网站为例:.baidu.com下的cookie可以共享给子域名访问,例如www.baidu.comtieba.baidu.com等。根路径(/)下的cookie也可以共享给任何子目录访问。

4.安全、性能优化相关

Cookie是以字符串的方式存储在客户端,以明文的方式在服务器与客户端之间传输,容易被拦截修改。不论当前请求是否需要Cookie,请求都会携带上当前域名下的所有Cookie,所以会产生大量不必要的数据,影响服务端性能以及带宽。可以通过设置CookieDomain以及Path适当控制携带的数量。

5.其他存储方式

除了Cookie存储之外,现代浏览器还支持localStoragesessionStorage存储,两者的主要区别在于前者是永久存储在浏览器,后者的生命周期是会话级别的,网页关闭即消失。还有indexDB,感兴趣的同学可参考阮老师的 浏览器数据库 IndexedDB 入门教程

五、跨域问题

1.为什么会产生跨域

相信现在绝大多数公司采用的都是前后端分离的开发模式,通过Ajax请求响应数据,当前访问网页的URL与接口地址用的不是一个域名。这个时候浏览器就会认为是跨域了,存在一定安全隐患。详细来说就是请求网页与接口之间只要满足以下任一条件,即被认为跨域:

因为浏览器遵循同源策略,当请求与响应不同源的时候,浏览器会试图先发送一个OPTIONS预请求给服务端,同时会加上Origin源地址和Host目标地址,询问是否允许跨域,也就是看http返回头字段Access-Control-Allow-Origin,若是*表示允许任何请求,也可以是指定的请求源地址。若允许则继续,否则浏览器会中断后续请求并打印错误。注意是被浏览器拦截了,请求是到达服务端了。服务端发号施令,控制是否允许跨域,而浏览器是实际执行者。

2.常见的跨域解决方案

JSONP

JSONP实现的原理:虽然XMLHttpRequest对象遵循同源政策,但是script标签不一样,它可以通过 src 填上目标地址从而发出 GET 请求,实现跨域请求并拿到响应。接下来我们封装一个简单的JSONP:

let myJSONP = (_url,params,callback) => {
 let splitUrl = (_url,params) => {
  let str = '';
  for(let key in params){
   str += key+'='+params[key]
  }
  return _url + '?' + str
 }
 return new Promise(resolve => {
  let _srcipt = document.createElement('script');
  _srcipt.src = splitUrl(_url,params);
  document.body.appendChild(_srcipt);
  window[callback] = res => {
   resolve(res)
   //渣男,用完即删除
   document.body.removeChild(_srcipt)
  }
 })
}

Nginx

让运维同学在Nginx中做反向代理,将所有请求中转一下,让服务端识别请求,以为是来自同源的请求,予以通过。 比如说现在客户端的域名为client.com,服务器的域名为server.com,客户端向服务器发送 Ajax 请求。Nginx配置方式如下:

server {
  listen  443;
  server_name  client.com;
  location /yourApiAddress {
    proxy_pass server.com;
  }
}

Nginx在其中相当于跳板机的作用。

CORS

开发同学代码中CORS设置允许任何来源即可。个人推荐这种配置,基本上一劳永逸,Nginx代理是运维同学设置的,经常遇到服务器调整等原因导致跨域反反复复,比较烦人。

其他方式

除此之外就是一些奇淫技巧的跨域解决方案,例如postMessageiframe等等,现实中基本上不会用到。就不建议深入了解了,记个大概即可。

六、HTTP请求方法有哪些

HTTP1.0:GETPOSTHEAD HTTP1.1:PUTPATCHDELETEOPTIONSTRACECONNECT

方法 描述
GET 获取资源
POST 资源传输,通常会修改服务器资源
HEAD 获得请求头信息
PUT 更新资源
DELETE 删除资源
PATCH 对PUT的补充,对已知资源部分更新
OPTIONS 列出请求资源支持的请求方法,用来跨域请求
TRACE 追踪请求/响应路径,用于测试或诊断
CONNECT 将连接改为管道方式用于代理服务器

七、常见HTTP请求头有哪些

1.Request Headers

User-Agent 浏览器信息,内容包含发出请求的用户信息。 Cookie 当前域名下所有能读取到的Cookie内容,不论服务器是否需要,都会被携带。 Accept 浏览器可接受的MIME类型。 Accept-Charset 浏览器可接受的字符集。 Accept-Encoding 浏览器可接受的压缩编码方式,常见的压缩方式有gzipbrServlet Accept-Language 浏览器能接受的语言。 Content-Length 表示请求消息正文的长度。 Authorization 授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中。 Host 客户端请求域。 If-Modified-Since 对应 response返回值 last-Modified 文件最后修改时间。 If-None-Match 对应 response返回值 Etag 文件唯一标识。

2.Response Headers

Cache-control 详见下面http缓存一栏,会详细讲 Content-encoding 压缩编码方式,对应 Accept-Encoding Content-Length 表示内容长度。 Content-Type 表示后面的文档属于什么MIME类型 Date 当前的GMT时间。 Expires 告诉客户端缓存的绝对时间(目前基本上已不再使用) Last-Modified 文件最后编辑时间 Etag 当前文件内容唯一标识,若被重新修改则会有变动。 Server 服务器通过这个头告诉浏览器服务器的类型。

八、TCP三次握手

在介绍三次握手之前,先抛出一个问题:为什么是三次握手,不是两次或者四次?

首先我们要先理解握手的目的是什么?为了确保双方的发送、接收能力正常。就像打电话之前,双方先“喂喂喂,听得见嘛”,一个道理。

最开始客户端处于CLOSED状态,服务器处于LISTEN状态(随时等待被撩)。

九、TCP四次挥手

有握手的过程,必然就会有分手的过程嘛。四次的过程是这样的:

十、HTTP缓存

缓存是性能优化中非常重要的一环,浏览器的缓存机制对开发也是非常重要的知识点。接下来以三个部分来把浏览器的缓存机制说清楚:

1.什么是强缓存、协商缓存

关于什么时候命中强缓存,什么时候命中协商缓存,主要依赖于http返回头信息里的Cache-Control返回字段进行控制。

什么情况下命中强缓存?以常见的max-age为例:若max-age=5356800,则意思是说浏览器在首次请求这个文件的时候,可以在本地磁盘中保存这个文件5356800秒,从首次加载时间开始以后的这些时间内,若再次请求这个文件,浏览器可以不发起http请求,而直接使用缓存中的内容即可,这样不仅节省了服务器负担,也提升网站用户体验。 什么情况下命中协商缓存?仍然以常见的max-age为例:若max-age=5356800,距离第一次请求文件已经过去了5356800秒,当用户再次需要这个资源的时候,浏览器就会拿之前这个文件返回的Etag以及Last-Modified,分别命名为If-None-MatchIf-Modified-Since作为请求参数传给服务端,服务端与现有文件进行匹配,若文件已更新,则返回200状态码,同时返回最新文件给客户端。若文件未更新,则返回304状态码,告诉客户端缓存有效,可以继续使用。

2.缓存位置

关于文件缓存位置,可通过Chrome开发面板中,Network栏目下每个文件后面有一个Size属性查看

3.Cache-Control有哪些字段

public 公共的。表示任何人都可以缓存,包括浏览器、代理服务器等。 private 私有的。表示只允许单个用户缓存,不能作为共享缓存。 no-cache 本地可以缓存,但每次都需要与服务端协商,即每次都命中协商缓存。 no-store 不适用任何缓存。 max-age=xxx 设置缓存最大周期(单位秒),超过这个相对时间被认为是过期,需要与服务端协商是否还可继续使用。与Expires不同,因为它是绝对时间,目前基本上已被废弃,因为若服务器时间与客户端时间相差较大的情况下,会产生一些异常问题。 s-maxage=xxx 设置代理服务器缓存文件过期相对时间,客户端会忽略它。 must-revalidate 一旦资源过期(比如超过max-age),在成功向原始服务器验证之前,缓存不能用该资源响应后续请求。 no-transform 不得对资源进行转换或转变。 only-if-cached 表明客户端只接受已缓存的响应,并且不要向原始服务器检查是否有更新的拷贝。

十一、HTTP1.1的缺点

1.无状态

其实这也不能说是缺点,这算是它的特点之一,至于是缺点还是优点,要分场景来看的。那么什么是无状态呢?就是指通信过程的上下文信息,每次请求都是独立、互相无关的,且默认状态不需要保留状态信息的。但是在一些场景下,比如前一次请求需要与后一次请求有一定关联,这个时候无状态处理起来就比较麻烦了。

2.臃肿的消息首部

HTTP/1.1 的首部无法压缩,再加上 cookie 的存在,经常会出现首部大小比请求数据大小还大的情况。

3.明文传输

也就是协议里的报文,即传输头信息,不使用二进制,而是使用文本的形式传输。这就给中间拦截者造成可乘之机,拦截传输内容,获取敏感信息。

4.队头阻塞

http传输是基于请求-应答的模式进行的,报文必须是一发一收,所有任务被放到一个任务队列中串行执行。当http开启长连接的时候,当前域名下会共用一个TCP连接,一旦队首因某些原因卡住,后续只能处于等待状态,这就是著名的队头阻塞问题。

那么如何解决队头阻塞问题?在不升级到HTTP2.0的前提下,有两种解决方案:

注意:域名也不是越多越好,因为每多一个域名,都要涉及到DNS查找TCP三次握手SSL/TLS握手,且TCP有一个慢启动特点,就是刚开始传输慢,慢慢的才会达到一个较快的稳定速度,如果启用了一个单独域名,而这个域名只传输了一个2KB的js文件,实际文件传输时间远远小于握手时间,就得不偿失了。具体哪个地方耗时可以在Chrome开发面板下Network中查看具体文件,其中有一个Waterfall内容,截图示例如下:

名词解释

十二、HTTP2.0的优势

1.头部压缩

HTTP1.1时代,默认情况下前后两次HTTP请求没有关联,这被称为无状态,请求以及响应头信息里有很多字段(本文之前已介绍过),不论是否需要,都会以key:value的形式在网络中传输,尤其对于GET请求,请求报文几乎全是请求头,这个时候就存在非常大的优化空间。HTTP2.0就针对这个问题采用了HPACK压缩算法对头部内容进行压缩,大大减少了网络传输。

HPACK压缩算法的特点是啥?在服务端与客户端建立一个哈希表,以索引的形式代替头信息,双方传输就以索引为准,拿到索引值后到哈希表中寻找对应头内容,以此减少网络传输。

2.多路复用

上面讲到了HTTP1.1队头阻塞的问题,虽然采用了长连接以及多域名分片方法在一定程度上规避里队头阻塞,但并没有从根本上解决问题。比如在有限的带宽情况下,如何完成优先级较高的请求,而不是一定要按照排队的顺序。

HTTP2.0是以二进制分帧的方式来解决所谓的队头阻塞问题。将原来的HeadersBody的报文解析成二进制的帧数据,传输过程中看到的是10101的格式。这些二进制帧不存在先后关系,因此也就不会排队等待,也就没有了 HTTP 的队头阻塞问题。

注意:所谓的乱序,指的是不同IDStream是乱序的,但同一个Stream ID 的帧一定是按顺序传输的。二进制帧到达后对方会将Stream ID相同的二进制帧组装成完整的请求报文和响应报文。

3.服务器推送

我们知道在目前的HTTP1.1时代,服务器是被动的,只有客户端主动发起请求,服务端才会响应对应内容,是一问一答的模式。并不会主动推送内容给客户端,除非采用websocket。而HTTP2.0就增加了服务器推送特性,可以对客户端的一个请求发送多个响应。比如客户端请求html页面的时候,服务器可以将当前页面用到的js以及css等资源一并返回给客户端,减少后续交互。

当然,客户端也可以拒绝服务器的推送。

4.解析速度快

服务器解析 HTTP1.1 的请求时,必须不断地读入字节,直到遇到分隔符 CRLF 为止。而解析 HTTP2 的请求就不用这么麻烦,因为 HTTP2.0是基于帧的协议,每个帧都有表示帧长度的字段。

5.优先级

HTTP2.0可以对比较紧急的请求设置一个较高的优先级,服务器在收到这样的请求后,可以优先处理。

十三、HTTPS知识点

HTTPS是超文本传输安全协议,加强版的HTTP,在HTTP的基础上对headersbody进行加密后再传输,大大增加了安全性。简单的讲,HTTPS = HTTP + SSL/TLS

至于为何安全,简要的说就是在之前HTTP明文传输的基础上增加了对称加密不对称加密算法。至于加密的原理及过程,需要额外一篇文章来详细讲解,感兴趣的同学可查阅相关资料,这里不再赘述。

与前端相关的另外一个HTTPS知识点就是:HTTPSHTTP握手的基础上又增加了一层SSL/TLS握手。所以安全是要有一定代价的,代价就是在真正连接前又多了个握手的过程。握手的过程这里不再赘述,感兴趣的同学可查阅相关资料。主要分以下三类:

十四、HTTP和HTTPS的区别

十五、HTTP代理

目前通常意义上的代理,一般认为是CDN节点,就是架设在客户端与原服务器之间的服务器,对客户端来说它就是服务器,对服务器来说它就是客户端。主要起到负载均衡的作用,减少原服务器的压力,分担原服务器带宽,提高用户访问资源速度,提高用户体验。

什么是CDN

默认情况下,所有资源都会向原服务器请求。这不仅会给原服务器造成较大压力,还会因距离问题让客户端等待较长时间,例如服务器在美国,中国用户首次请求要跨越大半个地球,显然比从上海服务器请求更慢。这个时候对于原服务器来说,就需要个代理,这个代理服务器就被称为CDN节点,节点按照一定规则定期向原服务器更新文件即可,附近的用户就近访问当前节点即可,既减轻了原服务器压力,也减少了请求时间,提高用户体验。

代理常见头部字段

Via

是一个能用首部,由代理服务器添加,适用于正向和反向代理,在请求和响应首部均可出现,这个消息首部可以用来追踪消息转发情况,防止循环请求,还可以识别在请求或响应传递链中消息发送者对于协议的支持能力。

Via: 1.1 vegur
Via: HTTP/1.1 GWA
Via: 1.0 fred, 1.1 p.yourAddress.net

X-Forwarded-For

是一种获取用户真实IP的字段,不管中间经过多少代理,这个字段始终记录最初的客户端的IP。 相应的,还有X-Forwarded-HostX-Forwarded-Proto,分别记录客户端(注意:不包括代理)的域名和协议名。

X-Real-IP

一般记录真实发出请求的客户端的IP,还有X-Forwarded-HostX-Forwarded-Proto分别记录真实发出请求的客户端的域名和协议名。

十六、http性能优化相关

其实能看到这里,相信你的心里已经对网络性能优化有一定的想法了,这里也就做一些简单的知识点罗列。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8