世界上最伟大的投资就是投资自己的教育

首页跨域资源共享CORS
随风 · 练气

CORS 进阶之 Preflight 请求 (二)

随风发布于3958 次阅读

1. Access-Control-Allow-Origin

上一篇从跨域到 CORS(一)文章有说过 CORS 的基本使用,也实现了跨域的请求。本篇来讲讲 CORS 更高阶的用法。

首先来讲讲Access-Control-Allow-Origin的用法。

Access-Control-Allow-Origin:*表示的是允许任何的来源都可以访问,然而这并不符合大多数人的需求。假如我们只需要固定的一台或几台机器,或者是某个域名下的才可以访问,这又该如何呢?

还是按照先前的例子,从 localhost:3000 的服务跨域到 nginx 服务 localhost:8080。现在来演示一下,只允许 localhost:3000 的访问,在 nginx 是这样配置的。

location / {
  add_header 'Access-Control-Allow-Origin' 'http://localhost:3000';
}

可见,是成功的。

也可以试一下把http://localhost:3000前面的http://去掉,会发现是不成功的,毕竟不同的协议也是不同的域的。

下面有个配置可以参考,在 nginx 中设置域名的访问。

set $cors '';
if ($http_origin ~* 'https?://(localhost|www\.yourdomain\.com|www\.yourotherdomain\.com)') {
        set $cors 'true';
}

if ($cors = 'true') {
        add_header 'Access-Control-Allow-Origin' "$http_origin";
}

在上面的配置中,$http_origin表示的是获得来源域的域名,也就是请求头Origin的内容。

2. Preflight 请求

之前在浏览器模拟跨域请求的 js 是这样的:

var xhttp = new XMLHttpRequest();
xhttp.open("GET", "http://localhost:8080", true);
xhttp.send();

使用的方法是 GET,CORS 跟 jsonp 等方法不一样的,它可以支持像 POST,DELETE 方法。

先用 POST 方法来试一下,nginx 那边需要改一下:

server {
    error_page  405     =200 $uri;
}

再把 js 中的GET改成POST方法。

可见,是成功的。如果改成 DELETE 方法呢?

报错了,大体上说 DELETE 方法是不被允许的。来看下产生的请求。

使用 DELETE 方法时,并不会真正的产生 DELETE 请求,而是先生成了一个叫 OPTIONS 的请求。

这个 OPTIONS 请求是怎么回事呢?

这个 OPTIONS 请求也叫 Preflight 请求,它是在发起 DELETE 真实请求时,先询问服务器是否支持 DELETE 方法,再用响应头信息的方式返回给浏览器,浏览器根据响应信息查看服务器是否支持 DELETE 方法,如果支持的话,就再发起真实的 DELETE 方法,不支持就报错了。所以出现了上面的报错信息。

我们先让服务器支持 DELETE 方法,再来尝试新的请求。

location / {
  add_header 'Access-Control-Allow-Origin' 'http://localhost:3000';
  add_header 'Access-Control-Allow-Methods' 'DELETE';
}

果然,成功了。且发出了真正的 DELETE 请求。

从前面的分析可以知道,GETPOST是不会发出 Preflight 请求的,而 DELETE 方法会,那还有什么情况下会呢?下面列举出来:

  • 使用的方法不是 GET, POST, 或 HEAD 的任何一种
  • Content-Type 请求来不是下面任何一种
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • 不寻常的请求头,例如不是下面的几种:
    • Accept
    • Accept-Language
    • Content-Language
  • XMLHttpRequest 的 upload 事件

值得注意的是,为了避免困惑,在Access-Control-Allow-Methods都会显式地写上GETPOST方法,即使它是默认就支持的。

add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE'

除此之外,频繁的 Preflight 请求可能会造成性能的消耗。我们可以用下面的方法处理一下:

add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;

Access-Control-Max-Age可以设置请求的过期时间,单位是秒 (second)。另外,返回 204 的状态码,是返回一个空内容的返回,毕竟,Preflight 请求只需要响应的头部信息 (Access-Control-Allow-Methods),并不需要响应内容的。

下一篇: CORS 进阶之设置请求头信息 (三)

完结。

本站文章均为原创内容,如需转载请注明出处,谢谢。

0 条回复
暂无回复~~
相关小书
跨域资源共享CORS

跨域资源共享CORS

什么是浏览器跨域,如何解决跨域问题,什么是 CORS?从入门到精通。

发表于

喜欢
统计信息
    学员: 29811
    视频数量: 1987
    文章数量: 526

© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn

粤公网安备 44152102000088号粤公网安备 44152102000088号 | 粤ICP备19038915号

Top