git-annex/doc/design/assistant/blog/day_44__webapp_basics.mdwn
2012-07-26 12:57:41 -04:00

83 lines
3.6 KiB
Markdown

After an all-nighter, I have `git annex webapp` launching a WebApp!
It doesn't do anything useful yet, just uses Yesod to display a couple of
hyperlinked pages and a favicon, securely.
The binary size grew rather alarmingly, BTW. :) Indeed, it's been growing
for months..
-rwxr-xr-x 1 root root 9.4M Jul 21 16:59 git-annex-no-assistant-stripped
-rwxr-xr-x 1 joey joey 12M Jul 25 20:54 git-annex-no-webapp-stripped
-rwxr-xr-x 1 joey joey 17M Jul 25 20:52 git-annex-with-webapp-stripped
----
Along the way, some Not Invented Here occurred:
I didn't use the yesod scaffolded site, because it's a lot of what
seems mostly to be cruft in this use case. And because I don't like
code generated from templates that people are then expected to edit. Ugh.
That's my least favorite part of Yesod. This added some pain, since
I had to do everything the hard way.
I didn't use [wai-handler-launch](http://hackage.haskell.org/package/wai-handler-launch)
because:
* It seems broken on IPv6 capable machines (it always opens
`http://127.0.0.1:port/` even though it apparently doesn't always
listen there.. I think it was listening on my machine's ipv6 address
instead. I know, I know; I should file a bug about this..)
* It always uses port 4587, which is **insane**. What if you have two
webapps?
* It requires javascript in the web browser, which
is used to ping the server, and shut it down when the web browser closes
(which behavior is wrong for git-annex anyway, since the daemon should
stay running across browser closes).
* It opens the webapp on web server startup, which is wrong for git-annex;
instead the command `git annex webapp` will open the webapp,
after `git annex assistant` started the web server.
Instead, I rolled my own WAI webapp laucher, that binds to any free port
on localhost, It does use `xdg-open` to launch the web browser,
like wai-handler-launch (or just `open` on OS X).
Also, I wrote my own WAI logger, which logs using System.Log.Logger,
instead of to stdout, like `runDebug` does.
----
The webapp only listens for connections from localhost, but that's
not sufficient "security". Instead, I added a secret token to
every url in the webapp, that only `git annex webapp` knows about.
But, if that token is passed to `xdg-open` on its command line,
it will be briefly visible to local attackers in the parameters of
`xdg-open`.. And if the web browser's not already running, it'll run
with it as a parameter, and be *very* visible.
So instead, I used a nasty hack. On startup, the assistant
will create a html file, readably only by the user, that redirects
the user to the real site url. Then `git annex webapp` will run
xdg-open on that file.
----
Making Yesod check the `auth=` parameter (to verify that the secret token
is right) is when using Yesod started to pay off. Yesod has a simple
`isAuthorized` method that can be overridden to do your own authentication
like this.
But Yesod really started to shine when I went to add the `auth=` parameter
to every url in the webapp. There's a `joinPath` method can can be used
to override the default url builder. And every type-safe url in the
application goes through there, so it's perfect for this.
I just had to be careful to make it not add `auth=` to the url for the
favicon, which is included in the "Permission Denied" error page. That'd be
an amusing security hole..
----
Next up: Doing some AJAX to get a dynamic view of the state of the daemon,
including currently running transfers, in the webapp. AKA stuff I've never
done before, and that, unlike all this heavy Haskell Yesod, scares me. :)