Rack-cors 未在 swagger-ui_rails 的生产环境中显示标题

Posted

技术标签:

【中文标题】Rack-cors 未在 swagger-ui_rails 的生产环境中显示标题【英文标题】:Rack-cors not showing headers in production env for swagger-ui_rails 【发布时间】:2018-03-04 14:34:37 【问题描述】:

我目前正在运行几个 Rails 3.2.x 应用程序。使用 Ruby 1.9.x 并且是 api 端点的那个有 Rack-cors gem (1.0.1) - 应用程序 Alice;另一个运行 swagger-ui_rails gem,是托管 api 文档的应用程序——应用程序 Bob。 swagger 文档是使用 swagger-docs gem 创建的,它运行格式版本 1.2。出于某种原因,由于此错误,我无法让应用 Alice 向我提供 Bob 的信息:

Failed to load https://alice.example.com/api-docs/v1/api-docs.json:
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://bob.example.com:3000' is therefore not allowed access. 

但是!当我查看网络选项卡时,响应是 200,我可以看到 json 信息。但是响应标头肯定没有所需的Access-Control-Allow-Origin 标头。

这通过 AWS Elastic Beanstalk(Bob 托管在 EBS 上)和本地(带有绑定地址)发生。

在我爱丽丝的config/environments/production.rb 中,我有以下内容:

config.middleware.insert_before 0, 'Rack::Cors' do
  allow do
    origins ->(origin, env) do
      Rails.logger.warn("CORS origin: #origin")
      origin =~ /\.example\.com(:\d+)?\z/
    end
    resource('*', :methods => [:get, :post, :options], :headers => :any)
  end
end

当我在 Alice 的 config/environments/development.rb 中有此代码时,本地主机连接并且 swagger-ui 按预期显示,控制台中没有错误。

在 Chrome 的网络选项卡中,这是我在本地拥有的(Bob 和 Alice 在 dev/localhost)

Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:http://apitest.bob.com:3000
Access-Control-Expose-Headers:
Access-Control-Max-Age:1728000
Content-Length:1499
Content-Type:application/json
Date:Fri, 22 Sep 2017 21:44:45 GMT
Last-Modified:Mon, 28 Aug 2017 17:37:22 GMT
Server:
Vary:Origin

这就是 Bob 在 dev 而 Alice 在 prod 时得到的结果:

Accept-Ranges:bytes
Connection:keep-alive
Content-Length:1500
Content-Type:application/json
Date:Fri, 22 Sep 2017 23:10:00 GMT
ETag:"abc-559ce64fb8374"
Last-Modified:Fri, 22 Sep 2017 22:04:35 GMT
Server:

如您所见,prod-Alice 不会像 dev-Alice 那样返回任何类型的标头,即使使用完全相同的 Rack-Cors 代码块也是如此。

rake middleware 在堆栈顶部显示 Rack::Cors,而curl -i https://alice.example.com/api-docs/v1/api-docs.json 从未在本地和 Bob 的服务器上为我返回正确的访问控制标头。

prod-Bob 也有一些 EBS 扩展来为 nginx 添加一些请求头和方法。在其他一些 SO 帖子中,我看到人们直接通过 Rails 添加响应标头,因此 Bob 在 application_controller.rb 中也有以下内容(在 dev 中,使用 binding.pry,我可以确认响应肯定具有指定的标头)

  after_filter :set_access_control_headers

  def set_access_control_headers
    headers['Access-Control-Allow-Origin'] = Rails.configuration.hostnames['headers']
    headers['Access-Control-Request-Methods'] = 'GET, PUT, POST, OPTIONS'
  end

我有点不知所措,如果有任何帮助或想法,我们将不胜感激。

【问题讨论】:

【参考方案1】:

我正在使用的 Swagger-docs gem 将我创建的 .json 文件放入 Rails 的 /public 目录中。因此,Rails 将其视为静态文件,而不是应该通过 Rack 中间件的东西。由于我们的 production.rb 文件有 config.serve_static_assets = false,这意味着所有这些静态文件都是我们的 Web 服务器 (Apache/Nginx) 的责任,而不是 rack-cors gem 的责任。

在向 Apache 添加一些 CORS 标头后,swagger-ui 正确加载,但标头加倍 - Apache 第 1 个,rack-cors 第 2 个。

我已经删除了 rack-cors gem,并根据与通配符子域相关的 SO 答案调整了 Alice 上的 Apache 服务器配置设置:

/etc/apache2/sites-enabled/mysite.conf

SetEnvIf Origin ^(https?://.+\.example\.com(?::\d1,5)?)$   CORS_ALLOW_ORIGIN=$1
Header append Access-Control-Allow-Origin  %CORS_ALLOW_ORIGINe   env=CORS_ALLOW_ORIGIN
Header merge  Vary "Origin"
Header set "Access-Control-Allow-Methods" "GET, POST, OPTIONS"

【讨论】:

以上是关于Rack-cors 未在 swagger-ui_rails 的生产环境中显示标题的主要内容,如果未能解决你的问题,请参考以下文章

[rack-cors gem更改接受标头从json到html

rack-cors gem 和设置 Access-Control-Allow-Origin Header

rails跨域请求配置

引发异常时如何保留响应标头?

KeyError:“未在索引中找到”-创建的虚拟变量未在索引中找到

ReferenceError:localStorage 未在 Object 中定义