Fetch / ajax 不能获取response中的所有headers的解决方法(适用nginx)

来源: https://www.aliyun.com/jiaocheng/123788.html

起因 

笔者在用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会在浏览器里面报类似如下的错误.

 

Fetch / ajax 不能获取response中的所有headers的解决方法(适用nginx)

 

什么是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 详解

你可能感兴趣的:(fetch,headers)