mark: A photo of Mark kneeling on top of the Taal Volcano in the Philippines. It was a long hike. (Default)
Mark Smith ([staff profile] mark) wrote in [site community profile] changelog2010-02-17 04:45 am

[dw-free] Remove Apache2-specificness from DW::Routing and friends

[commit: http://hg.dwscoalition.org/dw-free/rev/b6ad03cd95b5]

http://bugs.dwscoalition.org/show_bug.cgi?id=2282

Make DW::Routing/DW::Template not depend on Apache2 directly.

Patch by [personal profile] exor674.

Files modified:
  • cgi-bin/Apache/LiveJournal.pm
  • cgi-bin/DW/Controller.pm
  • cgi-bin/DW/Controller/Edges.pm
  • cgi-bin/DW/Controller/Misc.pm
  • cgi-bin/DW/Controller/Nav.pm
  • cgi-bin/DW/Request/Apache2.pm
  • cgi-bin/DW/Routing.pm
  • cgi-bin/DW/Routing/Apache2.pm
  • cgi-bin/DW/Template.pm
  • cgi-bin/DW/Template/Apache2.pm
  • cgi-bin/LJ/ModuleLoader.pm
  • t/routing.t
--------------------------------------------------------------------------------
diff -r 4b28bac2991f -r b6ad03cd95b5 cgi-bin/Apache/LiveJournal.pm
--- a/cgi-bin/Apache/LiveJournal.pm	Tue Feb 16 16:05:18 2010 +0000
+++ b/cgi-bin/Apache/LiveJournal.pm	Wed Feb 17 04:45:29 2010 +0000
@@ -39,8 +39,8 @@ use Compress::Zlib;
 use Compress::Zlib;
 use XMLRPC::Transport::HTTP;
 use LJ::URI;
-use DW::Routing::Apache2;
-use DW::Template::Apache2;
+use DW::Routing;
+use DW::Template;
 
 BEGIN {
     $LJ::OPTMOD_ZLIB = eval "use Compress::Zlib (); 1;";
@@ -331,7 +331,7 @@ sub trans
 
     # only allow certain pages over SSL
     if ($is_ssl) {
-        my $ret = DW::Routing::Apache2->call( $r, ssl => 1 );
+        my $ret = DW::Routing->call( ssl => 1 );
         return $ret if defined $ret;
 
         if ($uri =~ m!^/interface/! || $uri =~ m!^/__rpc_!) {
@@ -657,7 +657,7 @@ sub trans
 
         # see if there is a modular handler for this URI
         my $ret = LJ::URI->handle($uuri, $r);
-        $ret = DW::Routing::Apache2->call( $r, username => $user ) unless defined $ret;
+        $ret = DW::Routing->call( username => $user ) unless defined $ret;
         return $ret if defined $ret;
 
         if ($uuri eq "/__setdomsess") {
@@ -954,7 +954,7 @@ sub trans
 
     # see if there is a modular handler for this URI
     my $ret = LJ::URI->handle($uri, $r);
-    $ret = DW::Routing::Apache2->call( $r ) unless defined $ret;
+    $ret = DW::Routing->call unless defined $ret;
     return $ret if defined $ret;
 
     # customview (get an S1 journal by number)
@@ -1376,7 +1376,7 @@ sub journal_content
     # only if HTML is set, otherwise leave it alone so the user
     # gets "messed up template definition", cause something went wrong.
     if ( $handle_with_siteviews && $html ) {
-        return DW::Template::Apache2->render_string( $html, $opts->{siteviews_extra_content} );
+        return DW::Template->render_string( $html, $opts->{siteviews_extra_content} );
     } elsif ( $handle_with_bml ) {
         my $args = $r->args;
         my $args_wq = $args ? "?$args" : "";
diff -r 4b28bac2991f -r b6ad03cd95b5 cgi-bin/DW/Controller.pm
--- a/cgi-bin/DW/Controller.pm	Tue Feb 16 16:05:18 2010 +0000
+++ b/cgi-bin/DW/Controller.pm	Wed Feb 17 04:45:29 2010 +0000
@@ -19,8 +19,8 @@ use strict;
 use strict;
 use warnings;
 use Exporter;
-use DW::Routing::Apache2;
-use DW::Template::Apache2;
+use DW::Routing;
+use DW::Template;
 
 our ( @ISA, @EXPORT );
 @ISA = qw/ Exporter /;
@@ -42,14 +42,14 @@ sub needlogin {
 
 # returns an error page using a language string
 sub error_ml {
-    return DW::Template::Apache2->render_template(
+    return DW::Template->render_template(
         'error.tt', { message => LJ::Lang::ml( @_ ) }
     );
 }
 
 # return a success page using a language string
 sub success_ml {
-    return DW::Template::Apache2->render_template(
+    return DW::Template->render_template(
         'success.tt', { message => LJ::Lang::ml( @_ ) }
     );
 }
diff -r 4b28bac2991f -r b6ad03cd95b5 cgi-bin/DW/Controller/Edges.pm
--- a/cgi-bin/DW/Controller/Edges.pm	Tue Feb 16 16:05:18 2010 +0000
+++ b/cgi-bin/DW/Controller/Edges.pm	Wed Feb 17 04:45:29 2010 +0000
@@ -21,11 +21,11 @@ package DW::Controller::Edges;
 
 use strict;
 use warnings;
-use DW::Routing::Apache2;
+use DW::Routing;
 use DW::Request;
 use JSON;
 
-DW::Routing::Apache2->register_string(  "/data/edges", \&edges_handler, user => 1, format => 'json' );
+DW::Routing->register_string(  "/data/edges", \&edges_handler, user => 1, format => 'json' );
 
 my $formats = {
     'json' => [ "application/json; charset=utf-8", sub { $_[0]->print( objToJson( $_[1] ) ); } ],
diff -r 4b28bac2991f -r b6ad03cd95b5 cgi-bin/DW/Controller/Misc.pm
--- a/cgi-bin/DW/Controller/Misc.pm	Tue Feb 16 16:05:18 2010 +0000
+++ b/cgi-bin/DW/Controller/Misc.pm	Wed Feb 17 04:45:29 2010 +0000
@@ -22,11 +22,11 @@ use strict;
 use strict;
 use warnings;
 use DW::Controller;
-use DW::Routing::Apache2;
-use DW::Template::Apache2;
+use DW::Routing;
+use DW::Template;
 
-DW::Routing::Apache2->register_string( '/misc/whereami', \&whereami_handler, app => 1 );
-DW::Routing::Apache2->register_string( '/pubkey',        \&pubkey_handler,   app => 1 );
+DW::Routing->register_string( '/misc/whereami', \&whereami_handler, app => 1 );
+DW::Routing->register_string( '/pubkey',        \&pubkey_handler,   app => 1 );
 
 # handles the /misc/whereami page
 sub whereami_handler {
@@ -37,7 +37,7 @@ sub whereami_handler {
         cluster_name => $LJ::CLUSTER_NAME{$rv->{u}->clusterid} || LJ::Lang::ml( '.cluster.unknown' ),
     };
 
-    return DW::Template::Apache2->render_template( 'misc/whereami.tt', $vars );
+    return DW::Template->render_template( 'misc/whereami.tt', $vars );
 }
 
 # handle requests for a user's public key
@@ -49,7 +49,7 @@ sub pubkey_handler {
 
     LJ::load_user_props( $rv->{u}, 'public_key' );
 
-    return DW::Template::Apache2->render_template( 'misc/pubkey.tt', $rv );
+    return DW::Template->render_template( 'misc/pubkey.tt', $rv );
 }
 
 1;
diff -r 4b28bac2991f -r b6ad03cd95b5 cgi-bin/DW/Controller/Nav.pm
--- a/cgi-bin/DW/Controller/Nav.pm	Tue Feb 16 16:05:18 2010 +0000
+++ b/cgi-bin/DW/Controller/Nav.pm	Wed Feb 17 04:45:29 2010 +0000
@@ -19,14 +19,14 @@ use strict;
 use strict;
 use warnings;
 use DW::Controller;
-use DW::Routing::Apache2;
-use DW::Template::Apache2;
+use DW::Routing;
+use DW::Template;
 use DW::Logic::MenuNav;
 use JSON;
 
 # Defines the URL for routing.  I could use register_string( '/nav' ... ) if I didn't want to capture arguments
 # This is an application page, not a user styled page, and the default format is HTML (ie, /nav gives /nav.html)
-DW::Routing::Apache2->register_regex( qr!^/nav(?:/([a-z]*))?$!, \&nav_handler, app => 1 );
+DW::Routing->register_regex( qr!^/nav(?:/([a-z]*))?$!, \&nav_handler, app => 1 );
 
 # handles menu nav pages
 sub nav_handler {
@@ -63,7 +63,7 @@ sub nav_handler {
         $vars->{cat_title} = $menu_nav->[0]->{title} if $cat;
 
         # Now we tell it what template to render and pass in our variables
-        return DW::Template::Apache2->render_template( 'nav.tt', $vars );
+        return DW::Template->render_template( 'nav.tt', $vars );
     } else { 
         # return 404 for an unknown format
         return $r->NOT_FOUND;
diff -r 4b28bac2991f -r b6ad03cd95b5 cgi-bin/DW/Request/Apache2.pm
--- a/cgi-bin/DW/Request/Apache2.pm	Tue Feb 16 16:05:18 2010 +0000
+++ b/cgi-bin/DW/Request/Apache2.pm	Wed Feb 17 04:45:29 2010 +0000
@@ -26,8 +26,6 @@ use Apache2::RequestUtil ();
 use Apache2::RequestUtil ();
 use Apache2::RequestIO ();
 use Apache2::SubProcess ();
-
-use DW::Routing::Apache2;
 
 use fields (
             'r',         # The Apache2::Request object
@@ -218,6 +216,26 @@ sub r {
     return $self->{r};
 }
 
+# calls the method as a handler.
+sub call_response_handler {
+    my DW::Request::Apache2 $self = shift;
+
+    $self->{r}->handler( 'perl-script' );
+    $self->{r}->push_handlers( PerlResponseHandler => $_[0] );
+
+    return Apache2::Const::OK;
+}
+
+# FIXME: Temporary, until BML is gone / converted
+# FIXME: This is only valid from a response handler
+sub call_bml {
+    my DW::Request::Apache2 $self = shift;
+
+    $self->note(bml_filename => $_[0]);
+
+    return Apache::BML::handler($self->{r});
+}
+
 # constants
 sub OK {
     my DW::Request::Apache2 $self = $_[0];
diff -r 4b28bac2991f -r b6ad03cd95b5 cgi-bin/DW/Routing.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Routing.pm	Wed Feb 17 04:45:29 2010 +0000
@@ -0,0 +1,373 @@
+#!/usr/bin/perl
+#
+# DW::Routing
+#
+# Module to allow calling non-BML controller/views.
+#
+# Authors:
+#      Andrea Nall <anall@andreanall.com>
+#      Mark Smith <mark@dreamwidth.org>
+#
+# Copyright (c) 2009-2010 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Routing;
+use strict;
+
+use LJ::ModuleLoader;
+use DW::Template;
+use JSON;
+use DW::Request;
+
+our %string_choices;
+our %regex_choices = (
+    app  => [],
+    ssl  => [],
+    user => []
+);
+
+my $default_content_types = {
+    'html' => "text/html; charset=utf-8",
+    'json' => "application/json; charset=utf-8",
+};
+
+LJ::ModuleLoader->require_subclasses( "DW::Controller" );
+
+=head1 NAME
+
+DW::Routing - Module to allow calling non-BML controller/views.
+
+=head1 SYNOPSIS
+
+=head1 Page Call API
+
+=head2 C<< $class->call( $r, %opts ) >>
+
+=cut
+
+sub call {
+    my $class = shift;
+    my $call_opts = $class->get_call_opts(@_);
+
+    return $class->call_hash( $call_opts ) if defined $call_opts;
+    return undef;
+}
+
+=head2 C<< $class->get_call_opts( $r, %opts ) >>
+
+=cut
+
+sub get_call_opts {
+    my ( $class, %opts ) = @_;
+    my $r = DW::Request->get;
+
+    my ( $uri, $format ) = ( $r->uri, undef );
+    ( $uri, $format ) = ( $1, $2 )
+        if $uri =~ m/^(.+?)\.([a-z]+)$/;
+
+    # add more data to the options hash, we'll need it
+    $opts{role} ||= $opts{ssl} ? 'ssl' : ( $opts{username} ? 'user' : 'app' );
+    $opts{uri}    = $uri;
+    $opts{format} = $format;
+
+    # we construct this object as an easy way to get options later, it gives
+    # us accessors.  FIXME: this should be a separate class, not DW::Routing.
+    my $call_opts = bless( \%opts, $class );
+
+    # try the string options first as they're fast
+    my $hash = $opts{__hash} = $string_choices{$opts{role} . $uri};
+    return $call_opts if defined $hash;
+
+    # try the regex choices next
+    # FIXME: this should be a dynamically sorting array so the most used items float to the top
+    # for now it doesn't matter so much but eventually when everything is in the routing table
+    # that will have to be done
+    my @args;
+    foreach $hash ( @{ $regex_choices{$opts{role}} } ) {
+        if ( ( @args = $uri =~ $hash->{regex} ) ) {
+            $opts{__hash} = $hash;
+            $opts{subpatterns} = \@args;
+            return $call_opts;
+        }
+    }
+
+    # failed to find anything so fall through
+    return undef;
+}
+
+=head2 C<< $class->call_hash( $class, $call_opts ) >>
+
+Calls the raw hash.
+
+=cut
+
+sub call_hash {
+    my ( $class, $opts ) = @_;
+    my $r = DW::Request->get;
+
+    my $hash = $opts->{__hash};
+    return undef unless $hash && $hash->{sub};
+
+    $r->pnote(routing_opts => $opts);
+    return $r->call_response_handler( \&_call_hash );
+}
+
+=head2 C<< $class->_call_hash() >>
+
+Perl Response Handler for call_hash
+
+=cut
+
+sub _call_hash {
+    my $r = DW::Request->get;
+    my $opts = $r->pnote('routing_opts');
+    my $hash = $opts->{__hash};
+
+    $opts->{format} ||= $hash->{format};
+
+    my $format = $opts->{format};
+    $r->content_type( $default_content_types->{$format} )
+        if $default_content_types->{$format};
+
+    # try to call the handler that actually does the content creation; it will
+    # return either a string (valid result), or a number (HTTP code), or undef
+    # means there was an error of some sort
+    my $ret = eval { return $hash->{sub}->( $opts ) };
+    return $ret unless $@;
+
+    # here down is simply error handling for whatever the handler sub above
+    # might have died with
+    my $msg = $@;
+
+    my $err = LJ::errobj( $msg )
+        or die "LJ::errobj didn't return anything.";
+    $err->log;
+
+    # JSON error rendering
+    if ( $format eq 'json' ) {
+        my $text = $LJ::MSG_ERROR || "Sorry, there was a problem.";
+        my $remote = LJ::get_remote();
+        $text = "$msg" if ( $remote && $remote->show_raw_errors ) || $LJ::IS_DEV_SERVER;
+
+        $r->status( 500 );
+        $r->print(objToJson( { error => $text } ));
+        return $r->OK;
+
+    # default error rendering
+    } else {
+        $msg = $err->as_html;
+
+        chomp $msg;
+        $msg .= " \@ $LJ::SERVER_NAME" if $LJ::SERVER_NAME;
+        warn "$msg\n";
+
+        $r->status( 500 );
+        my $text = $LJ::MSG_ERROR || "Sorry, there was a problem.";
+        my $remote = LJ::get_remote();
+        $text = "<b>[Error: $msg]</b>" if ( $remote && $remote->show_raw_errors ) || $LJ::IS_DEV_SERVER;
+        return DW::Template->render_string( $text, { status=>500, content_type=>'text/html' } );
+    }
+}
+
+sub _static_helper {
+    my $r = DW::Request->get;
+    return $r->NOT_FOUND unless $_[0]->format eq 'html';
+    return  DW::Template->render_template( $_[0]->args );
+}
+
+=head1 Registration API
+
+=head2 C<< $class->register_static($string, $filename, $opts) >>
+
+Static page helper.
+
+=over
+
+=item string - path
+
+=item filename - template filename
+
+=item Opts:
+
+=over
+
+=item ssl - If this sub should run for ssl.
+
+=item app - 1 if app
+
+=item user - 1 if user
+
+=back
+
+=back
+
+=cut
+
+sub register_static {
+    my ( $class, $string, $fn, %opts ) = @_;
+
+    $opts{args} = $fn;
+    $class->register_string( $string, \&_static_helper, %opts );
+}
+
+=head2 C<< $class->register_string($string, $sub, $opts) >>
+
+=over
+
+=item string - path
+
+=item sub - sub
+
+=item Opts:
+
+=over
+
+=item ssl - If this sub should run for ssl.
+
+=item args - passed verbatim to sub.
+
+=item app - 1 if app
+
+=item user - 1 if user
+
+=back
+
+=back
+
+=cut
+
+sub register_string {
+    my ( $class, $string, $sub, %opts ) = @_;
+
+    $opts{app} = 1 if ! defined $opts{app} && ! $opts{user};
+    my $hash = {
+        args   => $opts{args},
+        sub    => $sub,
+        ssl    => $opts{ssl} || 0,
+        app    => $opts{app} || 0,
+        user   => $opts{user} || 0,
+        format => $opts{format} || 'html',
+    };
+    $string_choices{'app'  . $string} = $hash if $hash->{app};
+    $string_choices{'ssl'  . $string} = $hash if $hash->{ssl};
+    $string_choices{'user' . $string} = $hash if $hash->{user};
+}
+
+=head2 C<< $class->register_regex($regex, $sub, $opts) >>
+
+=over
+
+=item regex
+
+=item sub - sub
+
+=over
+
+=item Opts:
+
+=over
+
+=item ssl - If this sub should run for ssl.
+
+=item args - passed verbatim to sub.
+
+=item app - 1 if app
+
+=item user - 1 if user
+
+=back
+
+=back
+
+=cut
+sub register_regex {
+    my ( $class, $regex, $sub, %opts ) = @_;
+
+    $opts{app} = 1 if ! defined $opts{app} && !$opts{user};
+    my $hash = {
+        regex  => $regex,
+        args   => $opts{args},
+        sub    => $sub,
+        ssl    => $opts{ssl} || 0,
+        app    => $opts{app} || 0,
+        user   => $opts{user} || 0,
+        format => $opts{format} || 'html',
+    };
+    push @{$regex_choices{app}}, $hash if $hash->{app};
+    push @{$regex_choices{ssl}}, $hash if $hash->{ssl};
+    push @{$regex_choices{user}}, $hash if $hash->{user};
+}
+
+=head1 Controller API
+
+API to be used from the controllers.
+
+=head2 C<< $self->args >>
+
+Return the arguments passed to the register call.
+
+=cut
+
+sub args { return $_[0]->{__hash}->{args}; }
+
+=head2 C<< $self->format >>
+
+Return the format.
+
+=cut
+
+sub format { return $_[0]->{format}; }
+
+=head2 C<< $self->role >>
+
+Current mode: 'app' or 'user' or 'ssl'
+
+=cut
+
+sub role { return $_[0]->{role}; }
+
+=head2 C<< $self->ssl >>
+
+Is SSL request?
+
+=cut
+
+sub ssl { return $_[0]->{role} eq 'ssl' ? 1 : 0; }
+
+=head2 C<< $self->subpatterns >>
+
+Return the regex matches.
+
+=cut
+
+sub subpatterns { return $_[0]->{subpatterns}; }
+
+=head2 C<< $self->username >>
+
+Username
+
+=cut
+
+sub username { return $_[0]->{username}; }
+
+=head1 AUTHOR
+
+=item Andrea Nall <anall@andreanall.com>
+
+=item Mark Smith <mark@dreamwidth.org>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2009-2010 by Dreamwidth Studios, LLC.
+
+This program is free software; you may redistribute it and/or modify it under
+the same terms as Perl itself. For a copy of the license, please reference
+'perldoc perlartistic' or 'perldoc perlgpl'.
+
+=cut
+
+1;
diff -r 4b28bac2991f -r b6ad03cd95b5 cgi-bin/DW/Routing/Apache2.pm
--- a/cgi-bin/DW/Routing/Apache2.pm	Tue Feb 16 16:05:18 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,367 +0,0 @@
-#!/usr/bin/perl
-#
-# DW::Routing::Apache2
-#
-# Module to allow calling non-BML controller/views.
-#
-# Authors:
-#      Andrea Nall <anall@andreanall.com>
-#      Mark Smith <mark@dreamwidth.org>
-#
-# Copyright (c) 2009 by Dreamwidth Studios, LLC.
-#
-# This program is free software; you may redistribute it and/or modify it under
-# the same terms as Perl itself.  For a copy of the license, please reference
-# 'perldoc perlartistic' or 'perldoc perlgpl'.
-#
-
-package DW::Routing::Apache2;
-use strict;
-
-use LJ::ModuleLoader;
-use DW::Template::Apache2;
-use JSON;
-
-# FIXME: This shouldn't depend on Apache, but I'm using it here as I need to do a few calls
-#        that aren't supported by DW::Request, as well as it's needed in DW::Template.
-use Apache2::Const qw/ :common REDIRECT HTTP_NOT_MODIFIED
-                       HTTP_MOVED_PERMANENTLY HTTP_MOVED_TEMPORARILY
-                       M_TRACE M_OPTIONS /;
-
-my %string_choices;
-my %regex_choices = (
-    app  => [],
-    ssl  => [],
-    user => []
-);
-
-my $default_content_types = {
-    'html' => "text/html; charset=utf-8",
-    'json' => "application/json; charset=utf-8",
-};
-
-LJ::ModuleLoader->autouse_subclasses( "DW::Controller" );
-
-=head1 NAME
-
-DW::Routing::Apache2 - Module to allow calling non-BML controller/views.
-
-=head1 SYNOPSIS
-
-=head1 Page Call API
-
-=head2 C<< $class->call( $r, %opts ) >>
-
-=cut
-
-sub call {
-    my ( $class, $r, %opts ) = @_;
-
-    my ( $uri, $format ) = ( $r->uri, undef );
-    ( $uri, $format ) = ( $1, $2 )
-        if $uri =~ m/^(.+?)\.([a-z]+)$/;
-
-    # add more data to the options hash, we'll need it
-    $opts{mode}   = $opts{ssl} ? 'ssl' : ( $opts{username} ? 'user' : 'app' );
-    $opts{uri}    = $uri;
-    $opts{format} = $format;
-    $opts{__r}    = $r;
-
-    # we construct this object as an easy way to get options later, it gives
-    # us accessors.  FIXME: this should be a separate class, not DW::Routing.
-    my $call_opts = bless( \%opts, $class );
-
-    # try the string options first as they're fast
-    my $hash = $opts{__hash} = $string_choices{$opts{mode} . $uri};
-    return $class->call_hash( $call_opts ) if defined $hash;
-
-    # try the regex choices next
-    # FIXME: this should be a dynamically sorting array so the most used items float to the top
-    # for now it doesn't matter so much but eventually when everything is in the routing table
-    # that will have to be done
-    my @args;
-    foreach $hash ( @{ $regex_choices{$opts{mode}} } ) {
-        if ( ( @args = $uri =~ $hash->{regex} ) ) {
-            $opts{__hash} = $hash;
-            $opts{subpatterns} = \@args;
-            return $class->call_hash( $call_opts );
-        }
-    }
-
-    # failed to find anything so fall through
-    return undef;
-}
-
-=head2 C<< $class->call_hash( $class, $call_opts ) >>
-
-Calls the raw hash.
-
-=cut
-
-sub call_hash {
-    my ( $class, $opts ) = @_;
-
-    my $hash = $opts->{__hash};
-    return undef unless $hash && $hash->{sub} && $opts->{__r};
-
-    $opts->{__r}->handler( 'perl-script' );
-    $opts->{__r}->pnotes->{routing_opts} = $opts;
-    $opts->{__r}->push_handlers( PerlResponseHandler => \&_call_hash );
-
-    return OK;
-}
-
-=head2 C<< $class->_call_hash( $r ) >>
-
-Perl Response Handler for call_hash
-
-=cut
-
-sub _call_hash {
-    my ( $r ) = @_;
-    my $opts = $r->pnotes->{routing_opts};
-    my $hash = $opts->{__hash};
-
-    $opts->{format} ||= $hash->{format};
-
-    my $format = $opts->{format};
-    $r->content_type( $default_content_types->{$format} )
-        if $default_content_types->{$format};
-
-    # try to call the handler that actually does the content creation; it will
-    # return either a string (valid result), or a number (HTTP code), or undef
-    # means there was an error of some sort
-    my $ret = eval { return $hash->{sub}->( $opts ) };
-    return $ret unless $@;
-
-    # here down is simply error handling for whatever the handler sub above
-    # might have died with
-    my $msg = $@;
-
-    my $err = LJ::errobj( $msg )
-        or die "LJ::errobj didn't return anything.";
-    $err->log;
-
-    # JSON error rendering
-    if ( $format eq 'json' ) {
-        my $text = $LJ::MSG_ERROR || "Sorry, there was a problem.";
-        my $remote = LJ::get_remote();
-        $text = "$msg" if ( $remote && $remote->show_raw_errors ) || $LJ::IS_DEV_SERVER;
-
-        $r->status( 500 );
-        $r->print(objToJson( { error => $text } ));
-        return OK;
-
-    # default error rendering
-    } else {
-        $msg = $err->as_html;
-
-        chomp $msg;
-        $msg .= " \@ $LJ::SERVER_NAME" if $LJ::SERVER_NAME;
-        warn "$msg\n";
-
-        $r->status( 500 );
-        my $text = $LJ::MSG_ERROR || "Sorry, there was a problem.";
-        my $remote = LJ::get_remote();
-        $text = "<b>[Error: $msg]</b>" if ( $remote && $remote->show_raw_errors ) || $LJ::IS_DEV_SERVER;
-        return DW::Template::Apache2->render_string( $r, $text, { status=>500, content_type=>'text/html' } );
-    }
-}
-
-sub _static_helper {
-    return NOT_FOUND unless $_[0]->format eq 'html';
-    return $_[0]->render_template( $_[0]->args );
-}
-
-=head1 Registration API
-
-=head2 C<< $class->register_static($string, $filename, $opts) >>
-
-Static page helper.
-
-=over
-
-=item string - path
-
-=item filename - template filename
-
-=item Opts:
-
-=over
-
-=item ssl - If this sub should run for ssl.
-
-=item app - 1 if app
-
-=item user - 1 if user
-
-=back
-
-=back
-
-=cut
-
-sub register_static {
-    my ( $class, $string, $fn, %opts ) = @_;
-
-    $opts{args} = $fn;
-    $class->register_string( $string, \&_static_helper, %opts );
-}
-
-=head2 C<< $class->register_string($string, $sub, $opts) >>
-
-=over
-
-=item string - path
-
-=item sub - sub
-
-=item Opts:
-
-=over
-
-=item ssl - If this sub should run for ssl.
-
-=item args - passed verbatim to sub.
-
-=item app - 1 if app
-
-=item user - 1 if user
-
-=back
-
-=back
-
-=cut
-
-sub register_string {
-    my ( $class, $string, $sub, %opts ) = @_;
-
-    $opts{app} = 1 if ! defined $opts{app} && ! $opts{user};
-    my $hash = {
-        args   => $opts{args},
-        sub    => $sub,
-        ssl    => $opts{ssl} || 0,
-        app    => $opts{app} || 0,
-        user   => $opts{user} || 0,
-        format => $opts{format} || 'html',
-    };
-    $string_choices{'app'  . $string} = $hash if $hash->{app};
-    $string_choices{'ssl'  . $string} = $hash if $hash->{ssl};
-    $string_choices{'user' . $string} = $hash if $hash->{user};
-}
-
-=head2 C<< $class->register_regex($regex, $sub, $opts) >>
-
-=over
-
-=item regex
-
-=item sub - sub
-
-=over
-
-=item Opts:
-
-=over
-
-=item ssl - If this sub should run for ssl.
-
-=item args - passed verbatim to sub.
-
-=item app - 1 if app
-
-=item user - 1 if user
-
-=back
-
-=back
-
-=cut
-sub register_regex {
-    my ( $class, $regex, $sub, %opts ) = @_;
-
-    $opts{app} = 1 if ! defined $opts{app} && !$opts{user};
-    my $hash = {
-        regex  => $regex,
-        args   => $opts{args},
-        sub    => $sub,
-        ssl    => $opts{ssl} || 0,
-        app    => $opts{app} || 0,
-        user   => $opts{user} || 0,
-        format => $opts{format} || 'html',
-    };
-    push @{$regex_choices{app}}, $hash if $hash->{app};
-    push @{$regex_choices{ssl}}, $hash if $hash->{ssl};
-    push @{$regex_choices{user}}, $hash if $hash->{user};
-}
-
-=head1 Controller API
-
-API to be used from the controllers.
-
-=head2 C<< $self->args >>
-
-Return the arguments passed to the register call.
-
-=cut
-
-sub args { return $_[0]->{__hash}->{args}; }
-
-=head2 C<< $self->format >>
-
-Return the format.
-
-=cut
-
-sub format { return $_[0]->{format}; }
-
-=head2 C<< $self->mode >>
-
-Current mode: 'app' or 'user' or 'ssl'
-
-=cut
-
-sub mode { return $_[0]->{mode}; }
-
-=head2 C<< $self->ssl >>
-
-Is SSL request?
-
-=cut
-
-sub ssl { return $_[0]->{mode} eq 'ssl' ? 1 : 0; }
-
-=head2 C<< $self->subpatterns >>
-
-Return the regex matches.
-
-=cut
-
-sub subpatterns { return $_[0]->{subpatterns}; }
-
-=head2 C<< $self->username >>
-
-Username
-
-=cut
-
-sub username { return $_[0]->{username}; }
-
-=head1 AUTHOR
-
-=item Andrea Nall <anall@andreanall.com>
-
-=item Mark Smith <mark@dreamwidth.org>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright (c) 2009 by Dreamwidth Studios, LLC.
-
-This program is free software; you may redistribute it and/or modify it under
-the same terms as Perl itself. For a copy of the license, please reference
-'perldoc perlartistic' or 'perldoc perlgpl'.
-
-=cut
-
-1;
diff -r 4b28bac2991f -r b6ad03cd95b5 cgi-bin/DW/Template.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Template.pm	Wed Feb 17 04:45:29 2010 +0000
@@ -0,0 +1,323 @@
+#!/usr/bin/perl
+#
+# DW::Template
+#
+# Template Toolkit helpers for Apache2.
+#
+# Authors:
+#      Andrea Nall <anall@andreanall.com>
+#
+# Copyright (c) 2009-2010 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Template;
+use strict;
+use Template;
+use Template::Plugins;
+use Template::Namespace::Constants;
+use DW::FragmentCache;
+use DW::Request;
+
+=head1 NAME
+
+DW::Template - Template Toolkit helpers for Apache2.
+
+=head1 SYNOPSIS
+
+=cut 
+
+# setting this to 0 -- have to explicitly specify which plugins we want.
+$Template::Plugins::PLUGIN_BASE = '';
+
+my $site_constants = Template::Namespace::Constants->new({
+    name => $LJ::SITENAME,
+    nameshort => $LJ::SITENAMESHORT,
+    nameabbrev => $LJ::SITENAMEABBREV,
+    company => $LJ::SITECOMPANY,
+});
+
+my $roots_constants = Template::Namespace::Constants->new({
+    site => $LJ::SITEROOT,
+});
+
+# precreating this
+my $view_engine = Template->new({
+    INCLUDE_PATH => "$LJ::HOME/views/",
+    NAMESPACE => {
+        site => $site_constants,
+        roots => $roots_constants,
+    },
+    FILTERS => {
+        ml => [ \&ml, 1 ],
+    },
+    CACHE_SIZE => $LJ::TEMPLATE_CACHE_SIZE, # this can be undef, and that means cache everything.
+    STAT_TTL => $LJ::IS_DEV_SERVER ? 1 : 3600,
+    PLUGINS => {
+        autoformat => 'Template::Plugin::Autoformat',
+        date => 'Template::Plugin::Date',
+        url => 'Template::Plugin::URL',
+    },
+});
+
+=head1 API
+
+=head2 C<< $class->template_string( $filename, $opts ) >>
+
+Render a template to a string.
+
+=cut
+
+sub template_string {
+    my ($class, $filename, $opts) = @_;
+    my $r = DW::Request->get;
+
+    $r->note('ml_scope',"/$filename") unless $r->note('ml_scope');
+
+    my $out;
+    $view_engine->process( $filename, $opts, \$out )
+        or die Template->error();
+
+    return $out;
+}
+
+=head2 C<< $class->cached_template_string( $key, $filename, $subref, $opts, $extra ) >>
+
+Render a template to a string -- optionally fragment caching it.
+$subref returns the options for template_string.
+
+fragment opts:
+
+=over
+
+=item B< lock_failed > - The text returned by this subref is returned if the lock is failed and the grace period is up.
+
+=item B< expire > - Number of seconds the fragment is valid for
+
+=item B< grace_period > - Number of seconds that an expired fragment could still be served if the lock is in place
+
+=back
+
+=cut
+
+sub cached_template_string {
+    my ($class, $key, $filename, $subref, $opts, $extra ) = @_;
+
+    $extra ||= {};
+    $opts->{sections} = $extra;
+    return DW::FragmentCache->get( $key, {
+        lock_failed => $opts->{lock_failed},
+        expire => $opts->{expire},
+        grace_period => $opts->{grace_period},
+        render => sub {
+            return $class->template_string( $filename, $subref->( $_[0] ) );
+        }
+    }, $extra);
+}
+
+=head2 C<< $class->render_cached_template( $key, $filename, $subref, $extra ) >>
+
+Render a template inside the sitescheme or alone.
+
+See render_template, except note that the opts hash is returned by subref if it's needed.
+
+$extra can contain:
+
+=over
+
+=item B< no_sitescheme > == render alone
+
+=item B< title / windowtitle / head / bodyopts / ... > == text to get thrown in the section if inside sitescheme
+
+=item B< content_type > = content type
+
+=item B< status > = HTTP status code
+
+=item B< lock_failed > = subref for lock failed.
+
+=item B< expire > - Number of seconds the fragment is valid for
+
+=item B< grace_period > - Number of seconds that an expired fragment could still be served if the lock is in place
+
+=back
+
+=cut
+
+sub render_cached_template {
+    my ($class, $key, $filename, $subref, $opts, $extra) = @_;
+
+    my $out = $class->cached_template_string( $key, $filename, $subref, $opts, $extra );
+
+    return $class->render_string( $out, $extra );
+}
+
+=head2 C<< $class->render_template( $filename, $opts, $extra ) >>
+
+Render a template inside the sitescheme or alone.
+
+$extra can contain:
+
+=over
+
+=item B< no_sitescheme > == render alone
+
+=item B< title / windowtitle / head / bodyopts / ... > == text to get thrown in the section if inside sitescheme
+
+=item B< content_type > = content type
+
+=item B< status > = HTTP status code
+
+=back
+
+=cut
+
+sub render_template {
+    my ( $class, $filename, $opts, $extra ) = @_;
+
+    $extra ||= {};
+    $opts->{sections} = $extra;
+
+    my $out = $class->template_string( $filename, $opts );
+
+    return $class->render_string( $out, $extra );
+}
+
+=head2 C<< $class->render_string( $string, $extra ) >>
+
+Render a string inside the sitescheme or alone.
+
+$extra can contain:
+
+=over
+
+=item B< no_sitescheme > == render alone
+
+=item B< title / windowtitle / head / bodyopts / ... > == text to get thrown in the section if inside sitescheme
+
+=item B< content_type > = content type
+
+=item B< status > = HTTP status code
+
+=back
+
+=cut
+
+sub render_string {
+    my ( $class, $out, $extra ) = @_;
+
+    my $r = DW::Request->get;
+    $r->status( $extra->{status} ) if $extra->{status};
+    $r->content_type( $extra->{content_type} ) if $extra->{content_type};
+
+    if ( $extra->{no_sitescheme} ) {
+        $r->print( $out );
+
+        return $r->OK;
+    } else {
+        $r->pnote(render_sitescheme_code => $out);
+        $r->pnote(render_sitescheme_extra => $extra || {});
+
+        return $r->call_bml("$LJ::HOME/htdocs/misc/render_sitescheme.bml");
+    }
+}
+
+=head1 ML Stuff
+
+NOTE: All these methods use DW::Template::blah, not DW::Template->blah.
+
+=head2 C<< DW::Template::ml_scope( $scope ) >>
+
+Gets the scope or sets the scope to the given location
+
+=cut
+
+sub ml_scope {
+    return DW::Request->get->note('ml_scope', $_[0]);
+}
+
+=head2 C<< DW::Template::ml( $code, $vars ) >>
+
+=cut
+
+sub ml {
+    # save the last argument as the hashref, hopefully
+    my $args = $_[-1];
+    $args = {} unless $args && ref $args eq 'HASH';
+
+    # we have to return a sub here since we are a dynamic filter
+    return sub {
+        my ( $code ) = @_;
+
+        $code = DW::Request->get->note( 'ml_scope' ) . $code
+            if rindex( $code, '.', 0 ) == 0;
+
+        my $lang = decide_language();
+        return $code if $lang eq 'debug';
+        return LJ::Lang::get_text( $lang, $code, undef, $args );
+    };
+}
+
+sub decide_language {
+    my $r = DW::Request->get;
+    return $r->note( 'ml_lang' ) if $r->note( 'ml_lang' );
+    
+    my $lang = _decide_language();
+    
+    $r->note( 'ml_lang', $lang );
+    return $lang;
+}
+
+sub _decide_language
+{
+    my $r = DW::Request->get;
+
+    my $args = $r->get_args;
+    # GET param 'uselang' takes priority
+    my $uselang = $args->{'uselang'};
+    if ( $uselang eq "debug" || LJ::Lang::get_lang($uselang) ) {
+        return $uselang;
+    }
+
+    # next is their cookie preference
+    #FIXME: COOKIE!
+    #if ($BML::COOKIEIE{'langpref'} =~ m!^(\w{2,10})/(\d+)$!) {
+    #    if (exists $env->{"Langs-$1"}) {
+    #        # FIXME: Probably should actually do this!!!
+    #        # make sure the document says it was changed at least as new as when
+    #        # the user last set their current language, else their browser might
+    #        # show a cached (wrong language) version.
+    #        return $1;
+    #    }
+    #}
+
+    # FIXME: next is their browser's preference
+
+    # next is the default language
+    return $LJ::DEFAULT_LANG || $LJ::LANGS[0];
+
+    # lastly, english.
+    return "en";
+}
+
+=head1 AUTHOR
+
+=over
+
+=item Andrea Nall <anall@andreanall.com>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2009-2010 by Dreamwidth Studios, LLC.
+
+This program is free software; you may redistribute it and/or modify it under
+the same terms as Perl itself. For a copy of the license, please reference
+'perldoc perlartistic' or 'perldoc perlgpl'.
+
+=cut
+
+1;
diff -r 4b28bac2991f -r b6ad03cd95b5 cgi-bin/DW/Template/Apache2.pm
--- a/cgi-bin/DW/Template/Apache2.pm	Tue Feb 16 16:05:18 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,328 +0,0 @@
-#!/usr/bin/perl
-#
-# DW::Template::Apache2
-#
-# Template Toolkit helpers for Apache2.
-#
-# Authors:
-#      Andrea Nall <anall@andreanall.com>
-#
-# Copyright (c) 2009 by Dreamwidth Studios, LLC.
-#
-# This program is free software; you may redistribute it and/or modify it under
-# the same terms as Perl itself.  For a copy of the license, please reference
-# 'perldoc perlartistic' or 'perldoc perlgpl'.
-#
-
-package DW::Template::Apache2;
-use strict;
-use Template;
-use Template::Plugins;
-use Template::Namespace::Constants;
-use DW::FragmentCache;
-
-# FIXME: I cannot use a DW::Request for the Apache::BML::handler call,
-#        so I am only using Apache2 requests here, not mixing the two objects inside the same methods.
-#        Once we dispose of BML, this can switch.
-use Apache2::Const qw/ :common /;
-
-=head1 NAME
-
-DW::Template::Apache2 - Template Toolkit helpers for Apache2.
-
-=head1 SYNOPSIS
-
-=cut 
-
-# setting this to 0 -- have to explicitly specify which plugins we want.
-$Template::Plugins::PLUGIN_BASE = '';
-
-my $site_constants = Template::Namespace::Constants->new({
-    name => $LJ::SITENAME,
-    nameshort => $LJ::SITENAMESHORT,
-    nameabbrev => $LJ::SITENAMEABBREV,
-    company => $LJ::SITECOMPANY,
-});
-
-my $roots_constants = Template::Namespace::Constants->new({
-    site => $LJ::SITEROOT,
-});
-
-# precreating this
-my $view_engine = Template->new({
-    INCLUDE_PATH => "$LJ::HOME/views/",
-    NAMESPACE => {
-        site => $site_constants,
-        roots => $roots_constants,
-    },
-    FILTERS => {
-        ml => [ \&ml, 1 ],
-    },
-    CACHE_SIZE => $LJ::TEMPLATE_CACHE_SIZE, # this can be undef, and that means cache everything.
-    STAT_TTL => $LJ::IS_DEV_SERVER ? 1 : 3600,
-    PLUGINS => {
-        autoformat => 'Template::Plugin::Autoformat',
-        date => 'Template::Plugin::Date',
-        url => 'Template::Plugin::URL',
-    },
-});
-
-=head1 API
-
-=head2 C<< $class->template_string( $filename, $opts ) >>
-
-Render a template to a string.
-
-=cut
-
-sub template_string {
-    my ($class, $filename, $opts) = @_;
-    my $r = DW::Request->get;
-
-    $r->note('ml_scope',"/$filename") unless $r->note('ml_scope');
-
-    my $out;
-    $view_engine->process( $filename, $opts, \$out )
-        or die Template->error();
-
-    return $out;
-}
-
-=head2 C<< $class->cached_template_string( $key, $filename, $subref, $opts, $extra ) >>
-
-Render a template to a string -- optionally fragment caching it.
-$subref returns the options for template_string.
-
-fragment opts:
-
-=over
-
-=item B< lock_failed > - The text returned by this subref is returned if the lock is failed and the grace period is up.
-
-=item B< expire > - Number of seconds the fragment is valid for
-
-=item B< grace_period > - Number of seconds that an expired fragment could still be served if the lock is in place
-
-=back
-
-=cut
-
-sub cached_template_string {
-    my ($class, $key, $filename, $subref, $opts, $extra ) = @_;
-
-    $extra ||= {};
-    $opts->{sections} = $extra;
-    return DW::FragmentCache->get( $key, {
-        lock_failed => $opts->{lock_failed},
-        expire => $opts->{expire},
-        grace_period => $opts->{grace_period},
-        render => sub {
-            return $class->template_string( $filename, $subref->( $_[0] ) );
-        }
-    }, $extra);
-}
-
-=head2 C<< $class->render_cached_template( $key, $filename, $subref, $extra ) >>
-
-Render a template inside the sitescheme or alone.
-
-See render_template, except note that the opts hash is returned by subref if it's needed.
-
-$extra can contain:
-
-=over
-
-=item B< no_sitescheme > == render alone
-
-=item B< title / windowtitle / head / bodyopts / ... > == text to get thrown in the section if inside sitescheme
-
-=item B< content_type > = content type
-
-=item B< status > = HTTP status code
-
-=item B< lock_failed > = subref for lock failed.
-
-=item B< expire > - Number of seconds the fragment is valid for
-
-=item B< grace_period > - Number of seconds that an expired fragment could still be served if the lock is in place
-
-=back
-
-=cut
-
-sub render_cached_template {
-    my ($class, $key, $filename, $subref, $opts, $extra) = @_;
-
-    my $out = $class->cached_template_string( $key, $filename, $subref, $opts, $extra );
-
-    return $class->render_string( $out, $extra );
-}
-
-=head2 C<< $class->render_template( $filename, $opts, $extra ) >>
-
-Render a template inside the sitescheme or alone.
-
-$extra can contain:
-
-=over
-
-=item B< no_sitescheme > == render alone
-
-=item B< title / windowtitle / head / bodyopts / ... > == text to get thrown in the section if inside sitescheme
-
-=item B< content_type > = content type
-
-=item B< status > = HTTP status code
-
-=back
-
-=cut
-
-sub render_template {
-    my ( $class, $filename, $opts, $extra ) = @_;
-
-    $extra ||= {};
-    $opts->{sections} = $extra;
-
-    my $out = $class->template_string( $filename, $opts );
-
-    return $class->render_string( $out, $extra );
-}
-
-=head2 C<< $class->render_string( $string, $extra ) >>
-
-Render a string inside the sitescheme or alone.
-
-$extra can contain:
-
-=over
-
-=item B< no_sitescheme > == render alone
-
-=item B< title / windowtitle / head / bodyopts / ... > == text to get thrown in the section if inside sitescheme
-
-=item B< content_type > = content type
-
-=item B< status > = HTTP status code
-
-=back
-
-=cut
-
-sub render_string {
-    my ( $class, $out, $extra ) = @_;
-
-    my $r = DW::Request->get->r;
-    $r->status( $extra->{status} ) if $extra->{status};
-    $r->content_type( $extra->{content_type} ) if $extra->{content_type};
-
-    if ( $extra->{no_sitescheme} ) {
-        $r->print( $out );
-
-        return OK;
-    } else {
-        $r->pnotes->{render_sitescheme_code} = $out;
-        $r->pnotes->{render_sitescheme_extra} = $extra || {};
-        $r->notes->{bml_filename} = "$LJ::HOME/htdocs/misc/render_sitescheme.bml";
-
-        return Apache::BML::handler($r);
-    }
-}
-
-=head1 ML Stuff
-
-NOTE: All these methods use DW::Template::Apache2::blah, not DW::Template::Apache2->blah.
-
-=head2 C<< DW::Template::Apache2::ml_scope( $scope ) >>
-
-Gets the scope or sets the scope to the given location
-
-=cut
-
-sub ml_scope {
-    return DW::Request->get->note('ml_scope', $_[0]);
-}
-
-=head2 C<< DW::Template::Apache2::ml( $code, $vars ) >>
-
-=cut
-
-sub ml {
-    # save the last argument as the hashref, hopefully
-    my $args = $_[-1];
-    $args = {} unless $args && ref $args eq 'HASH';
-
-    # we have to return a sub here since we are a dynamic filter
-    return sub {
-        my ( $code ) = @_;
-
-        $code = DW::Request->get->note( 'ml_scope' ) . $code
-            if rindex( $code, '.', 0 ) == 0;
-
-        my $lang = decide_language();
-        return $code if $lang eq 'debug';
-        return LJ::Lang::get_text( $lang, $code, undef, $args );
-    };
-}
-
-sub decide_language {
-    my $r = DW::Request->get;
-    return $r->note( 'ml_lang' ) if $r->note( 'ml_lang' );
-    
-    my $lang = _decide_language();
-    
-    $r->note( 'ml_lang', $lang );
-    return $lang;
-}
-
-sub _decide_language
-{
-    my $r = DW::Request->get;
-
-    my $args = $r->get_args;
-    # GET param 'uselang' takes priority
-    my $uselang = $args->{'uselang'};
-    if ( $uselang eq "debug" || LJ::Lang::get_lang($uselang) ) {
-        return $uselang;
-    }
-
-    # next is their cookie preference
-    #FIXME: COOKIE!
-    #if ($BML::COOKIE{'langpref'} =~ m!^(\w{2,10})/(\d+)$!) {
-    #    if (exists $env->{"Langs-$1"}) {
-    #        # FIXME: Probably should actually do this!!!
-    #        # make sure the document says it was changed at least as new as when
-    #        # the user last set their current language, else their browser might
-    #        # show a cached (wrong language) version.
-    #        return $1;
-    #    }
-    #}
-
-    # FIXME: next is their browser's preference
-
-    # next is the default language
-    return $LJ::DEFAULT_LANG || $LJ::LANGS[0];
-
-    # lastly, english.
-    return "en";
-}
-
-=head1 AUTHOR
-
-=over
-
-=item Andrea Nall <anall@andreanall.com>
-
-=back
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright (c) 2009 by Dreamwidth Studios, LLC.
-
-This program is free software; you may redistribute it and/or modify it under
-the same terms as Perl itself. For a copy of the license, please reference
-'perldoc perlartistic' or 'perldoc perlgpl'.
-
-=cut
-
-1;
diff -r 4b28bac2991f -r b6ad03cd95b5 cgi-bin/LJ/ModuleLoader.pm
--- a/cgi-bin/LJ/ModuleLoader.pm	Tue Feb 16 16:05:18 2010 +0000
+++ b/cgi-bin/LJ/ModuleLoader.pm	Wed Feb 17 04:45:29 2010 +0000
@@ -70,6 +70,16 @@ sub autouse_subclasses {
     }
 }
 
+sub require_subclasses {
+    shift if @_ > 1; # get rid of classname
+    my $base_class = shift;
+
+    foreach my $class (LJ::ModuleLoader->module_subclasses($base_class)) {
+        eval "use $class";
+        die "Error loading $class: $@" if $@;
+    }
+}
+
 sub require_if_exists {
     shift if @_ > 1; # get rid of classname
 
diff -r 4b28bac2991f -r b6ad03cd95b5 t/routing.t
--- a/t/routing.t	Tue Feb 16 16:05:18 2010 +0000
+++ b/t/routing.t	Wed Feb 17 04:45:29 2010 +0000
@@ -1,12 +1,11 @@
 # -*-perl-*-
 use strict;
-use Test::More tests => 294;
+use Test::More tests => 174;
 use lib "$ENV{LJHOME}/cgi-bin";
 require 'ljlib.pl';
-use DW::Routing::Apache2;
-use Apache2::Const qw/ :common REDIRECT HTTP_NOT_MODIFIED
-                       HTTP_MOVED_PERMANENTLY HTTP_MOVED_TEMPORARILY
-                       M_TRACE M_OPTIONS /;
+use DW::Request::Standard;
+use HTTP::Request;
+use DW::Routing;
 
 my $result;
 my $expected_format = 'html';
@@ -16,235 +15,215 @@ handle_request( "foo", "/foo.format", 0,
 handle_request( "foo", "/foo.format", 0, 0 ); # 1 test
 # 2
 
-DW::Routing::Apache2->register_string( "/test/app", \&handler, app => 1, args => "it_worked_app" );
+DW::Routing->register_string( "/test/app", \&handler, app => 1, args => "it_worked_app" );
 
 $expected_format = 'html';
-handle_request( "/test app (app)" , "/test/app", 1, "it_worked_app" ); # 6 tests
+handle_request( "/test app (app)" , "/test/app", 1, "it_worked_app" ); # 3 tests
 handle_request( "/test app (ssl)" , "/test/app", 0, "it_worked_app", ssl => 1 ); # 1 test
 handle_request( "/test app (user)", "/test/app", 0, "it_worked_app", username => 'test' ); # 1 test
-# 10
+# 7
 
 $expected_format = 'format';
-handle_request( "/test app (app)" , "/test/app.format", 1, "it_worked_app" ); # 6 tests
+handle_request( "/test app (app)" , "/test/app.format", 1, "it_worked_app" ); # 3 tests
 handle_request( "/test app (ssl)" , "/test/app.format", 0, "it_worked_app", ssl => 1 ); # 1 test
 handle_request( "/test app (user)", "/test/app.format", 0, "it_worked_app", username => 'test' ); # 1 test
-# 18
+# 12
 
-DW::Routing::Apache2->register_string( "/test/ssl", \&handler, ssl => 1, app => 0, args => "it_worked_ssl" );
+DW::Routing->register_string( "/test/ssl", \&handler, ssl => 1, app => 0, args => "it_worked_ssl" );
 
 $expected_format = 'html';
 handle_request( "/test ssl (app)" , "/test/ssl", 0, "it_worked_ssl" ); # 1 tests
 handle_request( "/test ssl (ssl)" , "/test/ssl", 1, "it_worked_ssl", ssl => 1 ); # 1 test
-handle_request( "/test ssl (user)", "/test/ssl", 0, "it_worked_ssl", username => 'test' ); # 6 tests
-# 26
+handle_request( "/test ssl (user)", "/test/ssl", 0, "it_worked_ssl", username => 'test' ); # 3 tests
+# 17
 
 $expected_format = 'format';
 handle_request( "/test ssl (app)" , "/test/ssl.format", 0, "it_worked_ssl" ); # 1 tests
 handle_request( "/test ssl (ssl)" , "/test/ssl.format", 1, "it_worked_ssl", ssl => 1 ); # 1 test
-handle_request( "/test ssl (user)", "/test/ssl.format", 0, "it_worked_ssl", username => 'test' ); # 6 tests
-# 34
+handle_request( "/test ssl (user)", "/test/ssl.format", 0, "it_worked_ssl", username => 'test' ); # 3 tests
+# 22
 
-DW::Routing::Apache2->register_string( "/test/user", \&handler, user => 1, args => "it_worked_user" );
+DW::Routing->register_string( "/test/user", \&handler, user => 1, args => "it_worked_user" );
 
 $expected_format = 'html';
 handle_request( "/test user (app)" , "/test/user", 0, "it_worked_user" ); # 1 tests
 handle_request( "/test user (ssl)" , "/test/user", 0, "it_worked_user", ssl => 1 ); # 1 test
-handle_request( "/test user (user)", "/test/user", 1, "it_worked_user", username => 'test' ); # 6 tests
-# 42
+handle_request( "/test user (user)", "/test/user", 1, "it_worked_user", username => 'test' ); # 3 tests
+# 27
 
 $expected_format = 'format';
 handle_request( "/test user (app)" , "/test/user.format", 0, "it_worked_user" ); # 1 tests
 handle_request( "/test user (ssl)" , "/test/user.format", 0, "it_worked_user", ssl => 1 ); # 1 test
-handle_request( "/test user (user)", "/test/user.format", 1, "it_worked_user", username => 'test' ); # 6 tests
+handle_request( "/test user (user)", "/test/user.format", 1, "it_worked_user", username => 'test' ); # 3 tests
+# 32
+
+DW::Routing->register_string( "/test", \&handler, app => 1, args => "it_worked_app" );
+DW::Routing->register_string( "/test", \&handler, ssl => 1, app => 0, args => "it_worked_ssl" );
+DW::Routing->register_string( "/test", \&handler, user => 1, args => "it_worked_user" );
+
+$expected_format = 'html';
+handle_request( "/test multi (app)" , "/test", 1, "it_worked_app" ); # 3 tests
+handle_request( "/test multi (ssl)" , "/test", 1, "it_worked_ssl", ssl => 1 ); # 3 tests
+handle_request( "/test multi (user)", "/test", 1, "it_worked_user", username => 'test' ); # 3 tests
+# 41
+
+$expected_format = 'format';
+handle_request( "/test multi (app)" , "/test.format", 1, "it_worked_app" ); # 3 tests
+handle_request( "/test multi (ssl)" , "/test.format", 1, "it_worked_ssl", ssl => 1 ); # 3 tests
+handle_request( "/test multi (user)", "/test.format", 1, "it_worked_user", username => 'test' ); # 3 tests
 # 50
 
-DW::Routing::Apache2->register_string( "/test", \&handler, app => 1, args => "it_worked_app" );
-DW::Routing::Apache2->register_string( "/test", \&handler, ssl => 1, app => 0, args => "it_worked_ssl" );
-DW::Routing::Apache2->register_string( "/test", \&handler, user => 1, args => "it_worked_user" );
+DW::Routing->register_string( "/test/all", \&handler, app => 1, user => 1, ssl => 1, format => 'json', args => "it_worked_multi" );
+
+$expected_format = 'json';
+handle_request( "/test all (app)" , "/test/all", 1, "it_worked_multi"); # 3 tests
+handle_request( "/test all (ssl)" , "/test/all", 1, "it_worked_multi", ssl => 1 ); # 3 tests
+handle_request( "/test all (user)", "/test/all", 1, "it_worked_multi", username => 'test' ); # 3 tests
+# 59
+
+$expected_format = 'format';
+handle_request( "/test all (app)" , "/test/all.format", 1, "it_worked_multi"); # 3 tests
+handle_request( "/test all (ssl)" , "/test/all.format", 1, "it_worked_multi", ssl => 1 ); # 3 tests
+handle_request( "/test all (user)", "/test/all.format", 1, "it_worked_multi", username => 'test' ); # 3 tests
+# 68
+
+DW::Routing->register_regex( qr !^/r/app(/.+)$!, \&regex_handler, app => 1, args => ["/test", "it_worked_app"] );
 
 $expected_format = 'html';
-handle_request( "/test multi (app)" , "/test", 1, "it_worked_app" ); # 6 tests
-handle_request( "/test multi (ssl)" , "/test", 1, "it_worked_ssl", ssl => 1 ); # 6 tests
-handle_request( "/test multi (user)", "/test", 1, "it_worked_user", username => 'test' ); # 6 tests
-# 68
+handle_request( "/r/app (app)" , "/r/app/test", 1, "it_worked_app" ); # 3 tests
+handle_request( "/r/app (ssl)" , "/r/app/test", 0, "it_worked_app", ssl => 1 ); # 1 test
+handle_request( "/r/app (user)", "/r/app/test", 0, "it_worked_app", username => 'test' ); # 1 test
+# 74
 
 $expected_format = 'format';
-handle_request( "/test multi (app)" , "/test.format", 1, "it_worked_app" ); # 6 tests
-handle_request( "/test multi (ssl)" , "/test.format", 1, "it_worked_ssl", ssl => 1 ); # 6 tests
-handle_request( "/test multi (user)", "/test.format", 1, "it_worked_user", username => 'test' ); # 6 tests
-# 86
-
-DW::Routing::Apache2->register_string( "/test/all", \&handler, app => 1, user => 1, ssl => 1, format => 'json', args => "it_worked_multi" );
-
-$expected_format = 'json';
-handle_request( "/test all (app)" , "/test/all", 1, "it_worked_multi"); # 6 tests
-handle_request( "/test all (ssl)" , "/test/all", 1, "it_worked_multi", ssl => 1 ); # 6 tests
-handle_request( "/test all (user)", "/test/all", 1, "it_worked_multi", username => 'test' ); # 6 tests
-# 104
-
-$expected_format = 'format';
-handle_request( "/test all (app)" , "/test/all.format", 1, "it_worked_multi"); # 6 tests
-handle_request( "/test all (ssl)" , "/test/all.format", 1, "it_worked_multi", ssl => 1 ); # 6 tests
-handle_request( "/test all (user)", "/test/all.format", 1, "it_worked_multi", username => 'test' ); # 6 tests
-# 122
-
-DW::Routing::Apache2->register_regex( qr !^/r/app(/.+)$!, \&regex_handler, app => 1, args => ["/test", "it_worked_app"] );
-
-$expected_format = 'html';
-handle_request( "/r/app (app)" , "/r/app/test", 1, "it_worked_app" ); # 6 tests
-handle_request( "/r/app (ssl)" , "/r/app/test", 0, "it_worked_app", ssl => 1 ); # 1 test
-handle_request( "/r/app (user)", "/r/app/test", 0, "it_worked_app", username => 'test' ); # 1 test
-# 130
-
-$expected_format = 'format';
-handle_request( "/r/app (app)" , "/r/app/test.format", 1, "it_worked_app" ); # 6 tests
+handle_request( "/r/app (app)" , "/r/app/test.format", 1, "it_worked_app" ); # 3 tests
 handle_request( "/r/app (ssl)" , "/r/app/test.format", 0, "it_worked_app", ssl => 1 ); # 1 test
 handle_request( "/r/app (user)", "/r/app/test.format", 0, "it_worked_app", username => 'test' ); # 1 test
-# 138
+# 79
 
-DW::Routing::Apache2->register_regex( qr !^/r/ssl(/.+)$!, \&regex_handler, ssl => 1, app => 0, args => ["/test", "it_worked_ssl"] );
+DW::Routing->register_regex( qr !^/r/ssl(/.+)$!, \&regex_handler, ssl => 1, app => 0, args => ["/test", "it_worked_ssl"] );
 
 $expected_format = 'html';
 handle_request( "/r/ssl (app)" , "/r/ssl/test", 0, "it_worked_ssl" ); # 1 tests
-handle_request( "/r/ssl (ssl)" , "/r/ssl/test", 1, "it_worked_ssl", ssl => 1 ); # 6 test
+handle_request( "/r/ssl (ssl)" , "/r/ssl/test", 1, "it_worked_ssl", ssl => 1 ); # 3 tests
 handle_request( "/r/ssl (user)", "/r/ssl/test", 0, "it_worked_ssl", username => 'test' ); # 1 test
-# 146
+# 86
 
 $expected_format = 'format';
 handle_request( "/r/ssl (app)" , "/r/ssl/test.format", 0, "it_worked_ssl" ); # 1 tests
-handle_request( "/r/ssl (ssl)" , "/r/ssl/test.format", 1, "it_worked_ssl", ssl => 1 ); # 6 test
+handle_request( "/r/ssl (ssl)" , "/r/ssl/test.format", 1, "it_worked_ssl", ssl => 1 ); # 3 tests
 handle_request( "/r/ssl (user)", "/r/ssl/test.format", 0, "it_worked_ssl", username => 'test' ); # 1 test
-# 154
+# 92
 
-DW::Routing::Apache2->register_regex( qr !^/r/user(/.+)$!, \&regex_handler, user => 1, args => ["/test", "it_worked_user"] );
+DW::Routing->register_regex( qr !^/r/user(/.+)$!, \&regex_handler, user => 1, args => ["/test", "it_worked_user"] );
 
 $expected_format = 'html';
 handle_request( "/r/user (app)" , "/r/user/test", 0, "it_worked_user" ); # 1 tests
 handle_request( "/r/user (ssl)" , "/r/user/test", 0, "it_worked_user", ssl => 1 ); # 1 test
-handle_request( "/r/user (user)", "/r/user/test", 1, "it_worked_user", username => 'test' ); # 6 test
-# 162
+handle_request( "/r/user (user)", "/r/user/test", 1, "it_worked_user", username => 'test' ); # 3 tests
+# 98
 
 $expected_format = 'format';
 handle_request( "/r/user (app)" , "/r/user/test.format", 0, "it_worked_user" ); # 1 tests
 handle_request( "/r/user (ssl)" , "/r/user/test.format", 0, "it_worked_user", ssl => 1 ); # 1 test
-handle_request( "/r/user (user)", "/r/user/test.format", 1, "it_worked_user", username => 'test' ); # 6 test
-# 170
+handle_request( "/r/user (user)", "/r/user/test.format", 1, "it_worked_user", username => 'test' ); # 3 tests
+# 104
 
-DW::Routing::Apache2->register_regex( qr !^/r/multi(/.+)$!, \&regex_handler, app => 1, args => ["/test", "it_worked_app"] );
-DW::Routing::Apache2->register_regex( qr !^/r/multi(/.+)$!, \&regex_handler, ssl => 1, app => 0, args => ["/test", "it_worked_ssl"] );
-DW::Routing::Apache2->register_regex( qr !^/r/multi(/.+)$!, \&regex_handler, user => 1, args => ["/test", "it_worked_user"] );
+DW::Routing->register_regex( qr !^/r/multi(/.+)$!, \&regex_handler, app => 1, args => ["/test", "it_worked_app"] );
+DW::Routing->register_regex( qr !^/r/multi(/.+)$!, \&regex_handler, ssl => 1, app => 0, args => ["/test", "it_worked_ssl"] );
+DW::Routing->register_regex( qr !^/r/multi(/.+)$!, \&regex_handler, user => 1, args => ["/test", "it_worked_user"] );
 
 $expected_format = 'html';
-handle_request( "/r/multi (app)" , "/r/multi/test", 1, "it_worked_app" ); # 6 test
-handle_request( "/r/multi (ssl)" , "/r/multi/test", 1, "it_worked_ssl", ssl => 1 ); # 6 test
-handle_request( "/r/multi (user)", "/r/multi/test", 1, "it_worked_user", username => 'test' ); # 6 test
-# 188
+handle_request( "/r/multi (app)" , "/r/multi/test", 1, "it_worked_app" ); # 3 tests
+handle_request( "/r/multi (ssl)" , "/r/multi/test", 1, "it_worked_ssl", ssl => 1 ); # 3 tests
+handle_request( "/r/multi (user)", "/r/multi/test", 1, "it_worked_user", username => 'test' ); # 3 tests
+# 116
 
 $expected_format = 'format';
-handle_request( "/r/multi (app)" , "/r/multi/test.format", 1, "it_worked_app" ); # 6 tests
-handle_request( "/r/multi (ssl)" , "/r/multi/test.format", 1, "it_worked_ssl", ssl => 1 ); # 6 test
-handle_request( "/r/multi (user)", "/r/multi/test.format", 1, "it_worked_user", username => 'test' ); # 6 test
-# 206
+handle_request( "/r/multi (app)" , "/r/multi/test.format", 1, "it_worked_app" ); # 3 tests
+handle_request( "/r/multi (ssl)" , "/r/multi/test.format", 1, "it_worked_ssl", ssl => 1 ); # 3 tests
+handle_request( "/r/multi (user)", "/r/multi/test.format", 1, "it_worked_user", username => 'test' ); # 3 tests
+# 128
 
-DW::Routing::Apache2->register_regex( qr !^/r/all(/.+)$!, \&regex_handler, app => 1, user => 1, ssl => 1, format => 'json', args => ["/test", "it_worked_all"] );
+DW::Routing->register_regex( qr !^/r/all(/.+)$!, \&regex_handler, app => 1, user => 1, ssl => 1, format => 'json', args => ["/test", "it_worked_all"] );
 
 $expected_format = 'json';
-handle_request( "/r/all (app)" , "/r/all/test", 1, "it_worked_all" ); # 6 test
-handle_request( "/r/all (ssl)" , "/r/all/test", 1, "it_worked_all", ssl => 1 ); # 6 test
-handle_request( "/r/all (user)", "/r/all/test", 1, "it_worked_all", username => 'test' ); # 6 test
-# 224
+handle_request( "/r/all (app)" , "/r/all/test", 1, "it_worked_all" ); # 3 tests
+handle_request( "/r/all (ssl)" , "/r/all/test", 1, "it_worked_all", ssl => 1 ); # 3 tests
+handle_request( "/r/all (user)", "/r/all/test", 1, "it_worked_all", username => 'test' ); # 3 tests
+# 140
 
 $expected_format = 'format';
-handle_request( "/r/all (app)" , "/r/all/test.format", 1, "it_worked_all" ); # 6 tests
-handle_request( "/r/all (ssl)" , "/r/all/test.format", 1, "it_worked_all", ssl => 1 ); # 6 test
-handle_request( "/r/all (user)", "/r/all/test.format", 1, "it_worked_all", username => 'test' ); # 6 test
-# 242
+handle_request( "/r/all (app)" , "/r/all/test.format", 1, "it_worked_all" ); # 3 tests
+handle_request( "/r/all (ssl)" , "/r/all/test.format", 1, "it_worked_all", ssl => 1 ); # 3 tests
+handle_request( "/r/all (user)", "/r/all/test.format", 1, "it_worked_all", username => 'test' ); # 3 tests
+# 152
 
-DW::Routing::Apache2->register_string( "/test/app_implicit", \&handler, args => "it_worked_app" );
+DW::Routing->register_string( "/test/app_implicit", \&handler, args => "it_worked_app" );
 
 $expected_format = 'html';
-handle_request( "/test appapp_implicit (app)" , "/test/app_implicit", 1, "it_worked_app" ); # 6 tests
+handle_request( "/test appapp_implicit (app)" , "/test/app_implicit", 1, "it_worked_app" ); # 3 tests
 handle_request( "/test appapp_implicit (ssl)" , "/test/app_implicit", 0, "it_worked_app", ssl => 1 ); # 1 test
 handle_request( "/test appapp_implicit (user)", "/test/app_implicit", 0, "it_worked_app", username => 'test' ); # 1 test
-# 250
+# 157
 
 $expected_format = 'format';
-handle_request( "/test appapp_implicit (app)" , "/test/app_implicit.format", 1, "it_worked_app" ); # 6 tests
+handle_request( "/test appapp_implicit (app)" , "/test/app_implicit.format", 1, "it_worked_app" ); # 3 tests
 handle_request( "/test appapp_implicit (ssl)" , "/test/app_implicit.format", 0, "it_worked_app", ssl => 1 ); # 1 test
 handle_request( "/test appapp_implicit (user)", "/test/app_implicit.format", 0, "it_worked_app", username => 'test' ); # 1 test
-# 258
+# 162
 
-DW::Routing::Apache2->register_regex( qr !^/r/app_implicit(/.+)$!, \&regex_handler, args => ["/test", "it_worked_app"] );
+DW::Routing->register_regex( qr !^/r/app_implicit(/.+)$!, \&regex_handler, args => ["/test", "it_worked_app"] );
 
 $expected_format = 'html';
-handle_request( "/r/app_implicit (app)" , "/r/app_implicit/test", 1, "it_worked_app" ); # 6 tests
+handle_request( "/r/app_implicit (app)" , "/r/app_implicit/test", 1, "it_worked_app" ); # 3 tests
 handle_request( "/r/app_implicit (ssl)" , "/r/app_implicit/test", 0, "it_worked_app", ssl => 1 ); # 1 test
 handle_request( "/r/app_implicit (user)", "/r/app_implicit/test", 0, "it_worked_app", username => 'test' ); # 1 test
-# 266
+# 168
 
 $expected_format = 'format';
-handle_request( "/r/app_implicit (app)" , "/r/app_implicit/test.format", 1, "it_worked_app" ); # 6 tests
+handle_request( "/r/app_implicit (app)" , "/r/app_implicit/test.format", 1, "it_worked_app" ); # 3 tests
 handle_request( "/r/app_implicit (ssl)" , "/r/app_implicit/test.format", 0, "it_worked_app", ssl => 1 ); # 1 test
 handle_request( "/r/app_implicit (user)", "/r/app_implicit/test.format", 0, "it_worked_app", username => 'test' ); # 1 test
-# 274
+# 174
 
+use Data::Dumper;
 sub handle_request {
     my ( $name, $uri, $valid, $expected, %opts ) = @_;
-    my $r = DummyRequest->new( $uri );
+
+    $DW::Request::determined = 0;
+    $DW::Request::cur_req = undef;
+
+    my $req = HTTP::Request->new(GET=>"$uri");
+    my $r = DW::Request::Standard->new($req);
+
     $result = undef;
     $__name = $name;
 
-    my $ret = DW::Routing::Apache2->call( $r, %opts );
+    my $ret = DW::Routing->call( %opts );
     if ( ! $valid ) {
         is( $ret, undef, "$name: wrong return" );
         return 1;
     }
-    is( $ret, OK, "$name: wrong return" );
-    if ( ! defined $ret || $ret != OK ) {
-        return 0;
-    }
-    is ( $r->{handler}, 'perl-script', "$name: wrong handler type" );
-    is ( ref $r->{perl_handler}, 'CODE',  "$name: handler missing/incorrect" );
-    if ( ref $r->{perl_handler} ne 'CODE' ) {
-        return;
-    }
-    $ret = $r->{perl_handler}->($r);
-    is( $ret, OK, "$name: wrong return (from perl handler)" );
-    if ( $ret != OK ) {
+
+    is( $ret, $r->OK, "$name: wrong return" );
+    if ( $ret != $r->OK ) {
         return 0;
     }
     is ( $result, $expected, "$name: handler set wrong value.");
 }
 
 sub handler {
+    my $r = DW::Request->get;
     $result = $_[0]->args;
     is ( $_[0]->format, $expected_format, "$__name: format wrong!" );
-    return OK;
+    return $r->OK;
 }
 
 sub regex_handler {
+    my $r = DW::Request->get;
     $result = $_[0]->args->[1];
     is ( $_[0]->format, $expected_format, "$__name: format wrong!" );
     is( $_[0]->subpatterns->[0], $_[0]->args->[0], "$__name: capture wrong!" );
-    return OK;
+    return $r->OK;
 }
-
-# This is sorta hackish, but we need something that pretends to be
-# an Apache2 request enough to at least allow DW::Routing::Apache2 to work
-package DummyRequest;
-
-sub new {
-    my ($class, $uri) = @_;
-    
-    return bless({ uri => $uri, handler => '', perl_handler => undef, pnotes => {}, notes => {} }, $class);
-}
-
-sub uri { return $_[0]->{uri}; }
-sub handler { $_[0]->{handler} = $_[1]; }
-sub pnotes { return $_[0]->{pnotes}; }
-sub notes { return $_[0]->{notes}; }
-sub content_type { }
-sub status { }
-sub push_handlers {
-    $_[0]->{perl_handler} = $_[2] if $_[1] eq 'PerlResponseHandler';
-}
--------------------------------------------------------------------------------

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org