Index: trunk/app.psgi
===================================================================
--- trunk/app.psgi	(revision 78)
+++ trunk/app.psgi	(revision 79)
@@ -1,4 +1,12 @@
 #!/usr/bin/perl -w
 use strict;
+
+#TODO: allow individual options to be set via environment vars, too
+BookmarksApp->new({ config_file => $ENV{CONFIG_FILE} })->to_app;
+
+package BookmarksApp;
+
+use parent qw{Plack::Component};
+use Plack::Util::Accessor qw{config_file config _app _controller};
 
 use YAML;
@@ -9,97 +17,90 @@
 use Bookmarks::Controller;
 
-#TODO: allow individual options to be set via environment vars, too
+sub prepare_app {
+    my $self = shift;
 
--e $ENV{CONFIG_FILE} or die "Config file $ENV{CONFIG_FILE} not found\n";
+    -e $self->config_file or die "Config file " . $self->config_file . " not found\n";
 
-my $config = YAML::LoadFile($ENV{CONFIG_FILE});
+    my $config = YAML::LoadFile($self->config_file);
+    $self->config($config);
 
-sub get_controller {
-    my $env = shift;
-    my $req = Plack::Request->new($env);
+    my $router = router {
+        resource '/' => sub {
+            GET {
+                # check for a uri param, and if there is one present,
+                # see if a bookmark for that URI already exists; if so
+                # redirect to that bookmark, and if not, show the form
+                # to create a new bookmark
+                if (defined $self->_controller->request->param('uri')) {
+                    return $self->_controller->find_or_new;
+                }
 
-    return Bookmarks::Controller->new({
-        request => $req,
-        dbname  => $config->{dbname},
-    });
-}
+                # otherwise return a list
+                return $self->_controller->list;
+            };
+            POST {
+                # create the bookmark and redirect to the new bookmark's edit form
+                return $self->_controller->create_and_redirect;
+            };
+        };
 
-my $router = router {
-    resource '/' => sub {
-        GET {
-            my ($env) = @_;
-            my $controller = get_controller($env);
+        resource '/list' => sub {
+            GET {
+                return $self->_controller->list;
+            };
+        };
 
-            # check for a uri param, and if there is one present,
-            # see if a bookmark for that URI already exists; if so
-            # redirect to that bookmark, and if not, show the form
-            # to create a new bookmark
-            if (defined $controller->request->param('uri')) {
-                return $controller->find_or_new;
-            }
+        resource '/feed' => sub {
+            GET {
+                return $self->_controller->feed;
+            };
+        };
 
-            # otherwise return a list
-            return $controller->list;
+        resource '/{id}' => sub {
+            GET {
+                my ($env, $params) = @_;
+                return $self->_controller->view($params->{id});
+            };
+            POST {
+                my ($env, $params) = @_;
+                return $self->_controller->update_and_redirect($params->{id});
+            };
         };
-        POST {
-            my ($env) = @_;
-            my $controller = get_controller($env);
 
-            # create the bookmark and redirect to the new bookmark's edit form
-            return $controller->create_and_redirect;
+        resource '/{id}/{field}' => sub {
+            GET {
+                my ($env, $params) = @_;
+                return $self->_controller->view_field($params->{id}, $params->{field});
+            };
         };
     };
 
-    resource '/list' => sub {
-        GET {
-            my ($env) = @_;
-            my $controller = get_controller($env);
+    $self->_app(
+        builder {
+            enable_if { $_[0]->{REMOTE_ADDR} eq $config->{proxy_ip} } 'ReverseProxy';
+            enable_if { $_[0]->{REQUEST_METHOD} ne 'GET' } 'Auth::Digest', (
+                realm           => 'Bookmarks',
+                secret          => $config->{digest_key},
+                password_hashed => 1,
+                authenticator   => sub { $config->{digest_password} }
+            );
+            sub { $router->dispatch(shift); };
+        }
+    );
+}
 
-            return $controller->list;
-        };
-    };
+sub call {
+    my $self = shift;
+    my $env = shift;
 
-    resource '/feed' => sub {
-        GET {
-            my ($env) = @_;
-            my $controller = get_controller($env);
+    # initialize the controller based on this request
+    $self->_controller(
+        Bookmarks::Controller->new({
+            request => Plack::Request->new($env),
+            dbname  => $self->config->{dbname},
+        })
+    );
 
-            return $controller->feed;
-        };
-    };
-
-    resource '/{id}' => sub {
-        GET {
-            my ($env, $params) = @_;
-            my $controller = get_controller($env);
-
-            return $controller->view($params->{id});
-        };
-        POST {
-            my ($env, $params) = @_;
-            my $controller = get_controller($env);
-
-            return $controller->update_and_redirect($params->{id});
-        };
-    };
-
-    resource '/{id}/{field}' => sub {
-        GET {
-            my ($env, $params) = @_;
-            my $controller = get_controller($env);
-
-            return $controller->view_field($params->{id}, $params->{field});
-        };
-    };
-};
-
-builder {
-    enable_if { $_[0]->{REMOTE_ADDR} eq $config->{proxy_ip} } 'ReverseProxy';
-    enable_if { $_[0]->{REQUEST_METHOD} ne 'GET' } 'Auth::Digest', (
-        realm           => 'Bookmarks',
-        secret          => $config->{digest_key},
-        password_hashed => 1,
-        authenticator   => sub { $config->{digest_password} }
-    );
-    sub { $router->dispatch(shift); };
-};
+    # dispatch to the app
+    $self->_app->($env);
+}
