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

起因

笔者在用fetch进行react开发的时候用到了chrome跨域插件Allow-Control-Allow-Origin: *, 因为后端和前端的开发是同时进行的, 并且不在同一台机子上. 为了能够在前端方便地调试后端api, 我使用了这个插件. 姑且是能够进行cors请求了.

但是我发现, 无论如何都不能在fetchresponseheaders里面, 获得我想要的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会在浏览器里面报类似如下的错误.

Stack Overflow上的提问配图

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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值