周分享

HTTP全知道(下)

2020-04-03  本文已影响0人  橙汁坤

HTTP1.1 是如何解决队头阻塞问题

书接上文,HTTP 传输是基于请求-应答的模式进行的,报文必须是一发一收,任务被放在一个任务队列中串行执行,而所谓的HTTP队头阻塞问题。是指一旦队首的请求处理太慢,就会阻塞后面请求的处理。

即使是提高了并发连接,也满足不了对性能的需求,而只有能够并发的长连接数更多了,才能更好地解决了队头阻塞的问题。

HTTP 代理

HTTP 是基于请求-响应模型的协议,一般由客户端发请求,服务器来进行响应。
但是也有代理服务器的情况。引入代理之后,代理的服务器相当于一个中间人的角色,对于客户端而言,表现为服务器进行响应;而对于源服务器,表现为客户端发起请求,具有双重身份。

  1. Via
    代理服务器需要标明自己的身份,假如有两台代理服务器,在客户端发送请求后会经历这样一个过程:
    客户端 => 代理1 => 代理2 => 源服务器
    源服务器收到请求后,会在请求头拿到这个字段:
    Via: proxy_server1, proxy_server2
    而源服务器响应时,最终在客户端会拿到这样的响应头:
    Via: proxy_server2, proxy_server1
    Via中代理的顺序即为在 HTTP 传输中 报文传达的顺序

  2. X-Forwarded-For
    是为谁转发, 它记录的是请求方的IP地址(和Via区分开只记录请求方这一个IP)。

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

  4. X-Forwarded-For产生的问题
    前面可以看到,只记录了请求方的 IP,这意味着每经过一个不同的代理,这个字段的名字都要变,由此产生了问题:

为了解决这个问题产生了代理协议,一般使用明文版本,只需要在 HTTP 请求行上面加如下文本即可:

// PROXY + TCP4/TCP6 + 请求方地址 + 接收方地址 + 请求端口 + 接收端口
PROXY TCP4 0.0.0.1 0.0.0.2 1111 2222
GET / HTTP/1.1

什么是跨域

scheme(协议)、host(主机)和port(端口)都相同则为同源
说到http 就得说到跨域了,在前后端分离的开发模式中,经常会遇到跨域问题,即 Ajax 请求发出去了,服务器也成功响应了,前端就是拿不到这个响应。

非同源站点有这样一些限制

跨域请求是被浏览器拦截,响应其实是成功到达客户端了。那这个拦截是如何发生呢?

  1. 浏览器是多进程的,以 Chrome 为例,进程组成如下:
    当Ajax 请求准备发送的时候,其实还只是在渲染进程的处理。为了防止黑客通过脚本触碰到系统资源,浏览器将每一个渲染进程装进了沙箱,采取了站点隔离的手段。
  2. 在沙箱当中的渲染进程只能通过网络进程来发送网络请。在数据传递给了浏览器主进程,主进程接收到后,才真正地发出相应的网络请求。
    在服务端处理完数据后,将响应返回,主进程检查到跨域,且没有cors响应头,将响应体全部丢掉,并不会发送给渲染进程。这就达到了拦截数据的目的。
解决方案
CORS

CORS 就是是跨域资源共享。它需要浏览器和服务器的共同支持,具体来说,非 IE 和 IE10 以上支持CORS,服务器需要附加特定的响应头,后面具体拆解。
简单请求和非简单请求。

  1. Access-Control-Allow-Origin字段是服务器用来决定浏览器是否拦截这个响应,这是必需的字段。

  2. Access-Control-Allow-Credentials表示是否允许发送 Cookie,对于跨域请求,浏览器对这个字段默认值设为 false,而如果需要拿到浏览器的 Cookie,需要添加这个响应头并设为true, 并且在前端也需要设置withCredentials属性:
    let xhr = new XMLHttpRequest();xhr.withCredentials = true;

  3. Access-Control-Expose-Headers。这个字段是给 XMLHttpRequest 对象赋值,让它不仅可以拿到基本的 响应头字段,还能拿到这个字段声明的响应头字段。比如这样设置:Access-Control-Expose-Headers: test

    前端可以通过 XMLHttpRequest.getResponseHeader('test') 拿到 test 这个字段的值。

JSONP

虽然XMLHttpRequest对象遵循同源政策,但script标签可以通过 src 填上目标地址从而发出 GET 请求,实现跨域请求并拿到响应。这也就是 JSONP 的原理
和CORS相比,JSONP 最大的优势在于兼容性好,IE 低版本不能使用 CORS 但可以使用 JSONP,缺点也很明显,请求方法单一,只支持 GET 请求。

Nginx

Nginx通过反向代理服务器来轻松解决跨域问题。


image.png image.png
server {
  listen  80;
  server_name  client.com;
  location /api {
    proxy_pass server.com;
  }
}

Nginx 相当于起了一个跳板,这个跳板的名字也是client.com,让客户端首先访问 client.com/api,这当然没有跨域,然后 Nginx 服务器作为反向代理,将请求转发给server.com,当响应返回时又将响应给到客户端,这就完成整个跨域请求的过程。就像是在饭馆点餐时,服务员来回穿梭顾客和厨房是一样的道理,服务员记录了我们点的菜品,然后也将厨房的食物送到我们的餐桌上。

上一篇 下一篇

猜你喜欢

热点阅读