jeremywoertink
jeremywoertink

Reputation: 2341

Using rack-cors with Rackspace CDN issues

I have a rails 4.2 app using rack-cors. None of my font-awesome icons show up even though all my other assets are fine. I'm using the rackspace cdn. My CDN url looks something like

http://ddf908e003b5678bc25-9d6bfcdc12345678ba868a15bca98.r12.cf5.rackcdn.com/assets/main-4f3595479ce96112e1b8ab4e5357fc26.css

My rack-cors config is in my config/application.rb

config.middleware.insert_before 0, "Rack::Cors" do
  allow do
    origins 'localhost:3000', /^http:\/\/\w+.+rackcdn.com/
    resource '/assets/*', headers: :any, methods: :get
  end
end

The icons show up locally just fine. It's only in production that they don't show. Any ideas on what I might be missing?

EDIT

I'm using the font-awesome-sass gem. When I view the page, I don't get any javascript errors or anything, just the CORS warning, and no icons.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://ddf908e003b5678bc25-9d6bfcdc12345678ba868a15bca98.r12.cf5.rackcdn.com/assets/main-4f3595479ce96112e1b8ab4e5357fc26.css/assets/font-awesome/fontawesome-webfont-e9c0e802c2b0faf4d660e2bff17b5cf1.woff. This can be fixed by moving the resource to the same domain or enabling CORS.

EDIT 2

I'm using asset_sync to help set the custom headers that Ash Wilson suggested doing.

AssetSync.configure do |config|
  config.fog_provider = 'Rackspace'
  config.rackspace_username = ENV['RACKSPACE_USERNAME']
  config.rackspace_api_key = ENV['RACKSPACE_API_KEY']
  config.fog_directory = ENV['FOG_DIRECTORY']
  config.fog_region = ENV['FOG_REGION']
  config.gzip_compression = true
  config.manifest = true
  config.custom_headers = {
    "\.(ttf|otf|eot|woff|svg)$" => {
      "Access-Control-Allow-Origin" => "*",
      "Access-Control-Request-Method" => "*",
      "Access-Control-Allow-Methods" => "*"
    }
  }
end

I'm not doing any cacheing on my end just yet, but I was sure to clear any browser cache. I also found the 2 files complaining .woff and .ttf in the Control panel as Ash had mentioned below, and I added the headers manually into that. However, I'm still seeing the same issue. Maybe there's an additional step, or possibly AssetSync is just dead and doesn't work?

EDIT 3

Here are the headers from a curl. Looks like the CORS headers are in there. Waited all day for propagation, but still no go.

curl -i -s -XHEAD http://ddf908e003b5678bc25-9d6bfcdc12345678ba868a15bca98.r12.cf5.rackcdn.com/assets/font-awesome/fontawesome-webfont-e0e0f28a0197446b28f818aa81b80530.ttf

HTTP/1.1 200 OK
Content-Length: 112160
Last-Modified: Thu, 07 May 2015 16:49:12 GMT
Accept-Ranges: bytes
Access-Control-Request-Method: *
ETag: c4668ed2440df82d3fd2f8be9d31d07d
X-Timestamp: 1431017351.82062
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, HEAD, OPTIONS
Content-Type: application/font-sfnt
X-Trans-Id: tx53b90a9b638141c6874e6-00554bf992iad3
Cache-Control: public, max-age=259200
Expires: Sun, 10 May 2015 23:47:30 GMT
Date: Thu, 07 May 2015 23:47:30 GMT
Connection: keep-alive

Upvotes: 2

Views: 968

Answers (1)

Ash Wilson
Ash Wilson

Reputation: 24458

To get CORS working properly, you'll need to set the CORS headers on the Cloud Files object on Rackspace's end, rather than the ones served by your app. You can do this from the control panel by clicking on the gear icon next to each file:

control panel

The Cloud Files documentation includes a section on the CORS headers that are supported and what each means.

If you have a large number of assets, or a build process that publishes them automatically, you'll want to use the API or an SDK to set these instead. The developer documentation includes a code snippet that you can adopt to do this; substitute "Access-Control-Allow-Origin" or the other relevant headers for "Content-Type".

Here's a complete example using the Ruby SDK, Fog:

require 'fog'

# Authenticate
@client = Fog::Storage.new(
  :provider => 'rackspace',
  :rackspace_username => '{username}',
  :rackspace_api_key => '{apiKey}',
  :rackspace_region => '{region}'
)

# Find the file object
@directory = @client.directories.get("{container name}")
@file = @directory.get("{file name}")

# To only allow CORS requests from a page hosted at 'my-domain.com'
# You can also set this to '*' to allow CORS requests from anywhere
@file.access_control_allow_origin = "http://my-domain.com"
@file.save

Upvotes: 1

Related Questions