nginx-cors

针对跨域的问题,网上一搜已经很多了。很多都是如下的配置

1
2
3
4
5
6
7
8
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, HEAD, DELETE,TRACE,PUT,CONNECT';
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since,restrict-access,share-secret,thumbnail';
return 200;
}

但是这次按这样做了,居然没有效果。本来以为是location的问题。后来仔细看下了官方文档,默认只能是2xx和3xx的这些可以。

http://nginx.org/en/docs/http/ngx_http_headers_module.html

Adds the specified field to a response header provided that the response code equals 200, 201 (1.3.10), 204, 206, 301, 302, 303, 304, 307 (1.1.16, 1.0.13), or 308 (1.13.0). Parameter value can contain variables.
There could be several add_header directives. These directives are inherited from the previous configuration level if and only if there are no add_header directives defined on the current level.
If the always parameter is specified (1.7.5), the header field will be added regardless of the response code.

同时又比较怀疑是chrome版本的问题,怕新版的chrome有一些新的限制,但是放狗搜了一下也没有人说起。自己测试了一下发现也是一样的问题,只是发现直接访问是返回500的错误。

那看来问题就是可以定位出来了。nginx官方是1.7.5以后可以加上always参数来规避这个。但是我们的版本是比较老的,那就用lua来解决这个吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Cross-origin resource sharing


header_filter_by_lua "
if ngx.req.get_method() == 'OPTIONS' then
ngx.header.access_control_allow_origin = ngx.var.http_origin
ngx.header.access_control_allow_credentials = 'true'
ngx.header.access_control_max_age = 1728000
ngx.header.access_control_allow_methods = ngx.var.http_access_control_request_method
ngx.header.access_control_allow_headers = ngx.var.http_access_control_request_headers
ngx.header.cors = 'true'
ngx.exit(200)
else if ngx.var.http_origin then
ngx.header.access_control_allow_origin = ngx.var.http_origin
ngx.header.access_control_allow_credentials = 'true'
ngx.header.access_control_allow_methods = ngx.var.http_access_control_request_method
ngx.header.access_control_allow_headers = ngx.var.http_access_control_request_headers
ngx.header.cors = 'true'
end
end
";

虽然现在看着很简单,但是这个问题的原因发现还是搞了一下午。