Rerouting to AWS hosted assets from a Heroku Rails app - ruby-on-rails

I have a Heroku hosted Rails app that has reached the 300MB limit for the slug size and can no push to Heroku. To fix this issue, I've setup an AWS S3 account and want to redirect the assets being requested from my Rails app to the new S3 location. The Rails app is basically just serving JSON files that point to the static assets using a relative URL. An iOS app using the Rails JSON then has a hardcoded domain URL, and appends the path to the resources to that domain and requests assets it needs.
I want to update my Heroku app and change my asset locations without requiring an update to the iOS app in order to change the asset domain. So, I need to redirect static asset requests from the Rails app to the AWS server.
In my git repo, I've ignored the assets in the public folder that I've moved to the AWS server. The asset files are present on my local machine, but are not part of the git repo when uploaded to Heroku.
So far I've tried changing the config.action_controller.asset_host which does not seem to work since these are static assets and are being returned by the web server before Rails gets it.
I tried using routes rules to redirect to a different domain, but these routes never seem to be captured. The static files appear to be returned before the Rails app has a chance to handle the request.
I've tried using the rack-rewrite gem to try and redirect my assets to a different domain with the following in `initializers/rack_rewrite.rb:
require 'rack/rewrite'
AppNamespace::Application.config.middleware.insert_before(Rack::Lock, Rack::Rewrite) do
r301 %r{/images(.*)}, 'http://my-subdomain.amazonaws.com/images$1'
end
This doesn't seem to work either and it always just returns the static files.
So far I've been trying for hours to figure out the proper way to handle this situation. I'm not a Rails developer by trade, I build iOS apps, so please let me know if I'm going about this the wrong way or completely missed the "right" way of doing this.

I solved this using routes and the 'rails_serve_static_assets'. I had to move the local images out of the public folder in order to avoid Nginx from returning the images before hitting the Rails app. The route ended up like so:
match '/images/(*path)', :to => redirect { |params, request|
"#{Rails.configuration.assets.aws_url}#{request.path}"
}

Related

Heroku + Rails4.2 : Cloudfront setup

I am trying to setup Cloudfront for my heroku app. The documentation seems to be lacking to stand independently.
Here are the steps I followed:
1. Setup Cloudfront in AWS console
2. Added cloudfront domain name to production.rb `config.action_controller.asset_host = 'XXXX.cloudfront.net'`
3. Set `config.assets.compile = true` in production.rb
4. Verified AWS_SECRET_ACCESS_KEY is correct in heroku config
5. I have added `gem 'rails_12factor', group: :production`
None of assets load anymore. Any step I am missing in the setup?
Update1:
In the chrome debugger the asset is correctly requested from cloudfront from this url: http://XXXXX.cloudfront.net/assets/application-22c7c249df1a24541d86603b0715eefe.css
However in the request header see a Status Code:302 Moved Temporarily. I am wondering if I have a redirect loop and how I can debug it.
Update2
Thanks everyone for the suggestions. Some more info:
When I try to download the asset from my app, I get a redirect to home page on browser but using curl I am able to get the asset. ex: curl 'http: //www.myapp.com/assets/application-c9a778bb55ad4152d956fd34fe6f7839.css'
The app doesnt use SSL. However I have still set Origin Protocol Policy to Match Viewer as per #Omar's suggestions
I tried to download the asset from my app on browser and am able to access the assets. ex: 'http: //www.myapp.com/assets/application-c9a778bb55ad4152d956fd34fe6f7839.css'
However trying to access the assets directly on cloudfront (d1ax5oefcdtdki.cloudfront.net/assets/application-c9a778bb55ad4152d956fd34fe6f7839.css) redirects it to myapp.com
Screenshots for cloudfront DS:
https://www.dropbox.com/s/bkg480d4it6zl2r/Screenshot%202015-12-06%2014.01.28.png?dl=0
http://glui.me/?i=7ah73hffrhvmpt7/2015-12-06_at_2.02_PM.png/
https://www.dropbox.com/s/dd4wwgm3md8w7qn/Screenshot%202015-12-06%2014.05.20.png?dl=0
For anyone else having issues debugging cloudfront.
The problem was Cloudfront had cached redirects (prob bec of wrong setup). After invalidating the cache I was able to force CF to fetch assets from my app and serve them.
When you request the asset for the first time, cloudfront checks whether the file is cached or not so for example you request:
http://XXXXX.cloudfront.net/assets/application-22c7c249df1a24541d86603b0715eefe.css
for the first time cloudfront will give a cache miss and then it will pull the file from it equivalent path from rails. So that the next time you request the same file, it will be already cached.
In order for this to work you need to make sure that you have everything setup correctly.
From rails side there is nothing much to do except setting the assets_host in production.rb. As you already have the rails_12factor gem there is no need to add the config.assets.compile = true. From the documentation of the gem you can see in the how section that it add serving static assets "the documentation".
From cloudfronts side that is where I think you are facing a problem, you need to set some settings to let cloudfront know how it can communicate with your rails app when the cache misses. In the cloudfront setting you need to check the
Origin Domain Name to be the url of your rails app.
Origin Protocol Policy to Match Viewer
Distribution State to Enabled
Also there are some other settings there that can help you optimize your content delivery caching.

How do I get my rails assets to be served by cloudflare instead of my server?

I'm running a rails app on heroku and recently switched to cloudflare for CDN for asset serving. My understanding was that once I use cloudflare, my assets (ie js,css,images) would be served from cloudflare and not from my own server but in my heroku logs I still see the requests for assets. Do I need to configure something in my rails app like setting the asset_host or something? Thanks.
It might be helpful to clarify what CloudFlare caches by default as well (just to make sure you know that not every file extension is automatically cached).
Note: Caching also depends on how many requests we get for the resources before it gets cached (minimum of three).

Problems serving .js and .css assets cloudfront CDN Heroku Rails 4 App

I am trying to host the assets of my Rails 4 App over Cloudfront CDN. I used to use asset_sync and s3 but I wanted to switch over to a CDN.
When I go to my Heroku App, I see that all the pages are just bare HTML. None of the JS or CSS is being loaded.
These are the errors I am getting from my Console:
Screenshot of console errors: http://i61.tinypic.com/15rxdsj.jpg
Also, I am not sure if I have set up my Origin Domain Name and Origin Path correctly on the Cloudfront Origin Settings.
Currently I am using my heroku app url as the Origin Domain Name and "/production/assets" as the Origin Path.
Production.rb file: http://pastebin.com/2dzLpGfE
I have been trying unsuccessfully for the past week to get the Heroku app to display the CSS and JS. I would greatly appreciate any insight. Thanks in advance!
Moving to Cloudfront isn't as drastic as change as you seem to think if you had everything working from S3. After all, Cloudfront simply distributes the contents of your S3 bucket to edge locations. This means you just have to let Rails know to look for the CDN and not S3.
There are a lot of things that could be going on. You could have misconfigured Cloudfront, which should be pointing to your S3 bucket as the origin. You should test that setup by checking to see an asset in the browser by using the Cloudfront URL. The main point is that Cloudfront should have no idea about your Rails app.
Meanwhile, you can still use AssetSync to push your assets to S3 "underneath" an assets path. You must also configure config.action_controller.asset_host as described here.

Heroku does not display images and also is not accepting my authentication User/Pass for access..How can I access my images?

I have deployed my exhisting project to Heroku. My main pages display some images, which have not loaded on heroku ..... And my backend end authentication pages , accessible only by me, will not accept my user/pass.
images are stored in
app/assets/images
Several points for you
Images
Heroku runs an ephemeral file system, which essentially means your files are overwritten each time you push a new deploy.
This doesn't matter for asset based images, but if you're using the likes of Paperclip to store dynamically-uploaded images, you need to ensure you're able to persist the data (with the likes of S3)
--
Precompilation
In your case, the problem will likely be to do with the precompilation process:
In the production environment Sprockets uses the fingerprinting scheme
outlined above. By default Rails assumes assets have been precompiled
and will be served as static assets by your web server.
Precompilation of the assets is when the Rails application will serve assets from the /public directory, rather than the /assets dir. This is super important as it means if you're referencing assets using "static" CSS references, it simply won't work, especially on Heroku
The best solution for this is to use one of the Rails preprocessors (SCSS / SASS) & use one of the asset path helpers to reference the dynamic asset location:
#app/assets/stylesheets/application.css.scss
body {
background: asset_url("your_image.png");
}
--
Authentication
Your authentication is probably a problem with your database
A problem with Heroku is that as it uses a different database than your local system, you'll have to populate it with the data required to get it working.
It's a common issue to not be able to load the database correctly, missing out many different migrations. I would recommend the following:
$ heroku run rake db:migrate
After this, you need to ensure that you're able to create the relevant details in your application

Page caching trick on Heroku?

I am moving a rails app to Heroku.
Heroku doesn't seem to support page caching.
So I generated cached pages on my development machine and checked them in to Heroku.
For example, /about_us generates public/about_us.html.
But when I call /about_us, public/about_us.html doesn't seem to be called.
Should my trick work?
Thanks.
Sam
In Rails 3, you'll be using the assets pipeline, so your assets--about_us.html--will be precompiled and put into a folder, WITHIN your public folder. Usually, this file will not be located at 'public/about_us.html'.
With your assets now precompiled, they'll be statically available and appended with an id, that will uniquely identify this asset until it is changed. With the unique signature, caching will occur on both Heroku's (last I checked) as well as within browsers.
Basically, the asset pipeline is doing this already for you.

Resources