鲜荣彬
Herry

 预检请求表现形式:

  本机调试时,常常会出现同一个url请求两次的现象,如下图所示:

 

  此时 web服务器IP地址是: 127.0.0.1:4200,请求的地址为 128.31.52.31:20000,形成了跨域。

  便有了 preflight request(预检请求)。

 为什么会有预检请求?

  跨域资源共享标准新增了一组HTTP首部字段,允许服务器声明 A源站 通过浏览器有权限访问 B资源。

  规范要求,对那些可能对服务器资源产生副作用的HTTP请求方式,浏览器必须使用OPTTIONS 发起一个预检请求,

  从而获知服务器端是否允许该跨域请求。 服务器确认允许后,才发起实际的HTTP请求。

  说白了,就是要先发起一个验证,看是否符合要求。与HTTP三次握手,有一点点类似。

   触发预检请求条件

  并非所有的跨域请求都会触发preflight request。

   满足如下所有条件,即使跨域,也不会触发预检请求,一般称为简单请求

/*
  1、使用 GET、HEAD、POST 方法
  2、Content-Type 只能是 text/plain、 multipart/form-data、 application/x-www-form-urlencoded
  3、不添加自定义头部信息
*/

  请查看如下demo.

<!DOCTYPE html>
<html>
    <head></head>
    <body>
        <script type="text/javascript">
            fetch('http://localhost:8887',{
                method:'POST'
            })
        </script>
    </body>
</html>
const http=require('http');
http.createServer((request,response)=>{
    response.writeHead(200,{
        'Access-Control-Allow-Origin':'*'
    });

    response.end('123');
}).listen(8887);

  分别启动成不同的端口路径,则模拟成跨域请求。此时是不会有 OPTIONS 请求。

      那么,怎么才能触发 预检请求呢?

    其实,与简单请求的条件相反。

     当请求满足下述任一条件时,即应首先发送预检请求:

       1、使用如下 任一 Http请求方式

      PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH

       2、设置了对 CORS安全的首部字段集合 之外的首部字段,集合如下:

      Accept、Accept-Language、Content-Language、Content-Type、DPR、Viewport-Width、Width、Downlink、Save-Data

     3、Content-Type的值不属于下列之一:

      text/plain、Application/x-www-form-urlencorded、multipart/form-data

 

      如下Demo可以模拟请求出现 OPTIONS请求。

     HTML:

<!DOCTYPE html>
<html>
    <head></head>
    <body>
        <script type="text/javascript">
            fetch('http://localhost:8887',{
                method:'POST',
                headers: {
                    'X-Test-CORS':'shelf-cors'
                }
            })
        </script>
    </body>
</html>

  JS

const http=require('http');
http.createServer((request,response)=>{
    response.writeHead(200,{
        'Access-Control-Allow-Origin':'*',
        'Access-Control-Allow-Headers':'X-Test-CORS'
    // Access-Control-Allow-Methods':'POST,PUT,DELETE',
    // 'Access-Control-Max-Age':'1000'//在1000秒之内,不需要发送预请
    });

    response.end('123');
}).listen(8887);

 在请求头部添加自定义头部,便形成preflight request.

 预请求 Request Header 中的 Access-Control-Request-Method 指定了真正的请求方式。

  

  

posted on 2019-03-05 16:53  Herry彬  阅读(1848)  评论(0编辑  收藏  举报