Legacy Development with Pow

2 minute read

Pow is a zero-config Rack server that makes developing Rack apps (include Rails apps) a snap on Mac OS X.

You install Pow:

curl get.pow.cx | sh

You create a symlink to your app:

cd ~/.pow
ln -s ~/dev/myapp

You point your browser to http://myapp.dev/ and there’s you app!   Awesome!

However, there is a downside:  Pow doesn’t play nicely with Apache (or any server listening on port 80). Life isn’t all greenfield, if in the course of the day you need to work on PHP or CGI legacy apps Pow is not so simple.   Pow creates a firewall rule that redirects port 80 to its port; to access Apache you need to either toggle the firewall rule on and off or move Apache to a different port all together. And now you’re running two web servers.  There has to be a better way.

The Win And there is, make your legacy app a Rack App.  Thanks to the rack-legacy gem, this is actually quite simple.

First, install the rack-legacy and rack-rewrite gems:

gem install rack-legacy rack-rewrite

(To sudo or not to sudo, that’s up to you).

Next,  in the top level of your legacy app create this config.ru file:

require 'rack'
require 'rack-legacy'
require 'rack-rewrite'

INDEXES = ['index.html','index.php', 'index.cgi']

use Rack::Rewrite do
  rewrite %r{(.*/$)}, lambda {|match, rack_env|
    INDEXES.each do |index|
      if File.exists?(File.join(Dir.getwd, rack_env['PATH_INFO'], index))
        return rack_env['PATH_INFO'] + index

use Rack::Legacy::Php, Dir.getwd
use Rack::Legacy::Cgi, Dir.getwd
run Rack::File.new Dir.getwd

The Details Rack::Legacy::Php runs any requested file with the extension .php. Rack::Legacy::Cgi runs any requested file that is set executable (which means you’ll need to make sure your .html files are not). Files that don’t end in .php and aren’t executable are served as static content by Rack::File.

The INDEXES array contains a list of files to check for if a directory is requested (just like Apache’s DirectoryIndex directive). You can change the order or use different names (default.htm anyone?).

The Catch rack-legacy uses the php-cgi command line program to run scripts and while PHP ships with current versions of OS X, php-cgi is not included. You’ll need to install PHP using MacPort/Homebrew/Fink/etc. That’s beyond the scope of this post but, if you’re doing this kind of development, it’s probably not beyond you.

The Caveat This is probably not a fast as running PHP using the Apache module and it’s certainly not as fast as something like FastCGI. If you are primarily developing legacy apps you probably should stick to Apache. However, if you mostly work with Rack apps and just occasionally need legacy support, this is a great way to go.