Nginx API网关跨域问题解决
问题描述:
使用Nginx作为API网关并开启缓存功能以后,不明原因出现跨域访问错误,错误信息如下:
“http://epg.mydomain.com” that is not equal to the supplied origin. Origin 'http://local.epg.mydomain.com' is therefore not allowed access.
并且这个错误是不定时出现。
问题分析:
这个问题是在开启nginx网关缓存策略后出现,未开启网关缓存之前是没有问题的,并且API已经开放了跨域策略,因此,初步定位问题原因出在nginx网关缓存配置上。
nginx网关缓存配置如下:
location /int/page/
{
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header Set-Cookie;
proxy_hide_header "cache-control";
proxy_hide_header Expires;
proxy_ignore_headers Set-Cookie;
proxy_ignore_headers Cache-Control;
proxy_ignore_headers Expires;
proxy_cache api_cache;
proxy_cache_valid 200 302 2m;
proxy_cache_valid 404 1m;
proxy_cache_valid any 30m;
proxy_cache_key $host$uri$is_args$args;
add_header Nginx-Cache "$upstream_cache_status";
}
通过上述配置发现nginx的缓存proxy_cache_key配置为host+uri+参数,而我通过测试环境和正式环境以不同的域名访问时,nginx缓存不区分Origin保存缓存,但访问的时候,由于域名同源策略导致nginx保存的缓存只能返回给相同Origin访问的请求。缓存过期后,哪个域名先访问,就先缓存对应的Origin,与缓存Origin不同的域名访问,缓存会提示与之前提供的域名不一致,因此导致了不定时出现的诡异现象。
问题解决:
根据上述的问题分析,查找Origin在nginx内置变量名称为:$http_origin,将proxy_cache_key配置修改为:$http_origin$host$uri$is_args$args,如下所示:
location /int/page/
{
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header Set-Cookie;
proxy_hide_header "cache-control";
proxy_hide_header Expires;
proxy_ignore_headers Set-Cookie;
proxy_ignore_headers Cache-Control;
proxy_ignore_headers Expires;
proxy_cache api_cache;
proxy_cache_valid 200 302 2m;
proxy_cache_valid 404 1m;
proxy_cache_valid any 30m;
proxy_cache_key $http_origin$host$uri$is_args$args;
add_header Nginx-Cache "$upstream_cache_status";
}
保存,重启nginx,问题解决。
总结:
上述nginx跨域问题采坑是在nginx+缓存+跨域(多环境访问)多种组合因素叠加情况下出现的,如果缺少其一可能不会采坑。同时在实际操作中,也可能遇到不同的叠加因素,如不同的schema,我们应根据具体使用场景灵活的对proxy_cache_key进行配置。
通过这个采坑的过程,加深了对nginx缓存的原理的理解。