Rack-cors not showing headers in production env for swagger-ui_rails

1.2k Views Asked by At

I'm currently running a couple of Rails 3.2.x apps. The one using Ruby 1.9.x and is the api endpoint has Rack-cors gem (1.0.1) on it - app Alice; the other runs swagger-ui_rails gem and is the app hosting the api documentation -- app Bob. The swagger docs was created wth swagger-docs gem, which runs format version 1.2. For some reason or another, I cannot get app Alice to give me information for Bob because of this error:

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. 

However! When I look on the network tab, the response is a 200 and I can see the json information. But the response headers definitely do NOT have the required Access-Control-Allow-Origin header.

This happens both thru AWS Elastic Beanstalk (Bob is hosted on EBS) and locally (w/ a bound address).

In my config/environments/production.rb of Alice, I have the following:

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

When I have this code in config/environments/development.rb in Alice, localhost connects and swagger-ui shows up as expected with no errors in console.

In the network tab of Chrome, this is what I have locally (Bob and Alice in 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

This is what I get for when Bob is in dev and Alice is in 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:

As you can see, prod-Alice does not return any sort of headers the way dev-Alice does, even with the exact same Rack-Cors code block.

rake middleware displays Rack::Cors at the top of the stack, and curl -i https://alice.example.com/api-docs/v1/api-docs.json has never returned the proper access-control headers for me, both locally and on Bob's server.

prod-Bob also has some EBS extensions to add some request headers and methods to nginx. In some other SO post, I saw folks adding in response headers directly via Rails, and so Bob also has the following in application_controller.rb (and in dev, with binding.pry, I can confirm that the response definitely has the specified headers)

  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

I'm a bit at a loss and any help or thoughts would be appreciated.

1

There are 1 best solutions below

0
On BEST ANSWER

The Swagger-docs gem that I'm using puts the .json files that I've created into Rails' /public directory. As such, Rails sees this as static files and not something that should go through Rack middleware. Since our production.rb file had config.serve_static_assets = false, that meant that all these static files were the responsibility of our web server (Apache/Nginx) and not the responsibility of rack-cors gem.

After adding in some CORS headers to Apache, swagger-ui loaded appropriately, but was doubling up the headers - 1st for Apache, 2nd for rack-cors.

I've since removed rack-cors gem and have adjusted the Apache server conf setting on Alice, based on an SO answer related to wildcard subdomains:

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

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