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 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, aftergit 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.
I think making the html file redirect is just fine. desktopcouch does something like this. They talk about it being there to help you find the port number, but it contains the security token too.
They also have some javascript to delay the redirect for a while so you can bookmark the redirect file. You can click to set a cookie to skip the delay in future.
It's been a while since I used desktopcouch, but I found an old redirect file laying around. Here it is:
http://jasonwoof.com/downloads/desktopcouch-redirect.txt
The code is pretty short, you might find something useful there.