If you’re a Rails developer, you probably have used Pow to simplify your development environment. Pow is a simple web proxy that makes it nicer to develop locally. For Rails (or any Rack environment), it will automatically start the service, map it to a clean domain, and proxy requests. For example, for The Storyline, I point at http://storylines.dev and it automatically starts up the server in dev mode if it isn’t running, and then sends requests along. The main advantage is that, if you follow conventions, you end up with an easy way to switch between dev & prod. Just change .com to .dev and you’re running off your dev box.
I use it for a lot of other projects, too. Right now, I took a day off to work on a Node.js project and used Pow to proxy off requests. For non-Rack apps, Pow simply acts like a simple web proxy. It won’t automatically start/stop your dev server.
This proxy support is buggy, however, and I’ve run into a few problems that I’ve had to fix. My fixes are at my fork of Pow. You can see all of the commits in this compare view. More details about the bugs themselves at the end of this post.
I also wanted to quickly document for posterity (and Google) how I run my dev copy of Pow. I want to have it written down so I don’t spend another morning re-learning this. The following notes assume you’ve used Pow before and are for people that want to develop features for or fix bugs in pow.
First, install the official version of Pow using the regular installer. Find the following files and copy them somewhere safe:
~/Library/LaunchAgents/cx.pow.powd.plist
/Library/LaunchDaemons/cx.pow.firewall.plist
/etc/resolver/dev
Next, check out the project locally. I almost always check out my own fork, then add remotes for the official repo and any other forks that have interesting commits so I can fetch and merge/cherry pick commits I want.
To run my own copy, I uninstall the official Pow install by using their uninstall script. Typically, this is something like curl get.pow.cx/uninstall.sh | sh at your terminal prompt.
Then, from your local copy of the project, use NPM to install the library on your system.
npm install -g
For me, that ended up with everything in /usr/local/lib/node_modules/pow with a symlink for the pow binary in /usr/local/bin.
Pow uses launchd to start/stop/restart the server, so the next step is recreating the various plists. Remember the files you copied earlier? Copy your saved copies back to where they belong.
Next, open up ~/Library/LauncgAgents/cx.pow.powd.plist in your favorite editor. Replace it with something like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>cx.pow.powd</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/node</string>
<string>/Users/sujal/code/thirdparty/pow/bin/pow</string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
The key bits are the ProgramArguments strings. The first should point to wherever your node executable lives. The second should point to where your pow script lives.
Then, you need to launchd to use those configs. Execute these commands at your terminal prompt:
sudo launchctl load /Library/LaunchDaemons/cx.pow.firewall.plist
launchctl load ~/Library/LaunchAgents/cx.pow.powd.plist
If you check for running node processes, you can just ps ax | grep node at the prompt to see if it’s running. You should see something like:
65965 ?? S 0:01.08 /usr/local/bin/node /Users/sujal/code/thirdparty/pow/bin/pow
The output should match whatever you put in for the arguments in the powd plist above.
Some details about the bugs I ran into (and fixed):
I’m using two non-Rails frameworks right now. I use Goliath.io for our API server on The Storyline. I’m using node.js & express.js for this 48 hour hacking break project.
In both cases, I have to use Pow’s simple HTTP proxy support to get it to talk to the dev instances. The two major issues I ran into had to do with cookies and redirect support.
For the Goliath app, I have optional cookie support for API clients that can support cookies and don’t want to muck with custom auth headers. This makes testing in the browser easier, for example. I found that cookies weren’t getting set when I connected through Pow but did work if I hit localhost directly. The bug had to do with how Pow was forwarding cookies. Cookie handling was just broken, so I fixed that.
The other issue I ran into had to do with redirects. My node.js app uses Passport.js for authentication. It seemed that all of the authentication redirects were getting swallowed by Pow. It manifested as a hung connection on the browser. The browser would just sit and spin, spin, spin. After 4 minutes (!), the connection would end and the browser would show an empty page. That’s fixed, too.
If you want to check out the bug fixes or have other concerns, you can see the commits here. Feel free to leave comments – I check my Github notifications regularly.