优化CORS预检问题

近段时间PC端发布测试版本,使用webpack打包和gitlab runner自动化部署,然后使用nginx代理部署访问。测试过程中发现一个问题,每调用一个后台接口都会产生两次请求。我们以一次请求200ms计算,忽略前端渲染时间,本来200ms可以操作的界面需要400ms。并且本来可以一台服务器可以完成的工作非要两台服务器才能完成。这就比较严重了。本来文章记录一下这个问题的解决方案。

事件原因

先看看下图

预检请求产生的原因可以从跨源资源共享(CORS)中查询到。关于跨域资源共享的定义如下

跨源资源共享 (CORS)(或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它 origin(域,协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的”预检”请求。在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头。

从上面可以看出,预检请求是从浏览器CORS规则产生的。预检的作用是检查服务器是够允许发送真实请求。所有的请求都会产生预检请求,但是也有例外,比如简单请求,对于简单请求定义可以查看上面链接中的文章。

从上面的描述可以看出,产生预检请求的原因是我们定义了一些自定义的字段,比如

优化方式

因为预检请求的请求方式是OPTIONS,所以我们可以在Nginx代理层对OPTIONS做一些操作,比如对请求添加过期时间。为请求添加缓存,让Web端在一定时间内不访问我们的服务器资源即可

Nginx配置如下,OPTIONS接口过期时间为1d,也可以设置大一些。看公司需求即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
server {
listen 443 ssl;
server_name 域名;
charset utf-8;
ssl_certificate /etc/nginx/cert/test.app.iomte.com_bundle.pem;
ssl_certificate_key /etc/nginx/cert/test.app.iomte.com.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
#表示使用的TLS协议的类型。
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;

location / {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#启用支持websocket连接
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
if ($request_method = 'OPTIONS') {
expires 1d;
add_header 'Access-Control-Allow-Origin' '前端域名列表' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
add_header 'Access-Control-Expose-Headers' 'Authorization';
add_header 'Access-Control-Allow-Credentials' true;
add_header 'Access-Control-Max-Age' 86400;
return 204;
}

}
}

执行Nginx运行时重载,打开浏览器查看请求,发现请求正常了。

作者

Labradors

发布于

2022-06-18

更新于

2022-06-18

许可协议

评论