如何抑制来自后端服务器的 Nginx CORS 标头

Posted

技术标签:

【中文标题】如何抑制来自后端服务器的 Nginx CORS 标头【英文标题】:How supress Nginx CORS headers coming from backend server 【发布时间】:2017-11-12 19:56:20 【问题描述】:

我正在使用 nginx 来为 Angular 2 客户端提供服务并将 rest API 路由到后端服务器。 在 Angular 开发模式下,我使用常规的“ng 服务器”,然后我应该向 Nginx 添加 CORS 支持,这种方式仅对作为外部服务器的 REST API 请求。

我的 Nginx 配置是:

server 
    listen 80;
    resolver 127.0.0.1 valid=30s;
    root /path/dist-nginx;
    index index.html index.htm;


    location /prometheus/prometheus/ 
      if ($request_method = 'OPTIONS') 
        add_header 'Access-Control-Allow-Origin' $http_origin;
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        return 204;
      
      if ($request_method = 'GET') 
        add_header 'Access-Control-Allow-Origin' $http_origin;
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
      
      #proxy_set_header X-Real-IP  $remote_addr;
      #proxy_set_header X-Forwarded-For $remote_addr;
      proxy_set_header Host $host;
      proxy_pass http://prometheus:9090/;
    

    location / 
        try_files $uri $uri/ /index.html;
        #try_files $uri $uri/ /index.html =404;
    

location /prometheus/prometheus 用于 api 位置/服务 Angular 客户端

它与第一个请求完美配合:

http://localhost:3330/prometheus/prometheus/metrics

表明至少 CORS 设置运行良好。

但是当客户端执行以下请求时:

http://localhost:3330/prometheus/prometheus/api/v1/query?query=http_request_size_bytes

我在浏览器中遇到了这个问题:

 XMLHttpRequest cannot load
 http://local.appcelerator.io:3330/prometheus/prometheus/api/v1/query?query=http_request_size_bytes.
 The 'Access-Control-Allow-Origin' header contains multiple values '*,
 http://localhost:4200', but only one is allowed.  Origin
 'http://localhost:4200' is therefore not allowed access.

查看我得到的请求的标头答案:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Authorization,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
Access-Control-Allow-Headers:Accept, Authorization, Content-Type, Origin
Access-Control-Allow-Methods:GET, OPTIONS
Access-Control-Allow-Methods:GET, OPTIONS
Access-Control-Allow-Origin:http://localhost:4200
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:Date
Connection:keep-alive
Content-Encoding:gzip
Content-Length:657
Content-Type:application/json
Date:Sun, 11 Jun 2017 05:39:34 GMT
Server:nginx/1.13.1

因此,除了我的之外,还添加了 3 个 CORS 标头字段:

Access-Control-Allow-Origin:*
Access-Control-Allow-Headers:Accept, Authorization, Content-Type, Origin
Access-Control-Allow-Methods:GET, OPTIONS

Angular客户端直接请求Nginx,中间没有人。

这两个请求在 nginx 上直接 curl 完美运行。

如果我执行第一个请求:

http://localhost:3330/prometheus/prometheus/metrics

在一个女巫失败后第二次,我没有错误,标题字段正常。

似乎问题特别是与此请求的链接:

http://localhost:3330/prometheus/prometheus/api/v1/query?query=http_request_size_bytes

似乎这里的后端服务器prometheus在响应url /api/v1上的api请求时会添加一些CORS标头

我怎样才能搭上他们?

感谢您提供任何有助于理解那里发生的事情的想法。

【问题讨论】:

你说中间什么都没有,但是proxy_pass http://prometheus:9090/;在做什么呢?您确定由它提供的代码没有添加自己的 CORS 标头吗? 【参考方案1】:

最后,我可以确认添加的 CORS 字段来自 prometheus 后端。

因此,例如,当我请求 /prometheus/prometheus/metrics 时,我没有在标头中获得额外的 CORS 字段,但是当我请求 /prometheus/prometheus/api/v1 时,在标头中获得了额外的 CORS 字段

这是 Prometheus 不一致的行为,为了解决这个问题,我必须创建两个单独的位置,一个用于 /prometheus/prometheus/metrics 处理 CORS,一个用于 /prometheus/prometheus/api/v1,它不处理 CORS

【讨论】:

以上是关于如何抑制来自后端服务器的 Nginx CORS 标头的主要内容,如果未能解决你的问题,请参考以下文章

Angularjs + Spring-boot + nginx的CORS问题

Nginx 设置cors跨域

Nginx 设置cors跨域

禁用来自客户端脚本的OPTIONS请求

运行单元测试时如何抑制来自 node.js 应用程序的应用程序日志消息?

Cors 阻止 Nginx 上状态为 403 的请求