Rails 3.2.9 Intercept Asset Requests For Remapping - ruby-on-rails

In Ruby on Rails 3.2.9 is there a way to intercept asset requests and remap the URL that is being requested.
For example, for a request for /assets/javascripts/app.js I would like to intercept the request and strip out javascripts/. I've tried in the application.rb
config.asset_path = proc { |path|
path.slice! 'javascripts/'
}

I'm not aware of any way to intercept requests to assets and I highly doubt there's one or there'll ever be one at all.
Simply because it wouldn't work with compiled assets. What if the assets are on another server with a completely different software stack? For example if someone chooses to host the assets on Amazon S3, how could requests be intercepted at all?
If you really need this feature and you are self-hosting your assets the best way mght be configuring your web server to redirect the request.
Have a look at RewriteEngine for Apache or HttpRewriteModule for nginx. They provide mechanisms for URL rewriting. (I guess most production-grade web servers do have something simlar, too)

Related

How do CDN's work with a Rails application?

So I read this and the Rails docs regarding CDNs here and I'm still confused about a couple of things conceptually.
When do the Rails files like the controllers and models come into play?
How do you invalidate the CDN cache when an image updates?
But what about files with dynamic content say like a user's name and address. How is that handled?
This is my understanding. Please correct me if I misspeak:
First, when a request is made say to myrailsapp.com, the request first goes to the CDN because we now pointed the CNAME of myrailsapp.com to the CDN address (say it's cdnmyrailsapp.com). I guess the DNS servers understand to route those requests to the CDN. The CDN checks whether or not it has any content cached. IF it does not, I guess the CDN forwards the request to the actual server? That's when the controller for Rails is hit and a static asset or javascript file is delivered to the CDN. All future requests for that file now use the cached version on the CDN.
CDN can only serve your static assets (compiled css and js files etc), not models and controllers. (you can get this precompiled files by assets:precompile)
Your server serve all dynamic content dyrectly without CDN.
Your files are placed on CDN domain (http://c000000.cdn.rackspacecloud.com for sample), your application left on your domain (you do not need CNAME).
For images you need manually send them (fog-aws, fog gems ) on upload.

best method for serving static pages hosted on s3 in rails app on heroku

I have a rails app which is dynamic and works well on it's own, but we also have an s3 bucket which has a bunch of html pages which are constantly updated and revised.
I'm looking for an overall solution which allows me to route requests to the static files for a large number of potential pages, but also use the app for dynamic pages. None of the static pages require a user login, but all of the dynamic pages require a user login.
We are also currently using heroku to serve the application which is something else to take into consideration.
What are some methods/gems/ideas for how to serve these static pages quickly on the same domain without interfering with the rest of the app?
According to Heroku you have 3 options:
You can use page_caching. page_caching has been removed from rails4 but is still available as an external gem actionpack-page_caching but from what I see, does not work as expected in heroku (files are not persisted).
You can use cache through HTTP headers (which actually caches data on the client)
You can use Rack::Cache as a reverse proxy.
I think the best solution for your matter is the third one. Heroku suggests that you use Rack::Cache. Of course you can combine that with the HTTP headers.
You can find more details here and here

How to prevent abusive crawlers from crawling a rails app deployed on Heroku?

I want to restrict the crawler access to my rails app running on Heroku. This would have been a straight forward task if I was using Apache OR nginX. Since the app is deployed on Heroku I am not sure how I can restrict access at the HTTP server level.
I have tried to use robots.txt file, but the offending crawlers don't honor robot.txt.
These are the solutions I am considering:
1) A before_filter in the rails layer to restrict access.
2) Rack based solution to restrict access
I am wondering if there are any better ways to deal with this problem.
I have read about honeypot solutions: You have one URI that must not be crawled (put it in robots.txt). If any IP calls this URI, block it. I'd implement it as a Rack middleware so the hit does not go to the full Rails stack.
Sorry, I googled around but could not find the original article.

Rails: Proxy Pass?

I've got a web-app that I want to migrate to Rails, which is currently just plain HTML with an Apache proxy to another server, running a custom database/webserver that serves the site's dynamic content.
For the moment, I want to do a staged move, since the content on the proxied server I won't be able to update until I update the static (HTML) server.
So... how would I configure a Rails route to proxy all requests to /dynamic/* to this other server? Or, how would I translate the Apache rule below to Rails?
Apache Proxy Rule:
ProxyPassMatch ^((?i)/dynamic/)(.*)$ http://xxx.xxx.com:8080/$2
ProxyPassReverse /dynamic/ http://xxx.xxx.com:8080/
Rails routes are used to route some urls to one controller and one action.
You can't make a route to a distant URL or proxying like this.
And that wouldn't be a good idea as it would force us to load all rails (activerecord and everything) when it wouldn't be necessary at all. That's the opposite of scalability.
Using an Apache Proxy rule remains the most appropriate here.

A route to serve static assets (like .jpgs, etc?)

I've worked my way through a number of interesting routing problems - turning a request URL into a hash, etc., but just out of curiosity, is there a way to tell the routing system that you want anything that comes under a certain url subpath to be served literally - without going through a controller?
For instance, if I have /home/me/public_html/rails_proj/images/foo.jpg, and .../rails_proj/images/other/bar.jpg, can I insert a route that says "anything under images should just be served as an object of the default mime type?"
Might be interesting.
If you put the "images" directory into the "public" folder of the Rails app (for example: /public/images/) then you shouldn't have any problems with MIME types unless your web server is configured wrongly.
According to your examples, you want the images dir in the root of the app. I don't think there is a way though Rails to make those images visible, but if you really wanted to you could use mod_rewrite to make it work. Once again, it would be up to the web server to make sure the images had the correct MIME type.
Things that are served out of the public directory will not go through Rails - they'll just be handled by your server (probably apache). The only reason why you would need to serve images through the rails system is if you wanted some kind of control on who could access them. Just put everything else in public and access ala:
siteurl.whatever/images/*.jpg
I typically use nginx as a frontend and Apache/Passenger as a backend. Ngingx proxies all Rails requests to Apache but handles all static content itself. Check out the examples on the English nginx wiki. Here is a small excerpt for nginx config:
server {
listen 80;
server_name www.domain.com;
location ~* \.(jpg|jpeg|gif|png|ico|css|bmp|js)$ {
root /path/to/static/assets/dir;
}
location / {
proxy_pass http://127.0.0.1:81;
}
}
So have apache listen on port 81 to handle Rails requests proxied by nginx and let nginx deliver static content. Not only is nginx supposedly faster than Apache at delivering static content, but this also offloads your Rails application for every image, stylesheet, javascript or whatever other static content.
I think the simplest way solve this problem is just using image_path helper method, which provide you the path for the image you want to display in the view.
For example, if you want to refer a logo.png under the /assets/images/logo.png, you can just use image_path('logo.png').
Caveat: if your request URL matches a static resource WEBrick, mongrel or whatever will happily serve it. At any cost, you don't want this in production: if your traffic is high enough your app will be brought to its knees just because its mongrels will be busy serving static content.
So make sure that your web server is properly configured for all kinds of static content as the previous commenters have pointed out.

Resources