8

利用 Nginx 反向代理解决 CORS 问题

 3 years ago
source link: http://misaka.im/index.php/archives/19/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

利用 Nginx 反向代理解决 CORS 问题

2018.02.08默认分类 0 评

跨域请求(CORS)的响应在特定的情况下被浏览器拦截,这是因为请求了一个与当前域或端口不同的资源。所以通过 JavaScript 操控的 XMLHttpRequestFetch 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/;
    }
}

http://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;
        }
    }
}

现在所有由 http://test.misaka.im/jiushou/ 发回的响应都能顺利被浏览器接收了。

CORS on Nginx - https://enable-cors.org
HTTP访问控制(CORS) - MDN
nginx解决跨域


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK