预检请求(preflight request)

我们先看看什么是 预检请求

A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood.

It is an OPTIONS request, using three HTTP request headers: Access-Control-Request-MethodAccess-Control-Request-Headers, and the Origin header.

A preflight request is automatically issued by a browser, when needed. In normal cases, front-end developers don't need to craft such requests themselves.

For example, a client might be asking a server if it would allow a DELETE request, before sending a DELETE request, by using a preflight request:

OPTIONS /resource/foo 
Access-Control-Request-Method: DELETE 
Access-Control-Request-Headers: origin, x-requested-with
Origin: https://foo.bar.org

If the server allows it, then it will respond to the preflight request with a Access-Control-Allow-Methods response header, which lists DELETE:

HTTP/1.1 200 OK
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Origin: https://foo.bar.org
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 86400

简单的来说就是,就是判断CORS的协议是否被server端理解。

1)如果被理解,就是先发送一个OPTIONS请求。请求头需包含以下三个字段

    Access-Control-Request-MethodAccess-Control-Request-Headers, and the Origin header.

 2)浏览器自动发出,不需要自己发出。

看完了,是不是一脸萌币,什么叫被服务器理解。那么服务器又能理解哪些东西:

预先定义好的简单请求头。包含以下东西。

simple header (or CORS-safelisted request header) is one of the following HTTP headers:

Or one of these client hint headers:

When containing only simple headers, a requests is deemed simple and doesn't need to send a preflight request in the context of CORS.

最后一句话,如果是上面的请求头,就被视为一个简单的请求,并不需要发预检请求。也就是说OPTIONS请求不会发出。

现在情况明朗了。如果你使用自定义的请求头,server自然无法理解。就需要发出OPTIONS请求。

下面给出一个例子:

客户端:

       let promise = new Promise(( resolve, reject) => {
         let xhr = new XMLHttpRequest(),
             url = "http://localhost:3000/data";
         xhr. onreadystatechange = () => {
           if( xhr. readyState === 4) {
             if( xhr. status === 200) {
               resolve( JSON. parse( xhr. responseText));
            } else {
               reject();
            }
          }
        }
         xhr. open( "GET", url);
         xhr. setRequestHeader( "x-token", "I am x-token"); // 包含自定义请求头,服务器需要设置 Access-Control-Allow-Headers
         xhr. send( null); // 会发出预检请求。也就是OPTIONS请求
      });
       promise. then(( data) => {
         console. log( data);
      });

服务端

var express = require( "express"),
   app = express();

app. use(( req, res, next) => {
   res. set( "Access-Control-Allow-Origin", "http://localhost:8080");
   res. set( "Access-Control-Allow-Headers", "x-token"); // 需要对客户端进行同步设置
   next();
});

app. all( "/message", ( req, res) => {
   res. json({
     fruitList: [ "apple", "banana", "coconut", "watermelon"]
  });
});

app. all( "/data", ( req, res) => {
   console. log( req. get( "x-token"));
   res. json({
     name: "pizza",
     size: "medium"
  });
});

app. listen( 3000, () => {
   console. log( "server is running");
});


客户端发送截图:

第一发送: 会发送OPTIONS请求。包含以下三个字段。



第二次发出,会发出一个GET请求。


注意: 这里和请求的类型是无关的,无论是GET请求或者是POST请求。

参考文章:

Simple Headers

OPTIONS

preflight request


写完了,才发现推送了一个文章。晕,写的很好,贴出

简单跨域请求和带预检的跨域请求


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值