Ruby on Rails - Problems on Fedora 13

It is July 2010 and I just updated my desktop (which runs my webserver and hosts my rails applications) to fedora 13. As has sadly happened before, this has broken my rails applications.

Mongrel Hassles

Before we delve into what broke my rails install, let me gripe about another problem, namely whenever I reboot my system, I have to hand restart my mongrel clusters. Typically there are some PID files in /xx/rails/myapp/tmp/pids that provide PID's for mongrel servers that no longer exist. As long as these PID files are in place, I am unable to restart my mongrel clusters. I must to track down these PID files, delete them, then issue the command:

service mongrel_cluster restart
Or another twist, if I delete the PID files by mistake, then I need to track down the processes and kill them (which is easier frankly) or the mongrel maintenance script refuse to stop or start them.

Rendering Issue

What is happening is that when I visit my rails application URL's the views all appear as verbatim html, the html is not being rendered by the browser.

In July of 2010, I seem to be running rails 2.3.5

cholla $ yum list | grep rails
rubygem-rails.noarch                     1:2.3.5-1.fc13               @fedora   

If I visit the mongrel cluster directly via the url http://localhost:8001 everything works just fine (this is a nice discovery), so this is not a rails problem per se. I am running an apache webserver that relays to a mongrel proxy. Apparently what is happening is that now apache is labelling the Content-Type for the proxyed rails pages as text/plain, whereas we would like text/html.

I have no idea what has changed, presumably Apache has now decided to "volunteer" to fill in the missing Content-Type, but who knows for sure at this point.

A useful trick is to use telnet to talk to a web server (either to the mongrel directly, or to apache) via:

telnet localhost 8001
GET / HTTP/1.1
Indeed, two returns are required after the "GET" line (one to end the GET line itself, another to provide the blank line required by the HTTP protocol).

Rendering issues, the bottom line

Who would have believed it, but this was a problem in mongrel, and in the cookie handling of all things. In the file /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel/cgi.rb is a method send_cookies which has/had some bogus code. This would blow up, with one of the results being that the proper HTTP headers were not getting into the responses. The fixed code that I hacked into this file is:
    def send_cookies(to)
      # convert the cookies based on the myriad of possible ways to set a cookie
      if @head['cookie']
        cookie = @head['cookie']
        case cookie
        when Array
          cookie.each {|c| to['Set-Cookie'] = c.to_s }
        when Hash
          cookie.each_value {|c| to['Set-Cookie'] = c.to_s}
        # TJT code added to fix nasty bug
        when String
          cookies = cookie.split.map { |a| a[-1..-1]==';'?a[0..-2]:a }
          cookies.each do |c|
            if c.split('=').length == 2
              to['Set-Cookie'] = c
            else
              to['Set-Cookie'] = c+'='
            end
          end
        else
          to['Set-Cookie'] = cookie.to_s
        # TJT end of code added
        #else
        #  to['Set-Cookie'] = options['cookie'].to_s
        end

        @head.delete('cookie')
      end

      # @output_cookies seems to never be used, but we'll process it just in case
      @output_cookies.each {|c| to['Set-Cookie'] = c.to_s } if @output_cookies
    end

This fix is a near verbatim copy of what was recommended by one of the participants in the following discussions:

There were several lessons learned in all of this. The first and foremost is to take a peek at the server logs, in this case /u1/rails/micros/log/mongrel.8001.log. It was the errors and traceback here that led me to the true problem.

Note that when I ran script/server this ran mongrel, yet without a problem. I don't know what to say about that. The problem only appeared when the clusters were run.

Passenger

This was recommended to me when I ran afoul of troubles with mongrel. Apparently it was once known as mod_rails or mod_rack It works with either Apache or Nginx.

Passenger aka modrails aka mod_rack

It is not available via yum for fedora. The recommended way to install it is:

gem install passenger
passenger-install-apache2-module
It looks pretty interesting. It is an apache module, so it starts and stops along with apache rather than being a separate mongrel_cluster service.
Feedback? Questions? Drop me a line!

Ruby on Rails notes / tom@mmto.org