世界上最伟大的投资就是投资自己的教育
CORS 进阶之 Preflight 请求 (二)
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 请求。
从前面的分析可以知道,GET
,POST
是不会发出 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
都会显式地写上GET
,POST
方法,即使它是默认就支持的。
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 进阶之设置请求头信息 (三)
完结。
本站文章均为原创内容,如需转载请注明出处,谢谢。
© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn
粤公网安备 44152102000088号 | 粤ICP备19038915号
Top