今天debug一跨域问题,本来觉得就一很简单的问题,结果被无情打脸,费了老大劲了,有必要复盘下。

同样的接口Get好使而POST就是不行,前端那里一直报跨域请求失败。

1
No 'Access-Control-Allow-Origin' header is present on the requested resource

但我明明Nginx已经加上相关配置上了,没道理啊。

1
2
3
4
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Request-Method' 'GET,POST,OPTIONS,DELETE,PUT';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';

再三确认配置是没问题后只能求助GG,结果还真有发现,原来add_header不是所有返回都会追加,只限特定状态码的返回才有效,如果想所有返回都生效需要加上always选项参数。具体来看下官方的解释:

1
2
3
Syntax:	add_header name value [always];
Default:	—
Context:	http, server, location, if in location

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).

于是修改配置加上always

1
2
3
4
add_header 'Access-Control-Allow-Origin' $http_origin always;
add_header 'Access-Control-Request-Method' 'GET,POST,OPTIONS,DELETE,PUT' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;

重启Nginx,刷新页面,wow,跨域报错消失了,但是接口Post报500了错误。

此时已经完全明白过来了,正是由于这个接口GET请求返回正常,所以返回的header中会添加上Access-Control-Allow-Origin,而POST时接口返回500add_header不起作用,Access-Control-Allow-Origin添加不上所以才有了一直不生效的错觉,好坑~~~。不过还是怪自己没有完全掌握参数的用法,还是要多读文档。

参考

https://stackoverflow.com/questions/35946006/nginx-cors-doesnt-work-for-post

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