笔者在用fetch进行react开发的时候用到了chrome跨域插件Allow-Control-Allow-Origin: *
, 因为后端和前端的开发是同时进行的, 并且不在同一台机子上. 为了能够在前端方便地调试后端api, 我使用了这个插件. 姑且是能够进行cors请求了.
但是我发现, 无论如何都不能在fetch
的response
的headers
里面, 获得我想要的header
. 但是打开chrome开发者工具
,却能在network里面清清楚楚地看到headers
的确存在.
具体症状表现为: 无论怎么
get
都是null
AngularJS $http object not showing all headers from response
这个问题的解答里面说, 这是后端原因.因为(辣鸡)W3C规定,cors的时候服务器和做各种各样的确认.
但是只要在服务器上设置一下Access-Control-Expose-Headers:*
即可.
server {
listen 80;
# listen [::]:80 default_server;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Access-Control-Allow-Methods' '*';
add_header 'Access-Control-Expose-Headers' '*';
#以下省略
}
但是并没有这么简单.简单地add_headers
会在浏览器里面报类似如下的错误.
什么是preflight
? 它叫预请求
,可能因为http
请求就像是飞机一样飞来飞去而取了这样的名字.
什么情况下会进行preflight
? 阮一峰的文章(附在文后参考资料)有这样的描述:
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求。(1) 请求方法是以下三种方法之一:
- HEAD
- GET
- POST
(2)HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同时满足上面两个条件,就属于非简单请求。 浏览器对这两种请求的处理,是不一样的。
并且:
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。
这说明: 我们的请求在preflight
的时候就失败了. 即: 我们的服务器headers
设置没有对preflight
生效.
在nginx的对应域名的配置文件(配置文件可能在/etc/nginx
下)中,加入设定:
server {
#以上省略
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Headers' 'X-Pagination-Current-Page,Content-Type';
add_header 'Access-Control-Allow-Methods' 'PUT,GET,POST,HEAD,DELETE';
add_header 'Access-Control-Expose-Headers' 'X-Pagination-Current-Page,Content-Type';
#以下省略
}
其中 X-Pagination-Current-Page
和Content-Type
都是笔者想要获取的headers.
只有这样添加才不会在浏览器中报错,也能正常地获取headers
.
在修改完毕nginx的配置文件之后, 需要重新载入配置.
指令如下:
sudo nginx -s reload
.
附带一提: 笔者这种设定对这个域名下所有的请求生效. 请依据实际需求自行调整.
其一
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Access-Control-Allow-Expose-Headers' '*';
并不起效的时候,请手动指定你需要的headers
. 有些headers
可能不能使用通配符.
其二
add_header 'Access-Control-Allow-Expose-Headers' 'X-Pagination-Current-Page,Content-Type';
手滑写了个新标准. headers
名一定要对.
AngularJS $http object not showing all headers from response
阮一峰: 跨域资源共享 CORS 详解