If you ever tried to set up Ruby on Rails (RoR) on IIS 7.0 with FastCGI you have probably noticed that the process is not very straightforward. There are a few workarounds that need to be applied in order for RoR to function correctly. In particular, handling of static files in your web application can be tricky on IIS 7.0. The problem is that RoR uses clean URL’s that look similar to this: http://mysite.com/home/about. In order for RoR to be invoked for this kind of URL’s it is necessary to create a “catch all” handler mapping in IIS (that is a handler mapping with path attribute set to “*“). When you create such a handler mapping it will cause requests for static files to be routed to RoR, which will obviously fail to handle them.
For RoR to work correctly on IIS with FastCGI it needs to behave like a 404 handler, meaning that it should be invoked only if the requested URL does not exist as a file on a physical file system. The default IIS configuration does not allow this kind of configuration, so there are several workarounds available today - this article describes them in great details. However, these workarounds are either not recommended for production usage or are not easy to configure. In this post I will explain how URL Rewrite Module for IIS 7.0 can be used to configure IIS and RoR to work correctly with static files.
First let’s setup RoR. To set it up I used instructions from these two great articles:
Both articles are a bit outdated, so I ended up with performing the following steps:
Step 1: Installed latest version of Ruby by using One-Click Installer. At the time of writing this post the latest stable version was 1.8.6-26.
Step 2: Installed Rails by running gem installer from command line window:
gem intsall rails --include-dependencies
Step 3: Installed RoR extensions for IIS. After installation completed I checked that everything was setup successfully by typing the following in the command line window:
C:\>irb
irb(main):001:0> require 'fcgi'
=> true
irb(main):002:0> quit
Step 4: Created a web site in IIS with physical path C:\inetpub\ruby and with host name “ruby”. Also modified the %WINDIR%\system32\drivers\etc\hosts file to include this line:
127.0.0.1 ruby
Note that if you want to have RoR application in the “Default Web Site” in IIS you do not need to do this step.
Step 5: Created a test RoR application in a root folder of a web site:
cd c:\inetpub\ruby
rails myapp
cd myapp
ruby script\generate controller test index
Step 6: Created a temporary FastCGI handler mapping for RoR:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="Ruby via FastCGI"
path="*"
verb="*"
modules="FastCgiModule"
scriptProcessor="C:\ruby\bin\ruby.exe|c:\inetpub\ruby\myapp\public\dispatch.fcgi development"
resourceType="Unspecified" requireAccess="Script" />
</handlers>
</system.webServer>
</configuration>
Step 7: Modified the RoR application to display some meaningful information. For that I opened the app\controller\test_controller.rb file and pasted the following code into it:
class TestController < ApplicationController
def index
render :text=>"The index action"
end
def about
render :text=>"The about action"
end
end
Step 8: Tested that my RoR application works by browsing to http://ruby/test/about

Now let me show you why the handler mapping, that I have created in step 6, is problematic. If I try to request a static image file in my application I get this response:

This is because the “catch all” handler mapping for RoR causes the HTTP request for static file to be given to RoR. RoR tries to match the requested URL against all the routes defined for the application and since there is no route defined for static file the routing error is raised.
Now we will use URL rewrite module to fix this problem. First, let’s take a look at this article that explains how RoR is supposed to be setup on Apache Web Server. According to this article, RoR relies on Apache mod_rewrite to always rewrite requested URL’s to dispatch.fcgi unless the requested file already exists on a file system. Let’s try to configure IIS URL rewrite module to do the same. To do that we will take these scary looking mod_rewrite rules:
# Redirect all requests not available on the filesystem to Rails
RewriteEngine On
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
and import them into IIS by using “Import Rules” feature of URL rewrite module:

After saving the converted rules into the web.config file we will need to modify the handler mapping for RoR so that it does not use “*” mapping anymore:
<handlers>
<add name="Ruby via FastCGI"
path="dispatch.fcgi"
verb="*"
modules="FastCgiModule"
scriptProcessor="C:\ruby\bin\ruby.exe|c:\inetpub\ruby\myapp\public\dispatch.fcgi development"
resourceType="Unspecified" requireAccess="Script" />
</handlers>
Now let’s test whether these modifications help to resolve the problem with serving static files. First we confirm that the RoR application still works. For that we browse to http://ruby/test/about again:

Then we check if requests for static files are handled correctly. For that we browse to http://ruby/myapp/public/images/rails.png:

As you can see the mod_rewrite rules that were imported from RoR documentation work quite well in IIS. The Ruby on Rails application is fully functional and we did not use any workarounds for that - all the necessary functionality is available in IIS 7.0.
Read the complete post here
Comments