起于安全
跨域请求(CORS)的响应在特定的情况下被浏览器拦截,这是因为请求了一个与当前域或端口不同的资源。所以通过 JavaScript
操控的 XMLHttpRequest
或 Fetch
API 都会受到跨域限制。
这样一来,我们在编写 Web 程序时只能从加载同一域请求 HTTP 资源,除非 HTTP 响应头中指定了:
Access-Control-Allow-Origin: *;
它允许 HTTP 服务器声明哪些站点有权限访问该资源。
在浏览器发出跨域请求前,有可能先用 OPTIONS
方法发起一个预检请求来询问服务端是否支持跨域。
反向代理
源服务器不能修改 HTTP 响应头 ?
在接入后端 API 时,无法即时部署到线上环境测试,在其他地方部署都会触发 CORS 限制。
将前端代码转移到测试服务器上,使用 Nginx proxy_pass
来代理需要测试的 API :
server {
listen 80;
server_name test.misaka.im;
root /var/www/html/test/public;
index index.html index.htm index.php;
location ^~/jiushou/ {
rewrite ^/jiushou/app/(.*)$ /$1 break;
proxy_pass https://api.jiushouguoji.hk/app/;
}
}
访问 test.misaka.im/jiushou/
的请求就会被转发到 https://api.jiushouguoji.hk/app/
上。
跨域代理
但这样并没彻底解决CORS 限制的问题,每次都要将代码部署到 test.misaka.im
上才能进行测试。
在反向代理时加入 HTTP 头,这才是中规中矩的做法:
server {
listen 80;
server_name test.misaka.im;
root /var/www/html/test/public;
index index.html index.htm index.php;
location ^~/jiushou/ {
rewrite ^/jiushou/app/(.*)$ /$1 break;
proxy_pass https://api.jiushouguoji.hk/app/;
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range;
add_header Access-Control-Max-Age 1728000;
add_header Content-Type 'text/plain; charset=utf-8';
add_header Content-Length 0;
return 204;
}
if ($request_method = 'POST') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range;
add_header Access-Control-Expose-Headers Content-Length,Content-Range;
}
if ($request_method = 'GET') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range;
add_header Access-Control-Expose-Headers Content-Length,Content-Range;
}
}
}
现在所有由 test.misaka.im/jiushou/
发回的响应都能顺利被浏览器接收了。