What have you found for these years?

2013-12-10

tracing in pow

I wondered what's happening in pow, so I tried to trace
what it is doing. My conclusion is, how could this be
even more wrong?

Please follow me to see what's happening...

So on it's website, it's telling the users to install it via:

curl get.pow.cx | sh
Aside from the point that you should never do this (please
download the shell script and take a look before running it),
it is basically install.sh, which is trying to download a
tarball
for the specific version of pow and untar it,
and run the pow command to install the whole thing.

It would do a number of things. Let's only look at the
important ones, or there would be too much to look at.

So the pow command would pick the system installer,
it would then install a firewall plist, a number of
resolver configs, and a plist for pow itself in its
local installer.

After that, the installer would load the firewall with sudo,
and start pow via pow plist.

Note that since they are doing this in /Library/LaunchAgents
and /Library/LaunchDaemons, they would be running when
Mac OSX starts.

*

And what are they doing? There are a number of files
we should be looking at. Let's go through them one by one.

The firewall is probably cx.pow.firewall.plist.eco.
It is trying to forward port 80 to port 20559 by default.
That means, whenever you're hitting http://pow.dev:80 it
would be forwarded to http://127.0.0.1:20559.

Let's look into the DNS resolver, which I believe it's
resolver.eco, which would be installed into
/etc/resolver/dev with sudo.

According to Mac's resolver man page, this means only
domains ending with dev (or whatever it's configured) would
use this pow DNS server, listening on 20560 by default.

Lastly, the pow plist itself, which I think is cx.pow.powd.plist.eco,
which is simply trying to launch Node to run pow command.

*

So by installing pow, it would then install a pow daemon,
which itself is both a DNS server and an HTTP server. We'll
talk about this later. It would also install a special DNS
resolver for domains ending with .dev, and a firewall rule
for forwarding port 80 to port 20559.

In the end, what does pow really do for serving a request?

Mac would first look at /etc/resolver/dev and realize that
it needs a special DNS server located on 127.0.0.1:20560,
which is a pow DNS server, resolving the IP of the domain to
127.0.0.1, and the browser would then try to make a request
against 127.0.0.1:80, with header Host: whatever.dev, which
then the firewall would forward the request from 127.0.0.1:80
to 127.0.0.1:20559, which is the pow HTTP server, which would
try to look at ~/.pow/whatever, locating the config.ru, spawning
a nack_worker process, which is a Ruby server, listening on a
UNIX domain socket, and in the mean time, converting the request
object into a netstring embedding a JSON, writing into the UNIX
domain socket, and the nack_worker would parse the netstring,
extracting the JSON, parsing the JSON, and builds the Rack env
object based on the JSON it reads, finally calling the Rack app,
passing the response back to pow, and back to the browser.

Oh wait, it might not really pass the request along to the Rack app.
It could be intercepted by pow if the requested path matches a file
located in the particular Rack app's public directory.

Seriously? Sorry that I am too lazy to link the source line by line.
This is simply too much. It also needs to handle RVM stuffs, yet
another pile of stuffs.

I would much prefer a simple command to launch a server.
If you're developing a number of applications, and need to run them
at the same time, then I believe you must have the ability to solve
this in a more elegant way.

Maybe write a pow equivalent in Ruby, then all the conversions
could be omitted. We could simply spawn Ruby processes. I don't
see what's the point of using Node to run Ruby.

0 retries:

Post a Comment

All texts are licensed under CC Attribution 3.0