[Jifty-commit] jifty branch, plack, created. 1654b73062cfbd9a0d66f1e2d785accfcf038bb7

Jifty commits jifty-commit at lists.jifty.org
Thu Dec 10 14:20:09 EST 2009


The branch, plack has been created
        at  1654b73062cfbd9a0d66f1e2d785accfcf038bb7 (commit)

- Log -----------------------------------------------------------------
commit 486514c15a99a29a393cc2c8b45cd6c8cf1640e5
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Aug 14 14:43:58 2009 -0400

    Checkpoint

diff --git a/lib/Jifty/Continuation.pm b/lib/Jifty/Continuation.pm
index 44309fb..9cbce3b 100644
--- a/lib/Jifty/Continuation.pm
+++ b/lib/Jifty/Continuation.pm
@@ -63,6 +63,7 @@ use base qw/Class::Accessor::Fast Jifty::Object/;
 
 __PACKAGE__->mk_accessors(qw(id parent
                              request response code
+                             version
                              ));
 
 =head2 new PARAMHASH
@@ -112,7 +113,8 @@ sub new {
                 request  => Jifty::Request->new(),
                 response => Jifty::Response->new(),
                 code     => undef,
-                @_
+                @_,
+                version  => 2,
                );
 
     # We don't want refs
@@ -129,6 +131,11 @@ sub new {
     my $key = Jifty->web->serial . "_" . int(rand(10)) . int(rand(10)) . int(rand(10)) . int(rand(10)) . int(rand(10)) . int(rand(10));
     $self->id($key);
 
+    # Make sure we don't store any of the connection information
+    local $self->request->{env}{"psgi.input"};
+    local $self->request->{env}{"psgi.errors"};
+    local $self->request->{_body_parser}{input_handle} if defined $self->request->{_body_parser};
+
     # Save it into the session
     Jifty->web->session->set_continuation($key => $self);
 
@@ -145,7 +152,7 @@ to ask "are we about to call a continuation?"
 
 sub return_path_matches {
     my $self = shift;
-    my $called_uri = $ENV{'REQUEST_URI'};
+    my $called_uri = Jifty->web->request->uri;
     my $request_path = $self->request->path;
 
     # XXX TODO: WE should be using URI canonicalization
@@ -242,7 +249,12 @@ sub return {
       if $self->code;
 
     # Set the current request to the one in the continuation
-    return Jifty->web->request($self->request->clone);
+    my $input  = Jifty->web->request->env->{"psgi.input"};
+    my $errors = Jifty->web->request->env->{"psgi.errors"};
+    Jifty->web->request($self->request->clone);
+    Jifty->web->request->env->{"psgi.input"}  = $input;
+    Jifty->web->request->env->{"psgi.errors"} = $errors;
+    return Jifty->web->request;
 }
 
 =head2 delete
diff --git a/lib/Jifty/Dispatcher.pm b/lib/Jifty/Dispatcher.pm
index e6e874a..9f16427 100644
--- a/lib/Jifty/Dispatcher.pm
+++ b/lib/Jifty/Dispatcher.pm
@@ -757,14 +757,7 @@ sub _do_abort {
     $self->log->debug("Aborting processing");
     if (@_) {
         # This is the status code
-        my $status = shift;
-        my $apache = Jifty->handler->apache;
-        $apache->header_out(Status => $status);
-        Jifty->handler->send_http_header;
-
-        # The body should just be the status
-        require HTTP::Status;
-        print STDOUT $status, ' ' , HTTP::Status::status_message($status);
+        Jifty->web->response->status( shift );
     }
     $self->_abort;
 }
@@ -866,13 +859,6 @@ sub _do_dispatch {
         $self->_handle_stage('RUN' => 'show');
     }
 
-    # Close the handle down, so the client can go on their merry way
-    unless (Jifty->web->request->is_subrequest) {
-        Jifty->handler->buffer->flush_output;
-        close(STDOUT);
-        $Jifty::SERVER->close_client_sockets if $Jifty::SERVER;
-    }
-
     # Cleanup
     $self->_handle_stage('CLEANUP');
 
@@ -960,7 +946,7 @@ came in with that method.
 sub _match_method {
     my ( $self, $method ) = @_;
     #$self->log->debug("Matching method ".request->request_method." against ".$method);
-    $Request->request_method eq uc($method);
+    $Request->method eq uc($method);
 }
 
 =head2 _match_https
diff --git a/lib/Jifty/Handler.pm b/lib/Jifty/Handler.pm
index 315f2eb..e2d89d5 100644
--- a/lib/Jifty/Handler.pm
+++ b/lib/Jifty/Handler.pm
@@ -12,10 +12,8 @@ Jifty::Handler - Methods related to the finding and returning content
   use Jifty;
   Jifty->new();
 
-  my $handler = Jifty::Handler->handle_request( cgi => $cgi );
-
-  # after each request is handled
-  Jifty::Handler->cleanup_request;
+  my $handler = Jifty::Handler->new;
+  $handler->handle_request( request => HTTP::Engine::Request->new(...) );
 
 =head1 DESCRIPTION
 
@@ -30,27 +28,7 @@ use Jifty::View::Declare::Handler ();
 use Class::Trigger;
 use String::BufferStack;
 
-BEGIN {
-    # Creating a new CGI object breaks FastCGI in all sorts of painful
-    # ways.  So wrap the call and preempt it if we already have one
-    use CGI ();
-
-    # If this file gets reloaded using Module::Refresh, don't do this
-    # magic again, or we'll get infinite recursion
-    unless (CGI->can('__jifty_real_new')) {
-        *CGI::__jifty_real_new = \&CGI::new;
-
-        no warnings qw(redefine);
-        *CGI::new = sub {
-            return Jifty->handler->cgi if Jifty->handler->cgi;
-            CGI::__jifty_real_new(@_);	
-        }
-    }
-};
-
-
-
-__PACKAGE__->mk_accessors(qw(dispatcher _view_handlers cgi apache stash buffer));
+__PACKAGE__->mk_accessors(qw(dispatcher _view_handlers stash buffer));
 
 =head2 new
 
@@ -133,44 +111,22 @@ sub view {
     return $self->_view_handlers->{$class};
 }
 
-=head2 cgi
-
-Returns the L<CGI> object for the current request, or C<undef> if
-there is none.
-
-=head2 apache
-
-Returns the L<HTML::Mason::FakeApache> or L<Apache> object for the
-current request, ot C<undef> if there is none.
-
 =head2 handle_request
 
 When your server processs (be it Jifty-internal, FastCGI or anything
 else) wants to handle a request coming in from the outside world, you
 should call C<handle_request>.
 
-=over
-
-=item cgi
-
-A L<CGI> object that your server has already set up and loaded with
-your request's data.
-
-=back
-
 =cut
 
-
 sub handle_request {
     my $self = shift;
-    my %args = (
-        cgi => undef,
-        @_
-    );
+    my $req = Plack::Request->new(shift);
+    my $response;
 
     $self->setup_view_handlers() unless $self->_view_handlers;
 
-    $self->call_trigger('before_request', $args{cgi});
+    $self->call_trigger('before_request', $req);
 
     # this is scoped deeper because we want to make sure everything is cleaned
     # up for the LeakDetector plugin. I tried putting the triggers in the
@@ -187,17 +143,15 @@ sub handle_request {
             Jifty::I18N->refresh;
         }
 
-        $self->cgi( $args{cgi} );
-        $self->apache( HTML::Mason::FakeApache->new( cgi => $self->cgi ) );
-
-        Jifty->web->request( Jifty::Request->new()->fill( $self->cgi ) );
+        Jifty->web->request( Jifty::Request->promote( $req ) );
         Jifty->web->response( Jifty::Response->new );
+        Jifty->web->response->status(200);
 
         Jifty->api->reset;
         for ( Jifty->plugins ) {
             $_->new_request;
         }
-        $self->log->info( Jifty->web->request->request_method . " request for " . Jifty->web->request->path  );
+        $self->log->info( Jifty->web->request->method . " request for " . Jifty->web->request->path  );
         Jifty->web->setup_session;
 
         Jifty::I18N->get_language_handle;
@@ -209,30 +163,14 @@ sub handle_request {
             $self->buffer->flush_output;
         } 
 
-        $self->call_trigger('before_cleanup', $args{cgi});
+        $self->call_trigger('before_cleanup', $req);
 
         $self->cleanup_request();
+        $response = Jifty->web->response;
     }
 
-    $self->call_trigger('after_request', $args{cgi});
-}
-
-=head2 send_http_header
-
-Sends any relevent HTTP headers, by calling
-L<HTML::Mason::FakeApache/send_http_header>.  If this is running
-inside a standalone server, also sends the HTTP status header first.
-
-Returns false if the header has already been sent.
-
-=cut
-
-sub send_http_header {
-    my $self = shift;
-    return if $self->apache->http_header_sent;
-    $Jifty::SERVER->send_http_status if $Jifty::SERVER;
-    $self->apache->send_http_header;
-    return 1;
+    $self->call_trigger('after_request', $req);
+    return $response->finalize;
 }
 
 =head2 cleanup_request
@@ -250,8 +188,6 @@ sub cleanup_request {
 
     Jifty->web->session->unload();
     Jifty::Record->flush_cache if Jifty::Record->can('flush_cache');
-    $self->cgi(undef);
-    $self->apache(undef);
     $self->stash(undef);
     $self->buffer->pop for 1 .. $self->buffer->depth;
     $self->buffer->clear;
diff --git a/lib/Jifty/Manual/Cookbook.pod b/lib/Jifty/Manual/Cookbook.pod
index ccc9b40..2afa881 100644
--- a/lib/Jifty/Manual/Cookbook.pod
+++ b/lib/Jifty/Manual/Cookbook.pod
@@ -457,7 +457,7 @@ In a C<Template::Declare> view, do something like this:
         # ...
         # create dynamic $image, for example using Chart::Clicker
 
-        Jifty->handler->apache->content_type('image/png');
+        Jifty->web->response->content_type('image/png');
         Jifty->web->out($image);
     };
 
diff --git a/lib/Jifty/Plugin/CompressedCSSandJS.pm b/lib/Jifty/Plugin/CompressedCSSandJS.pm
index aafcb69..6b28edc 100644
--- a/lib/Jifty/Plugin/CompressedCSSandJS.pm
+++ b/lib/Jifty/Plugin/CompressedCSSandJS.pm
@@ -244,9 +244,9 @@ sub _serve_cas_object {
     my ($self, $name, $incoming_key) = @_;
     my $key = Jifty::CAS->key('ccjs', $name);
 
-    if ( Jifty->handler->cgi->http('If-Modified-Since') and $incoming_key eq $key ) {
+    if ( Jifty->web->request->header('If-Modified-Since') and $incoming_key eq $key ) {
         $self->log->debug("Returning 304 for cached $name");
-        Jifty->handler->apache->header_out( Status => 304 );
+        Jifty->web->response->status( 304 );
         return;
     }
 
@@ -255,16 +255,15 @@ sub _serve_cas_object {
     $compression = 'gzip' if $obj->metadata->{deflate}
       && Jifty::View::Static::Handler->client_accepts_gzipped_content;
 
-    Jifty->handler->apache->content_type($obj->metadata->{content_type});
+    Jifty->web->response->content_type($obj->metadata->{content_type});
     Jifty::View::Static::Handler->send_http_header($compression, length($obj->content));
 
     if ( $compression ) {
         $self->log->debug("Sending gzipped squished $name");
-        binmode STDOUT;
-        print $obj->content_deflated;
+        Jifty->web->out($obj->content_deflated);
     } else {
         $self->log->debug("Sending squished $name");
-        print $obj->content;
+        Jifty->web->out($obj->content);
     }
 }
 
diff --git a/lib/Jifty/Plugin/ErrorTemplates/View.pm b/lib/Jifty/Plugin/ErrorTemplates/View.pm
index 5c9b934..3f5feae 100644
--- a/lib/Jifty/Plugin/ErrorTemplates/View.pm
+++ b/lib/Jifty/Plugin/ErrorTemplates/View.pm
@@ -2,7 +2,6 @@ package Jifty::Plugin::ErrorTemplates::View;
 
 use strict;
 use warnings;
-use vars qw( $r );
 
 use Jifty::View::Declare -base;
 
@@ -81,7 +80,7 @@ caused by the Jifty app's wrapper, for instance.
 
 
 template '__jifty/error/error.css' => sub {
-    Jifty->handler->apache->content_type("text/css");
+    Jifty->web->response->content_type("text/css");
     h1 {
         outs('color: red');
     };
@@ -112,7 +111,7 @@ sub maybe_page (&;$) {
 template '/errors/404' => sub {
     my $file = get('path') || Jifty->web->request->path;
     Jifty->log->error( "404: user tried to get to " . $file );
-    Jifty->handler->apache->header_out( Status => '404' )
+    Jifty->web->response->status( 404 )
         unless Jifty->web->request->is_subrequest;
     maybe_page { title => _("Something's not quite right") } content {
         with( id => "overview" ), div {
diff --git a/lib/Jifty/Plugin/I18N.pm b/lib/Jifty/Plugin/I18N.pm
index c09a39a..0320561 100644
--- a/lib/Jifty/Plugin/I18N.pm
+++ b/lib/Jifty/Plugin/I18N.pm
@@ -82,9 +82,6 @@ sub _i18n_js {
 
         unless ( $current_lang =~ /^$allowed_regex/) {
             $self->log->error("user is requesting $current_lang which is not allowed");
-            my $headers = Jifty->handler->apache->headers_in;
-            use Data::Dumper;
-            $self->log->error(Dumper($headers));
         }
     }
 
diff --git a/lib/Jifty/Plugin/REST/Dispatcher.pm b/lib/Jifty/Plugin/REST/Dispatcher.pm
index cecc1f4..0f270a1 100644
--- a/lib/Jifty/Plugin/REST/Dispatcher.pm
+++ b/lib/Jifty/Plugin/REST/Dispatcher.pm
@@ -58,11 +58,8 @@ Shows basic help about resources and formats available via this RESTian interfac
 =cut
 
 sub show_help {
-    my $apache = Jifty->handler->apache;
+    Jifty->web->response->content_type('text/plain; charset=utf-8');
 
-    $apache->header_out('Content-Type' => 'text/plain; charset=UTF-8');
-    Jifty->handler->send_http_header;
-   
     print qq{
 Accessing resources:
 
@@ -115,10 +112,7 @@ sub show_help_specific {
     my $method = "show_help_specific_$topic";
     __PACKAGE__->can($method) or abort(404);
 
-    my $apache = Jifty->handler->apache;
-
-    $apache->header_out('Content-Type' => 'text/plain; charset=UTF-8');
-    Jifty->handler->send_http_header;
+    Jifty->web->response->content_type('text/plain; charset=utf-8');
 
     print __PACKAGE__->$method;
     last_rule;
@@ -284,12 +278,9 @@ renders the content as yaml, json, javascript, perl, xml or html.
 
 sub outs {
     my $prefix = shift;
-    my $apache = Jifty->handler->apache;
-
     my $format = output_format($prefix);
 
-    $apache->header_out('Content-Type' => $format->{content_type});
-    Jifty->handler->send_http_header;
+    Jifty->web->response->content_type($format->{content_type});
     print $format->{freezer}->(@_);
 
     last_rule;
@@ -821,31 +812,7 @@ sub _dispatch_to_action {
             if defined $rec->id;
     }
     
-    # CGI.pm doesn't handle form encoded data in PUT requests, so we have
-    # to read the request body from PUTDATA and have CGI.pm parse it
-    if ( Jifty->web->request->request_method eq 'PUT'
-        and (   $ENV{'CONTENT_TYPE'} =~ m|^application/x-www-form-urlencoded$|
-              or $ENV{'CONTENT_TYPE'} =~ m|^multipart/form-data$| ) )
-    {
-        my $cgi    = Jifty->handler->cgi;
-        my $length = defined $ENV{'CONTENT_LENGTH'} ? $ENV{'CONTENT_LENGTH'} : 0;
-        my $data = $cgi->param('PUTDATA');
-
-        if ( defined $data ) {
-            my @params = $cgi->all_parameters;
-            $cgi->parse_params( $data );
-            push @params, $cgi->all_parameters;
-            
-            my %seen;
-            my @uniq = map { $seen{$_}++ == 0 ? $_ : () } @params;
-
-            # Add only the newly parsed arguments to the Jifty::Request
-            Jifty->web->request->argument( $_ => $cgi->param( $_ ) )
-                for @uniq;
-        }
-    }
-
-    Jifty->web->request->request_method('POST');
+    Jifty->web->request->method('POST');
     dispatch "/=/action/$action";
 }
 
@@ -979,7 +946,8 @@ sub run_action {
 
         my $url = Jifty->web->url(path => $path);
 
-        Jifty->handler->apache->header_out('Location' => $url);
+        Jifty->web->response->status( 302 );
+        Jifty->web->response->header('Location' => $url);
     }
 
     outs(undef, $action->result->as_hash);
diff --git a/lib/Jifty/Plugin/SkeletonApp/View.pm b/lib/Jifty/Plugin/SkeletonApp/View.pm
index 6824f43..ce839e0 100644
--- a/lib/Jifty/Plugin/SkeletonApp/View.pm
+++ b/lib/Jifty/Plugin/SkeletonApp/View.pm
@@ -2,7 +2,6 @@ package Jifty::Plugin::SkeletonApp::View;
 
 use strict;
 use warnings;
-use vars qw( $r );
 
 use Jifty::View::Declare -base;
 
@@ -48,7 +47,7 @@ template '__jifty/empty' => sub :Static {
 
 private template 'header' => sub {
     my ($title) = get_current_attr(qw(title));
-    Jifty->handler->apache->content_type('text/html; charset=utf-8');
+    Jifty->web->response->content_type('text/html; charset=utf-8');
     head { 
         with(
             'http-equiv' => "content-type",
diff --git a/lib/Jifty/Plugin/TestServerWarnings/View.pm b/lib/Jifty/Plugin/TestServerWarnings/View.pm
index 69ff727..c9c1f9e 100644
--- a/lib/Jifty/Plugin/TestServerWarnings/View.pm
+++ b/lib/Jifty/Plugin/TestServerWarnings/View.pm
@@ -19,7 +19,7 @@ client.
 
 template "/__jifty/test_warnings" => sub {
     my $plugin = Jifty->find_plugin('Jifty::Plugin::TestServerWarnings');
-    Jifty->handler->apache->content_type("application/x-perl");
+    Jifty->web->response->content_type("application/x-perl");
     outs_raw($plugin->encoded_warnings);
 };
 
diff --git a/lib/Jifty/Plugin/ViewDeclarePage/Page.pm b/lib/Jifty/Plugin/ViewDeclarePage/Page.pm
index fa8dbc7..dd3b788 100644
--- a/lib/Jifty/Plugin/ViewDeclarePage/Page.pm
+++ b/lib/Jifty/Plugin/ViewDeclarePage/Page.pm
@@ -272,7 +272,7 @@ sub render_header {
     $self->render_doctype;
 
     head {
-        Jifty->handler->apache->content_type('text/html; charset=utf-8');
+        Jifty->web->response->content_type('text/html; charset=utf-8');
         with(
             'http-equiv' => "content-type",
             content      => "text/html; charset=utf-8"
diff --git a/lib/Jifty/Request.pm b/lib/Jifty/Request.pm
index 89af7d8..49ae763 100644
--- a/lib/Jifty/Request.pm
+++ b/lib/Jifty/Request.pm
@@ -3,8 +3,17 @@ use strict;
 
 package Jifty::Request;
 
-use base qw/Jifty::Object Class::Accessor::Fast/;
-__PACKAGE__->mk_accessors(qw(_top_request arguments template_arguments just_validating path continuation_id future_continuation_id continuation_type continuation_path request_method));
+use Any::Moose;
+extends 'Plack::Request', 'Jifty::Object';
+
+has '_top_request' => (is => 'rw');
+has 'arguments' => (is => 'rw');
+has 'template_arguments' => (is => 'rw');
+has 'just_validating' => (is => 'rw');
+has 'continuation_id' => (is => 'rw');
+has 'future_continuation_id' => (is => 'rw');
+has 'continuation_type' => (is => 'rw');
+has 'continuation_path' => (is => 'rw');
 
 use Jifty::JSON;
 use Jifty::YAML;
@@ -64,7 +73,7 @@ independent fragments.  See L<Jifty::Web::PageRegion>.
 
 =head1 METHODS
 
-=head2 new PARAMHASH
+=head2 BUILD PARAMHASH
 
 Creates a new request object.  For each key in the I<PARAMHASH>, the
 method of that name is called, with the I<PARAMHASH>'s value as its
@@ -72,23 +81,20 @@ sole argument.
 
 =cut
 
-sub new {
-    my $class = shift;
-    my $self = bless {}, $class;
+sub BUILD {
+    my $self = shift;
+
+    # Copy a bunch of information off of the top Plack request
+    my $env = Jifty->web->request->top_request->env;
+    $self->{env}{$_} = $env->{$_} for qw/psgi.version psgi.multithread psgi.multiprocess psgi.errors/;
+    # Stub in an empty input filehandle
+    $self->{env}{"psgi.input"} = Plack::Util::inline_object( read => sub {0} );
 
     $self->{'actions'} = {};
     $self->{'state_variables'} = {};
     $self->{'fragments'} = {};
     $self->arguments({});
     $self->template_arguments({});
-    $self->request_method("GET");
-
-    my %args = @_;
-    for (keys %args) {
-        $self->$_($args{$_}) if $self->can($_);
-    }
-
-    return $self;
 }
 
 =head2 clone
@@ -103,39 +109,47 @@ sub clone {
     # "Semi-shallow" clone
     return bless({map {
         my $val = $self->{$_};
-        $_ => (ref($val) ? { %$val } : $val);
+        $_ => (ref($val) eq "HASH" ? { %$val } : ref($val) eq "ARRAY" ? [ @$val ] : $val);
     } keys %$self}, ref($self));
 }
 
-=head2 fill
+=head2 promote
 
 Attempt to fill in the request from any number of various methods --
-YAML, JSON, etc.  Falls back to query parameters.  Takes a CGI object.
+YAML, JSON, etc.  Falls back to query parameters.  Takes a
+L<HTTP::Engine::Request> object.
 
 =cut
 
-sub fill {
-    my $self = shift;
-    my ($cgi) = @_;
+sub promote {
+    my $class = shift;
+    my ($req) = @_;
 
-    # Store away request method
-    $self->request_method( uc $cgi->request_method );
+    die Carp::longmess("old calling style") unless ref $req;
+
+    # Import all props from HTTP::Engine::Request object
+    my $self = bless $req, $class;
+    $self->{'actions'} = {};
+    $self->{'state_variables'} = {};
+    $self->{'fragments'} = {};
+    $self->arguments({});
+    $self->template_arguments({});
 
     # Grab content type and posted data, if any
-    my $ct   = $ENV{"CONTENT_TYPE"};
-    my $data = $cgi->param('POSTDATA');
+    my $ct   = $req->content_type;
+    my $data = $req->raw_body;
 
     # Check it for something appropriate
     if ($data) {
         if ($ct =~ m{^text/x-json}) {
-            return $self->from_data_structure(eval{Jifty::JSON::jsonToObj($data)}, $cgi);
+            return $self->from_data_structure(eval{Jifty::JSON::jsonToObj($data)});
         } elsif ($ct =~ m{^text/x-yaml}) {
-            return $self->from_data_structure(eval{Jifty::YAML::Load($data)}, $cgi);
+            return $self->from_data_structure(eval{Jifty::YAML::Load($data)});
         }
     }
 
-    # Fall back on using the mason args
-    return $self->from_cgi($cgi);
+    # Fall back on using the straight HTTP arguments
+    return $self->from_args;
 }
 
 =head2 from_data_structure
@@ -151,21 +165,11 @@ Returns itself.
 sub from_data_structure {
     my $self = shift;
     my $data = shift;
-    my $cgi;
-    $cgi = shift if (@_);
 
     my $path = $data->{'path'};
-    
-    if ($cgi && ! $path) {
-        $path = $cgi->path_info;
-        $path =~ s/\?.*//;
-    };
-
-    if (!$path) {
-        $path = '/';
-    }
+    $path ||= $self->path || '/';
 
-    $self->path( Jifty::Util->canonicalize_path( $path));
+    $self->path( Jifty::Util->canonicalize_path( $path ) );
     $self->just_validating( $data->{validating} ) if $data->{validating};
 
     if ( ref $data->{continuation} eq "HASH" ) {
@@ -188,10 +192,7 @@ sub from_data_structure {
             for my $arg ( keys %{ $a->{fields} || {} } ) {
                 if ( ref $a->{fields}{$arg} ) {
 
-                    # Double-fallback exists for historical reasons only;
-                    # Jifty applications after July 10th, 2006 should
-                    # never generate them.
-                    for my $type (qw/doublefallback fallback value/) {
+                    for my $type (qw/fallback value/) {
                         $arguments{$arg} = $a->{fields}{$arg}{$type}
                             if exists $a->{fields}{$arg}{$type};
                     }
@@ -244,34 +245,27 @@ sub from_data_structure {
     return $self;
 }
 
-=head2 from_cgi CGI
+=head2 from_args REQ
 
-Calls C<from_webform> with the CGI's parameters, after doing Mason
-parameter mapping, and splitting C<|>'s in argument names.  See
-L</argument munging>.
+Calls C<from_webform> with the L<HTTP::Engine::Request/parameters>
+after splitting C<|>'s in argument names.  See L</argument munging>.
 
 Returns itself.
 
 =cut
 
-sub from_cgi {
+sub from_args {
     my $self = shift;
-    my ($cgi) = @_;
 
-    my $path = $cgi->path_info;
-    $path =~ s/\?.*//;
-    $self->path( $path );
-
-    use HTML::Mason::Utils;
-    my %args = HTML::Mason::Utils::cgi_request_args( $cgi, $cgi->request_method );
+    my %args = %{ $self->parameters };
 
     # Either CGI.pm or HTML::Mason should really deal with encoding for us.
     for my $k (keys %args) {
         my $val = $args{$k};
         if(ref($val) && ref($val) eq 'ARRAY') {
-            $args{$k} = [map {Jifty::I18N->promote_encoding($_, $ENV{CONTENT_TYPE})} @$val];
+            $args{$k} = [map {Jifty::I18N->promote_encoding($_, $self->content_type)} @$val];
         } elsif(!ref($val)) {
-            $args{$k} = Jifty::I18N->promote_encoding($val, $ENV{CONTENT_TYPE});
+            $args{$k} = Jifty::I18N->promote_encoding($val, $self->content_type);
         }
 
         if (ref($val) eq 'Fh') {
@@ -286,8 +280,6 @@ sub from_cgi {
             # If your key has a '=', you may just lose
             my ($k, $v) = split /=/, $newarg, 2;
             $args{$k} = $v;
-            # The following breaks page regions and the like, sadly:
-            #$args{$k} ? (ref $args{$k} ? [@{$args{$k}},$v] : [$args{$k}, $v] ) : $v;
         }
     }
     return $self->from_webform( %args );
@@ -505,9 +497,7 @@ sub webform_to_data_structure {
 
 
     # Mapping from argument types to data structure names;
-    # Double-fallback exists for historical reasons only; Jifty
-    # applications after July 10th, 2006 should never generate them.
-    my %types = ("J:A:F:F:F" => "doublefallback", "J:A:F:F" => "fallback", "J:A:F" => "value");
+    my %types = ("J:A:F:F" => "fallback", "J:A:F" => "value");
 
     # The "sort" here is key; it ensures that action registrations
     # come before action arguments
@@ -965,9 +955,20 @@ sub top_request {
     return $self->_top_request || $self;
 }
 
+no Any::Moose;
+__PACKAGE__->meta->make_immutable;
+
+
 package Jifty::Request::Action;
-use base 'Class::Accessor::Fast';
-__PACKAGE__->mk_accessors( qw/moniker arguments class order active modified has_run/);
+use Any::Moose;
+
+has 'moniker';
+has 'arguments';
+has 'class';
+has 'order';
+has 'active';
+has 'modified';
+has 'has_run';
 
 =head2 Jifty::Request::Action
 
@@ -1010,9 +1011,18 @@ sub delete {
 }
 
 
+no Any::Moose;
+__PACKAGE__->meta->make_immutable;
+
+
 package Jifty::Request::StateVariable;
-use base 'Class::Accessor::Fast';
-__PACKAGE__->mk_accessors (qw/key value/);
+use Any::Moose;
+
+has 'key';
+has 'value';
+
+no Any::Moose;
+__PACKAGE__->meta->make_immutable;
 
 =head2 Jifty::Request::StateVariable
 
@@ -1025,8 +1035,17 @@ A small package that encapsulates the bits of a state variable:
 =cut
 
 package Jifty::Request::Fragment;
-use base 'Class::Accessor::Fast';
-__PACKAGE__->mk_accessors( qw/name path wrapper in_form arguments parent/ );
+use Any::Moose;
+
+has 'name';
+has 'path';
+has 'wrapper';
+has 'in_form';
+has 'arguments';
+has 'parent';
+
+no Any::Moose;
+__PACKAGE__->meta->make_immutable;
 
 =head2 Jifty::Request::Fragment
 
diff --git a/lib/Jifty/Response.pm b/lib/Jifty/Response.pm
index 6caca4b..e9966b1 100644
--- a/lib/Jifty/Response.pm
+++ b/lib/Jifty/Response.pm
@@ -15,51 +15,10 @@ L<Jifty::Result> objects of each L<Jifty::Action> that ran.
 
 =cut
 
-use base qw/Jifty::Object Class::Accessor::Fast/;
+use Any::Moose;
+extends 'Plack::Response';
 
-__PACKAGE__->mk_accessors(qw(error));
-
-=head2 new
-
-Creates a new L<Jifty::Response> object.
-
-=cut
-
-sub new {
-    my $class = shift;
-    bless {results => {}, headers => []}, $class;
-}
-
-
-=head2 add_header KEY => VALUE
-
-Add an HTTP header to the outgoing HTTP response. 
-
-=cut
-
-
-sub add_header {
-    my $self = shift;
-     Jifty->handler->apache->header_out( @_ ) if Jifty->handler->apache;
-
-    # This one is so we can get jifty's headers into mason
-    # Otherwise we'd have to wrap mason's output layer
-
-    push @{$self->{headers}}, [@_];
-}
-
-=head2 headers
-
-Returns an array of key-value pairs of all the HTTP headers we want to
-stick on the outgoing HTTP request.
-
-
-=cut
-
-sub headers {
-    my $self = shift;
-    return @{$self->{headers}};
-}
+has 'error'   => (is => 'rw');
 
 =head2 result MONIKER [RESULT]
 
@@ -83,7 +42,7 @@ Returns a hash which maps moniker to its L<Jifty::Result>
 
 sub results {
     my $self = shift;
-    return %{$self->{results}};
+    return %{$self->{results} || {}};
 }
 
 =head2 messages
@@ -112,7 +71,7 @@ L</error> set.
 
 sub success {
     my $self = shift;
-    return 0 if grep {$_->failure} values %{$self->{results}};
+    return 0 if grep {$_->failure} values %{$self->{results} || {}};
     return 1;
 }
 
@@ -128,4 +87,6 @@ sub failure {
     return not $self->success;
 }
 
+no Any::Moose;
+__PACKAGE__->meta->make_immutable();
 1;
diff --git a/lib/Jifty/Script/Server.pm b/lib/Jifty/Script/Server.pm
index e603786..dad2d87 100755
--- a/lib/Jifty/Script/Server.pm
+++ b/lib/Jifty/Script/Server.pm
@@ -17,6 +17,7 @@ use Test::Builder ();
 BEGIN { $SIG{__DIE__} = $x;}
 
 
+use HTTP::Engine;
 use File::Path ();
 use Jifty::Util;
 
@@ -170,41 +171,40 @@ sub _run_server {
     Jifty->new();
 
     # Purge stale mason cache data
-    my $data_dir     = Jifty->config->framework('Web')->{'DataDir'};
-    my $server_class = Jifty->config->framework('Web')->{'ServerClass'}
-      || 'Jifty::Server';
-    die "--user option only available with Net::Server subclasses\n"
-      if $self->{user} and $server_class eq "Jifty::Server";
-    die "--group option only available with Net::Server subclasses\n"
-      if $self->{group} and $server_class eq "Jifty::Server";
-    die "--host option only available with Net::Server subclasses\n"
-      if $self->{host} and $server_class eq "Jifty::Server";
-
-    Jifty::Util->require($server_class);
-
+    my $data_dir = Jifty->config->framework('Web')->{'DataDir'};
     File::Path::rmtree( [ "$data_dir/cache", "$data_dir/obj" ] )
-      if Jifty->handler->view('Jifty::View::Mason::Handler')
-          and -d $data_dir;
+        if Jifty->handler->view('Jifty::View::Mason::Handler')
+            and -d $data_dir;
 
-    $SIG{TERM} = sub { exit };
-    mkdir PIDDIR or die "Can't create directory @{[PIDDIR]}: $!"
+    $SIG{TERM} = sub {exit};
+    mkdir PIDDIR
+        or die "Can't create directory @{[PIDDIR]}: $!"
         if !-d PIDDIR;
-    open my $fh, '>', PIDFILE or die "Can't open @{[PIDFILE]} for writing: $!";
+    open my $fh, '>', PIDFILE
+        or die "Can't open @{[PIDFILE]} for writing: $!";
     print $fh $$;
     close $fh;
 
     Jifty->handle->dbh->{Profile} = '6/DBI::ProfileDumper'
-      if $self->{dbiprof};
+        if $self->{dbiprof};
 
     $ENV{JIFTY_SERVER_SIGREADY} ||= $self->{sigready}
-      if $self->{sigready};
-    Log::Log4perl->get_logger($server_class)->less_logging(3)
-      if $self->{quiet};
-    $Jifty::SERVER = $server_class->new( port => $self->{port} );
-    my @args;
-    push @args, $_ => $self->{$_}
-      for grep { exists $self->{$_} } qw/user group host/;
-    $Jifty::SERVER->run(@args);
+        if $self->{sigready};
+
+    Jifty->config->framework('Web')->{'Port'} = $self->{port} if $self->{port};
+    my $port = Jifty->config->framework('Web')->{'Port'} || 8888;
+
+    my %args = ( port => $port );
+    $args{$_} = $self->{$_} for grep defined $self->{$_}, qw/host user group/;
+
+    $Jifty::SERVER = HTTP::Engine->new(
+        interface => {
+            module => 'Standalone',
+            args   => \%args,
+            request_handler => sub { Jifty->handler->handle_request(@_) },
+        },
+    );
+    $Jifty::SERVER->run;
 }
 
 sub _stop {
diff --git a/lib/Jifty/Server.pm b/lib/Jifty/Server.pm
index 7615ab8..29f894b 100644
--- a/lib/Jifty/Server.pm
+++ b/lib/Jifty/Server.pm
@@ -54,8 +54,8 @@ Sets up the Jifty singleton.  This is called automatically by L</new>.
 sub setup_jifty {
     my $self = shift;
     my %args = (
-                port => undef,
-                @_
+        port => undef,
+        @_
     );
 
     Jifty->config->framework('Web')->{'Port'} = $args{port} if $args{port};
@@ -76,16 +76,6 @@ sub handle_request {
     Jifty->handler->handle_request( cgi  => $cgi );
 }
 
-=head2 send_http_status
-
-Sends the HTTP status header.
-
-=cut
-
-sub send_http_status {
-    print STDOUT "HTTP/1.0 ".  (Jifty->handler->apache->{headers_out}->{'Status'} || '200 Jifty OK') .  "\n";
-}
-
 =head2 print_banner
 
 Overrives L<HTML::Server::Simple::Mason>'s print_banner to use the
diff --git a/lib/Jifty/Test/WWW/Mechanize.pm b/lib/Jifty/Test/WWW/Mechanize.pm
index 70da389..e3c8680 100644
--- a/lib/Jifty/Test/WWW/Mechanize.pm
+++ b/lib/Jifty/Test/WWW/Mechanize.pm
@@ -2,6 +2,7 @@ use strict;
 use warnings;
 
 package Jifty::Test::WWW::Mechanize;
+use WWW::Mechanize::HTTPEngineTest;
 use base qw/Test::WWW::Mechanize/;
 
 delete $ENV{'http_proxy'}; # Otherwise Test::WWW::Mechanize tries to go through your HTTP proxy
@@ -40,8 +41,14 @@ sub new {
     my $class = shift;
     my $self = $class->SUPER::new(@_);
     $self->cookie_jar(HTTP::Cookies->new);
+    $self->WWW::Mechanize::HTTPEngineTest::http_engine_hook(
+        uri => Jifty->web->url,
+        handler => sub {
+            Jifty->handler->handle_request(@_);
+        },
+    );
     return $self;
-} 
+}
 
 =head2 moniker_for ACTION, FIELD1 => VALUE1, FIELD2 => VALUE2
 
diff --git a/lib/Jifty/View.pm b/lib/Jifty/View.pm
index 484dc90..34a3da4 100644
--- a/lib/Jifty/View.pm
+++ b/lib/Jifty/View.pm
@@ -35,24 +35,14 @@ sends a header if need be.
 
 sub out_method {
     Jifty->web->session->set_cookie;
-    my $r = Jifty->handler->apache;
+    my $r = Jifty->web->response;
 
     # Send a header
     $r->content_type || $r->content_type('text/html; charset=utf-8'); # Set up a default
-    unless ( $r->http_header_sent or not __PACKAGE__->auto_send_headers ) {
-        Jifty->handler->send_http_header;
-    }
-
-    binmode *STDOUT;
 
     # We now install a new, faster out_method that doesn't have to
     # keep checking whether headers have been sent.
-    my $content;
-    if ( my ($enc) = $r->content_type =~ /charset=([\w-]+)$/ ) {
-        $content = sub { print STDOUT map Encode::encode($enc, $_), @_; };
-    } else {
-        $content = sub { print STDOUT @_; };
-    }
+    my $content = sub { Jifty->web->response->{body} .= $_ for @_ };
     Jifty->handler->buffer->out_method( $content );
     $content->(@_);
 }
diff --git a/lib/Jifty/View/Declare/BaseClass.pm b/lib/Jifty/View/Declare/BaseClass.pm
index e3f6158..8469e17 100644
--- a/lib/Jifty/View/Declare/BaseClass.pm
+++ b/lib/Jifty/View/Declare/BaseClass.pm
@@ -45,7 +45,6 @@ sub use_mason_wrapper {
         my $req = $interp->make_request( comp => '/_elements/wrapper' );
         my $wrapper = $interp->load("/_elements/wrapper");
         local $HTML::Mason::Commands::m = $req;
-        local $HTML::Mason::Commands::r = Jifty->handler->apache;
         $req->comp(
             {content => sub {$code->()}},
             $wrapper,
diff --git a/lib/Jifty/View/Declare/CoreTemplates.pm b/lib/Jifty/View/Declare/CoreTemplates.pm
index fb8fbb8..dec6de5 100644
--- a/lib/Jifty/View/Declare/CoreTemplates.pm
+++ b/lib/Jifty/View/Declare/CoreTemplates.pm
@@ -39,10 +39,9 @@ These templates are still in masonland. we're doign something wrong with escapin
 template '__jifty/subs' => sub {
     my ($forever) = get(qw(forever)) || 1;
 
-    Jifty->handler->apache->content_type("text/html; charset=utf-8");
-    Jifty->handler->apache->headers_out->{'Pragma'}        = 'no-cache';
-    Jifty->handler->apache->headers_out->{'Cache-control'} = 'no-cache';
-    Jifty->handler->send_http_header;
+    Jifty->web->response->content_type("text/html; charset=utf-8");
+    Jifty->web->response->header('Pragma' => 'no-cache');
+    Jifty->web->response->header('Cache-control' => 'no-cache');
 
     my $writer = XML::Writer->new;
     $writer->xmlDecl( "UTF-8", "yes" );
@@ -93,7 +92,7 @@ template '__jifty/autocomplete.xml' => sub {
     # Note: the only point to this file is to set the content_type; the actual
     # behavior is accomplished inside the framework.  It will go away once we
     # have infrastructure for serving things of various content-types.
-    Jifty->handler->apache->content_type('text/xml; charset=UTF-8');
+    Jifty->web->response->content_type('text/xml; charset=utf-8');
     my $ref = Jifty->web->response->result('autocomplete')->content;
     my @options = @{ $ref->{'completions'} || [] };
     body {
@@ -119,7 +118,7 @@ template '__jifty/autocomplete.xml' => sub {
 
 
 template '__jifty/validator.xml' => sub {
-    Jifty->handler->apache->content_type('text/xml; charset=UTF-8');
+    Jifty->web->response->content_type('text/xml; charset=utf-8');
     my $output = "";
     use XML::Writer;
     my $writer = XML::Writer->new( OUTPUT => \$output );
@@ -310,7 +309,7 @@ template '__jifty/webservices/xml' => sub {
     }
 
     $writer->endTag();
-    Jifty->handler->apache->content_type('text/xml; charset=UTF-8');
+    Jifty->web->response->content_type('text/xml; charset=utf-8');
 
     # For some reason, this line is needed, lest we end up outputting ISO-8859-1 text
     utf8::decode($output);
@@ -344,7 +343,7 @@ template '__jifty/webservices/xml' => sub {
 
 
 template '__jifty/webservices/yaml' => sub {
-    Jifty->handler->apache->content_type("text/x-yaml");
+    Jifty->web->response->content_type("text/x-yaml");
     outs( Jifty::YAML::Dump( { Jifty->web->response->results } ) );
 };
 
diff --git a/lib/Jifty/View/Declare/Helpers.pm b/lib/Jifty/View/Declare/Helpers.pm
index f17e99b..6004b1a 100644
--- a/lib/Jifty/View/Declare/Helpers.pm
+++ b/lib/Jifty/View/Declare/Helpers.pm
@@ -100,7 +100,7 @@ sub page (&;$) {
     my ( $meta, $code ) = @_;
     my $ret = sub {
         my $self = shift;
-        Jifty->handler->apache->content_type('text/html; charset=utf-8');
+        Jifty->web->response->content_type('text/html; charset=utf-8');
         my $wrapper = Jifty->app_class('View')->can('wrapper') || \&wrapper;
         my @metadata = $meta ? $meta->($self) : ();
         my $metadata = $#metadata == 0 ? $metadata[0] : {@metadata};
diff --git a/lib/Jifty/View/Mason/Handler.pm b/lib/Jifty/View/Mason/Handler.pm
index 220320a..418ffab 100644
--- a/lib/Jifty/View/Mason/Handler.pm
+++ b/lib/Jifty/View/Mason/Handler.pm
@@ -61,7 +61,6 @@ sub new {
     my $self = $package->SUPER::new( request_class => 'Jifty::View::Mason::Request',
                                      out_method => sub {Carp::cluck("Mason output skipped Jifty's output stack!") if grep {defined and length} @_},
                                      %p );
-    $self->interp->compiler->add_allowed_globals('$r');
     $self->interp->set_escape( h => \&escape_utf8 );
     $self->interp->set_escape( u => \&escape_uri );
 
@@ -212,15 +211,11 @@ sub _comp_setup {
 
     Jifty->web->session->set_cookie;
 
-    # Set up the global
-    my $r = Jifty->handler->apache;
-    $self->interp->set_global('$r', $r);
-
     # XXX FIXME This is a kludge to get use_mason_wrapper to work
     $self->interp->set_global('$jifty_internal_request', 0);
     $self->interp->set_global('$jifty_internal_request', 1) if defined $args;
 
-    return $args ? %$args : $self->request_args($r);
+    return $args ? %$args : $self->request_args;
 }
 
 sub handle_comp {
diff --git a/lib/Jifty/View/Mason/Request.pm b/lib/Jifty/View/Mason/Request.pm
index 7e067aa..04359d2 100644
--- a/lib/Jifty/View/Mason/Request.pm
+++ b/lib/Jifty/View/Mason/Request.pm
@@ -39,7 +39,6 @@ running the component, and we're supposed to send headers, sends them.
 sub exec
 {
     my $self = shift;
-    my $r = Jifty->handler->apache;
     my $retval;
 
     eval { $retval = $self->SUPER::exec(@_) };
@@ -51,14 +50,7 @@ sub exec
                   rethrow_exception $err;
     }
 
-    # On a success code, send headers if they have not been sent and
-    # if we are the top-level request. Since the out_method sends
-    # headers, this will typically only apply after $m->abort.
-    if ($self->auto_send_headers
-        and not $r->http_header_sent
-        and (!$retval or $retval==200)) {
-        Jifty->handler->send_http_header;
-    }
+    return $retval;
 }
 
 =head2 print
diff --git a/lib/Jifty/View/Static/Handler.pm b/lib/Jifty/View/Static/Handler.pm
index 8023737..087977a 100644
--- a/lib/Jifty/View/Static/Handler.pm
+++ b/lib/Jifty/View/Static/Handler.pm
@@ -92,7 +92,7 @@ sub handle_request {
 
     my $local_path = $self->file_path($path) or return undef;
 
-    if ( my $since = Jifty->handler->cgi->http('If-Modified-Since') ) {
+    if ( my $since = Jifty->web->request->header('If-Modified-Since') ) {
         my @file_info = stat($local_path);
 
         # IE appends "; length=N" to If-Modified-Since headers and we need
@@ -124,7 +124,7 @@ Returns true if it looks like the client accepts gzip encoding. Otherwise, retur
 sub client_accepts_gzipped_content {
     my $self = shift;
     no warnings 'uninitialized';
-    return Jifty->handler->cgi->http('Accept-Encoding') =~ /\bgzip\b/;
+    return Jifty->web->request->header('Accept-Encoding') =~ /\bgzip\b/;
 }
 
 
@@ -232,8 +232,7 @@ sub send_file {
         Jifty->web->mason->clear_buffer if Jifty->web->mason;
 
         my @file_info = stat($local_path);
-        my $apache    = Jifty->handler->apache;
-        $apache->content_type($mime_type);
+        Jifty->web->response->content_type($mime_type);
         $self->send_http_header( $compression, $file_info[7], $file_info[9] );
 
         if ( $compression eq 'gzip' ) {
@@ -244,9 +243,8 @@ sub send_file {
             print STDOUT Compress::Zlib::memGzip(<$fh>);
         }
         else {
-            $apache->send_fd($fh);
+            Jifty->web->response->content($fh);
         }
-        close($fh);
         return 1;
     }
     else {
@@ -265,22 +263,20 @@ sub send_http_header {
     my $self = shift;
     my ($compression, $length, $modified) = @_;
     my $now    = time();
-    my $apache = Jifty->handler->apache;
-    $apache->header_out( Status          => 200 );
+    my $response = Jifty->web->response;
+    $response->status( 200 );
 
     # Expire in a year
-    $apache->header_out( 'Cache-Control' => 'max-age=31536000, public' );
-    $apache->header_out( 'Expires' => HTTP::Date::time2str( $now + 31536000 ) );
- 
-    $apache->header_out(
+    $response->header( 'Cache-Control' => 'max-age=31536000, public' );
+    $response->header( 'Expires' => HTTP::Date::time2str( $now + 31536000 ) );
+
+    $response->header(
       'Last-Modified' => HTTP::Date::time2str( $modified ) ) if $modified;
 
-    $apache->header_out( 'Content-Length' => $length )
+    $response->header( 'Content-Length' => $length )
       unless ( $compression eq 'gzip' );
-    $apache->header_out( 'Content-Encoding' => "gzip" )
+    $response->header( 'Content-Encoding' => "gzip" )
       if ( $compression eq 'gzip' );
-
-    Jifty->handler->send_http_header;
 }
 
 
@@ -292,11 +288,9 @@ Sends a "304 Not modified" response to the browser, telling it to use a cached c
 
 sub send_not_modified {
     my $self = shift;
-    my $apache = Jifty->handler->apache;
-    $apache->header_out( Status => 304 );
-    Jifty->handler->send_http_header;
+    my $response = Jifty->web->response;
+    $response->status( 304 );
     return 1;
-
 }
 
 1;
diff --git a/lib/Jifty/Web.pm b/lib/Jifty/Web.pm
index 02f465a..d5593e0 100644
--- a/lib/Jifty/Web.pm
+++ b/lib/Jifty/Web.pm
@@ -106,7 +106,7 @@ sub mason {
 
 =head3 out
 
-Send a string to the browser. The default implementation uses Mason->out;
+Send a string to the browser.
 
 =cut
 
@@ -365,7 +365,7 @@ sub _validate_request_actions {
                         . "'" );
                 $self->log->warn( Jifty->api->explain($request_action->class ) );
                 # Possible cross-site request forgery
-                $self->log->error("Action " . $request_action->class . " has been denied because the request is a GET") if $self->request->request_method eq "GET";
+                $self->log->error("Action " . $request_action->class . " has been denied because the request is a GET") if $self->request->method eq "GET";
                 push @denied_actions, $request_action;
                 next;
             }
@@ -749,7 +749,7 @@ sub redirect {
         # PATH_INFO, which is what $request->path is normally set to.
         # We should replicate that here.
         $request->path( URI::Escape::uri_unescape( $page->url ) );
-        $request->request_method("GET"); # ..effectively.
+        $request->method("GET"); # ..effectively.
         $request->continuation($self->request->continuation);
         my $cont = Jifty::Continuation->new(
             request  => $request,
@@ -793,18 +793,16 @@ sub _redirect {
     # Clear out the output, if any
     Jifty->handler->buffer->clear;
 
-    my $apache = Jifty->handler->apache;
+    my $response = Jifty->web->response;
 
     $self->log->debug("Execing redirect to $page");
     # Headers..
-    $apache->header_out( Location => $page );
-    $apache->header_out( Status => 302 );
+    $response->header( Location => $page );
+    $response->status( 302 );
 
     # cookie has to be sent or returning from continuations breaks
     Jifty->web->session->set_cookie;
 
-    Jifty->handler->send_http_header;
-
     # Mason abort, or dispatcher abort out of here
     $self->mason->abort if $self->mason;
     Jifty::Dispatcher::_abort();
diff --git a/lib/Jifty/Web/Form.pm b/lib/Jifty/Web/Form.pm
index 5913301..7a68dec 100644
--- a/lib/Jifty/Web/Form.pm
+++ b/lib/Jifty/Web/Form.pm
@@ -201,7 +201,7 @@ sub start {
     }
 
     my $root = $self->submit_to;
-    ($root) = $ENV{'REQUEST_URI'} =~ /([^\?]*)/ unless defined $root;
+    ($root) = Jifty->web->request->uri =~ /([^\?]*)/ unless defined $root;
     my $form_start = qq!<form method="post" action="!  . Jifty->web->escape( $root ) . qq!"!;
     $form_start .= qq! name="@{[ $self->name ]}"! if defined $self->name;
     $form_start .= qq! target="@{[ $self->target ]}"! if defined $self->target;
diff --git a/lib/Jifty/Web/Form/Clickable.pm b/lib/Jifty/Web/Form/Clickable.pm
index da26031..ef0572a 100644
--- a/lib/Jifty/Web/Form/Clickable.pm
+++ b/lib/Jifty/Web/Form/Clickable.pm
@@ -155,7 +155,7 @@ get an unexpected error from your browser.
 
 sub new {
     my $class = shift;
-    my ($root) = $ENV{'REQUEST_URI'} =~ /([^\?]*)/;
+    my $root = Jifty->web->request->path;
 
     my %args = (
         parameters => {},
@@ -428,7 +428,7 @@ sub post_parameters {
     my %parameters
         = ( _map( %{ $self->{fallback} || {} } ), $self->parameters );
 
-    my ($root) = $ENV{'REQUEST_URI'} =~ /([^\?]*)/;
+    my $root = Jifty->web->request->request_uri;
 
     # Submit actions should only show up once
     my %uniq;
@@ -479,7 +479,7 @@ sub complete_url {
 
     my %parameters = $self->get_parameters;
 
-    my ($root) = $ENV{'REQUEST_URI'} =~ /([^\?]*)/;
+    my ($root) = Jifty->web->request->request_uri;
     my $url = $self->returns ? $root : $self->url;
     if (%parameters) {
         $url .= ( $url =~ /\?/ ) ? ";" : "?";
diff --git a/lib/Jifty/Web/Form/Link.pm b/lib/Jifty/Web/Form/Link.pm
index e4e064c..c0003f3 100644
--- a/lib/Jifty/Web/Form/Link.pm
+++ b/lib/Jifty/Web/Form/Link.pm
@@ -69,7 +69,7 @@ Any parameter which L<Jifty::Web::Form::Element/new> can take.
 sub new {
     my $class = shift;
     my $args = ref($_[0]) ? $_[0] : {@_};
-    my ($root) = $ENV{'REQUEST_URI'} =~ /([^\?]*)/;
+    my ($root) = Jifty->web->request->uri =~ /([^\?]*)/;
     my $self  = $class->SUPER::new(
       { url          => $root,
         label        => "Click me!",
diff --git a/lib/Jifty/Web/Session.pm b/lib/Jifty/Web/Session.pm
index 320d71c..4415f35 100644
--- a/lib/Jifty/Web/Session.pm
+++ b/lib/Jifty/Web/Session.pm
@@ -315,7 +315,7 @@ sub set_cookie {
 
     # never send a cookie with cached content. misbehaving proxies cause
     # terrific problems
-    return if Jifty->handler->apache->header_out('Expires');
+    return if Jifty->web->response->header('Expires');
 
     my $cookie_name = $self->cookie_name;
     my %cookies     = CGI::Cookie->fetch();
@@ -325,12 +325,10 @@ sub set_cookie {
         -expires => $self->expires,
     );
 
-    # XXX TODO might need to change under mod_perl
     if ( not $cookies{$cookie_name}
         or ( $cookies{$cookie_name} ne $cookie->as_string ) )
     {
-        Jifty->web->response->add_header(
-            'Set-Cookie' => $cookie->as_string );
+        Jifty->web->response->cookies->{$cookie->name} = $cookie;
     }
 }
 
diff --git a/lib/Jifty/Web/Session/ClientSide.pm b/lib/Jifty/Web/Session/ClientSide.pm
index 3a7c873..dc6d986 100644
--- a/lib/Jifty/Web/Session/ClientSide.pm
+++ b/lib/Jifty/Web/Session/ClientSide.pm
@@ -238,9 +238,7 @@ sub flush {
     );
 
     foreach my $cookie ($splitter->split( $data_cookie )) {
-        Jifty->web->response->add_header(
-            'Set-Cookie' => $cookie->as_string
-        );
+        Jifty->web->response->cookies->{$cookie->name} = $cookie;
     }
 }
 
diff --git a/share/web/static/css/autohandler b/share/web/static/css/autohandler
index 4ca73a1..afd5b73 100644
--- a/share/web/static/css/autohandler
+++ b/share/web/static/css/autohandler
@@ -1,5 +1,5 @@
 <%init>
-$r->content_type('text/css');
+Jifty->web->response->content_type('text/css');
 $m->call_next();
 return();
 </%init>
diff --git a/share/web/templates/=/subs b/share/web/templates/=/subs
index 6f41b43..2860b2d 100644
--- a/share/web/templates/=/subs
+++ b/share/web/templates/=/subs
@@ -3,9 +3,9 @@ $forever => 1
 </%args>
 <%init>
 
-$r->content_type("text/html; charset=utf-8");
-$r->headers_out->{'Pragma'}        = 'no-cache';
-$r->headers_out->{'Cache-control'} = 'no-cache';
+Jifty->web->response->content_type("text/html; charset=utf-8");
+Jifty->web->response->header('Pragma' => 'no-cache');
+Jifty->web->response->header('Cache-control' => 'no-cache');
 Jifty->handler->send_http_header;
 
 my $writer = XML::Writer->new;
diff --git a/share/web/templates/__jifty/autocomplete.xml b/share/web/templates/__jifty/autocomplete.xml
index 2a6aaf2..c60d199 100644
--- a/share/web/templates/__jifty/autocomplete.xml
+++ b/share/web/templates/__jifty/autocomplete.xml
@@ -2,7 +2,7 @@
 # Note: the only point to this file is to set the content_type; the actual
 # behavior is accomplished inside the framework.  It will go away once we
 # have infrastructure for serving things of various content-types.
-$r->content_type('text/xml; charset=UTF-8');
+Jifty->web->response->content_type('text/xml; charset=UTF-8');
 unless (Jifty->web->response->result('autocomplete')) {
   print "<body />";
   return;
diff --git a/share/web/templates/__jifty/error/error.css b/share/web/templates/__jifty/error/error.css
index 09a3c41..e59d88a 100644
--- a/share/web/templates/__jifty/error/error.css
+++ b/share/web/templates/__jifty/error/error.css
@@ -3,11 +3,11 @@ h1 {
 }
 
 <%init>
-$r->content_type("text/css");
+Jifty->web->response->content_type("text/css");
 </%init>
 <%doc>
 
 This exists as a fallback CSS, in case the Jifty app's CSS is causing
 the error.
 
-</%doc>
\ No newline at end of file
+</%doc>
diff --git a/share/web/templates/__jifty/validator.xml b/share/web/templates/__jifty/validator.xml
index 6fb4df1..a6eaab2 100644
--- a/share/web/templates/__jifty/validator.xml
+++ b/share/web/templates/__jifty/validator.xml
@@ -1,5 +1,5 @@
 <%init>
-$r->content_type('text/xml; charset=UTF-8');
+Jifty->web->response->content_type('text/xml; charset=UTF-8');
 
 my $output = "";
 use XML::Writer;
diff --git a/share/web/templates/__jifty/webservices/json b/share/web/templates/__jifty/webservices/json
index bacde46..25fd10d 100644
--- a/share/web/templates/__jifty/webservices/json
+++ b/share/web/templates/__jifty/webservices/json
@@ -1,4 +1,4 @@
-% $r->content_type("text/x-json");
+% Jifty->web->response->content_type("text/x-json");
 <% Jifty::JSON::objToJson(\%results) |n%>
 
 <%INIT>
diff --git a/share/web/templates/__jifty/webservices/xml b/share/web/templates/__jifty/webservices/xml
index e4c8d8d..c4b2ae4 100644
--- a/share/web/templates/__jifty/webservices/xml
+++ b/share/web/templates/__jifty/webservices/xml
@@ -1,7 +1,7 @@
 <%init>
 my $output = "";
 my $writer = XML::Writer->new( OUTPUT => \$output, UNSAFE => 1 );
-$r->content_type('text/xml; charset=utf-8');
+Jifty->web->response->content_type('text/xml; charset=utf-8');
 $writer->xmlDecl( "UTF-8", "yes" );
 $writer->startTag("response");
 
@@ -100,7 +100,7 @@ for (keys %results) {
 }
 
 $writer->endTag();
-Jifty->handler->apache->content_type('text/xml; charset=UTF-8');
+Jifty->web->response->content_type('text/xml; charset=UTF-8');
 Jifty->web->out($output);
 </%init>
 <%once>
diff --git a/share/web/templates/__jifty/webservices/yaml b/share/web/templates/__jifty/webservices/yaml
index aba0115..35fda5a 100644
--- a/share/web/templates/__jifty/webservices/yaml
+++ b/share/web/templates/__jifty/webservices/yaml
@@ -1,4 +1,4 @@
-% $r->content_type("text/x-yaml");
+% Jifty->web->response->content_type("text/x-yaml");
 <% Jifty::YAML::Dump(\%results) |n%>
 
 <%INIT>
diff --git a/share/web/templates/_elements/header b/share/web/templates/_elements/header
index b8e97d3..df87efe 100644
--- a/share/web/templates/_elements/header
+++ b/share/web/templates/_elements/header
@@ -13,5 +13,5 @@
 $title => ""
 </%args>
 <%init>
-$r->content_type('text/html; charset=utf-8');
+Jifty->web->response->content_type('text/html; charset=utf-8');
 </%init>

commit 51404abe2622ca1fa87d063a63115caf64c00288
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 1 19:50:04 2009 +0800

    use Plack.

diff --git a/lib/Jifty/Handler.pm b/lib/Jifty/Handler.pm
index e2d89d5..c161a4d 100644
--- a/lib/Jifty/Handler.pm
+++ b/lib/Jifty/Handler.pm
@@ -13,7 +13,7 @@ Jifty::Handler - Methods related to the finding and returning content
   Jifty->new();
 
   my $handler = Jifty::Handler->new;
-  $handler->handle_request( request => HTTP::Engine::Request->new(...) );
+  $handler->handle_request( $env );
 
 =head1 DESCRIPTION
 
@@ -120,8 +120,8 @@ should call C<handle_request>.
 =cut
 
 sub handle_request {
-    my $self = shift;
-    my $req = Plack::Request->new(shift);
+    my ($self, $env) = @_;
+    my $req = Plack::Request->new($env);
     my $response;
 
     $self->setup_view_handlers() unless $self->_view_handlers;
diff --git a/lib/Jifty/Request.pm b/lib/Jifty/Request.pm
index 49ae763..8c9f45b 100644
--- a/lib/Jifty/Request.pm
+++ b/lib/Jifty/Request.pm
@@ -18,6 +18,7 @@ has 'continuation_path' => (is => 'rw');
 use Jifty::JSON;
 use Jifty::YAML;
 use Jifty::Web::FileUpload;
+use Plack::Util ();
 
 =head1 NAME
 
@@ -117,7 +118,7 @@ sub clone {
 
 Attempt to fill in the request from any number of various methods --
 YAML, JSON, etc.  Falls back to query parameters.  Takes a
-L<HTTP::Engine::Request> object.
+L<Plack::Request> object.
 
 =cut
 
@@ -127,7 +128,7 @@ sub promote {
 
     die Carp::longmess("old calling style") unless ref $req;
 
-    # Import all props from HTTP::Engine::Request object
+    # Import all props from Plack::Request object
     my $self = bless $req, $class;
     $self->{'actions'} = {};
     $self->{'state_variables'} = {};
@@ -247,7 +248,7 @@ sub from_data_structure {
 
 =head2 from_args REQ
 
-Calls C<from_webform> with the L<HTTP::Engine::Request/parameters>
+Calls C<from_webform> with the L<Plack::Request/parameters>
 after splitting C<|>'s in argument names.  See L</argument munging>.
 
 Returns itself.
diff --git a/lib/Jifty/Script/Server.pm b/lib/Jifty/Script/Server.pm
index dad2d87..8b75f25 100755
--- a/lib/Jifty/Script/Server.pm
+++ b/lib/Jifty/Script/Server.pm
@@ -17,7 +17,7 @@ use Test::Builder ();
 BEGIN { $SIG{__DIE__} = $x;}
 
 
-use HTTP::Engine;
+use Plack::Loader;
 use File::Path ();
 use Jifty::Util;
 
@@ -197,14 +197,10 @@ sub _run_server {
     my %args = ( port => $port );
     $args{$_} = $self->{$_} for grep defined $self->{$_}, qw/host user group/;
 
-    $Jifty::SERVER = HTTP::Engine->new(
-        interface => {
-            module => 'Standalone',
-            args   => \%args,
-            request_handler => sub { Jifty->handler->handle_request(@_) },
-        },
-    );
-    $Jifty::SERVER->run;
+    my $app = sub { Jifty->handler->handle_request(@_) };
+
+    $Jifty::SERVER = Plack::Loader->load('Standalone', %args);
+    $Jifty::SERVER->run($app);
 }
 
 sub _stop {
diff --git a/lib/Jifty/Test.pm b/lib/Jifty/Test.pm
index ba15ac1..a26cc7f 100644
--- a/lib/Jifty/Test.pm
+++ b/lib/Jifty/Test.pm
@@ -471,7 +471,8 @@ sub make_server {
         unshift @Jifty::Server::ISA, 'Jifty::TestServer::Apache';
     }
     else {
-        unshift @Jifty::Server::ISA, 'Test::HTTP::Server::Simple';
+        require Jifty::TestServer::Plack;
+        unshift @Jifty::Server::ISA, 'Jifty::TestServer::Plack';
     }
 
     my $server = Jifty::Server->new;
diff --git a/lib/Jifty/Test/WWW/Mechanize.pm b/lib/Jifty/Test/WWW/Mechanize.pm
index e3c8680..e15d20a 100644
--- a/lib/Jifty/Test/WWW/Mechanize.pm
+++ b/lib/Jifty/Test/WWW/Mechanize.pm
@@ -2,7 +2,6 @@ use strict;
 use warnings;
 
 package Jifty::Test::WWW::Mechanize;
-use WWW::Mechanize::HTTPEngineTest;
 use base qw/Test::WWW::Mechanize/;
 
 delete $ENV{'http_proxy'}; # Otherwise Test::WWW::Mechanize tries to go through your HTTP proxy
@@ -15,6 +14,7 @@ use HTTP::Cookies;
 use XML::XPath;
 use Hook::LexWrap;
 use List::Util qw(first);
+use Plack::Test;
 use Carp;
 
 # XXX TODO: We're leaving out FLUFF errors because it complains about non-standard
@@ -41,7 +41,7 @@ sub new {
     my $class = shift;
     my $self = $class->SUPER::new(@_);
     $self->cookie_jar(HTTP::Cookies->new);
-    $self->WWW::Mechanize::HTTPEngineTest::http_engine_hook(
+    $self->_plack_hook(
         uri => Jifty->web->url,
         handler => sub {
             Jifty->handler->handle_request(@_);
@@ -50,6 +50,32 @@ sub new {
     return $self;
 }
 
+sub _plack_hook {
+    my $self = shift;
+    my %args = (
+        uri => "http://localhost:8888/",
+        @_
+    );
+
+    die "No handler provided"
+        unless $args{handler};
+
+    my $cb;
+
+    test_psgi
+        app => $args{handler},
+        client => sub {$cb = shift};
+
+    my $for = URI->new( $args{uri} );
+    $self->add_handler(
+        request_send => $cb,
+        m_scheme => $for->scheme,
+        m_host => $for->host,
+        m_port => $for->port,
+        m_path_prefix => $for->path,
+    );
+}
+
 =head2 moniker_for ACTION, FIELD1 => VALUE1, FIELD2 => VALUE2
 
 Finds the moniker of the first action of type I<ACTION> whose

commit fb4925407852593779ee188ddde02f671aa318c4
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 1 20:12:46 2009 +0800

    make sure first constructor of Jifty::Request works.

diff --git a/lib/Jifty/Request.pm b/lib/Jifty/Request.pm
index 8c9f45b..6154585 100644
--- a/lib/Jifty/Request.pm
+++ b/lib/Jifty/Request.pm
@@ -86,10 +86,12 @@ sub BUILD {
     my $self = shift;
 
     # Copy a bunch of information off of the top Plack request
-    my $env = Jifty->web->request->top_request->env;
-    $self->{env}{$_} = $env->{$_} for qw/psgi.version psgi.multithread psgi.multiprocess psgi.errors/;
-    # Stub in an empty input filehandle
-    $self->{env}{"psgi.input"} = Plack::Util::inline_object( read => sub {0} );
+    if ( Jifty->web->request ) {
+        my $env = Jifty->web->request->top_request->env;
+        $self->{env}{$_} = $env->{$_} for qw/psgi.version psgi.multithread psgi.multiprocess psgi.errors/;
+        # Stub in an empty input filehandle
+        $self->{env}{"psgi.input"} = Plack::Util::inline_object( read => sub {0} );
+    }
 
     $self->{'actions'} = {};
     $self->{'state_variables'} = {};

commit a2985fd81bffff430c6327a9c911b114bdc157a2
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 1 20:29:31 2009 +0800

    Mouse is not happy with Jifty::Request::Action attributes without "is"

diff --git a/lib/Jifty/Request.pm b/lib/Jifty/Request.pm
index 6154585..1b86296 100644
--- a/lib/Jifty/Request.pm
+++ b/lib/Jifty/Request.pm
@@ -965,13 +965,13 @@ __PACKAGE__->meta->make_immutable;
 package Jifty::Request::Action;
 use Any::Moose;
 
-has 'moniker';
-has 'arguments';
-has 'class';
-has 'order';
-has 'active';
-has 'modified';
-has 'has_run';
+has 'moniker', is => 'rw';
+has 'arguments', is => 'rw';
+has 'class', is => 'rw';
+has 'order', is => 'rw';
+has 'active', is => 'rw';
+has 'modified', is => 'rw';
+has 'has_run', is => 'rw';
 
 =head2 Jifty::Request::Action
 
@@ -1040,12 +1040,12 @@ A small package that encapsulates the bits of a state variable:
 package Jifty::Request::Fragment;
 use Any::Moose;
 
-has 'name';
-has 'path';
-has 'wrapper';
-has 'in_form';
-has 'arguments';
-has 'parent';
+has 'name', is => 'rw';
+has 'path', is => 'rw';
+has 'wrapper', is => 'rw';
+has 'in_form', is => 'rw';
+has 'arguments', is => 'rw';
+has 'parent', is => 'rw';
 
 no Any::Moose;
 __PACKAGE__->meta->make_immutable;

commit b99dd99497c153646ea85ac545aa57c0317a496f
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 1 20:37:18 2009 +0800

    ignore the restart test

diff --git a/t/TestApp-RestartServer/t/restart.t b/t/TestApp-RestartServer/t/restart.t
index deaae3d..7f44a1a 100644
--- a/t/TestApp-RestartServer/t/restart.t
+++ b/t/TestApp-RestartServer/t/restart.t
@@ -10,6 +10,8 @@ use Cwd;
 my $cwd;
 
 BEGIN {
+    plan skip_all => "disabled for psgi";
+
     plan skip_all => "live test doesn't work on Win32 at the moment" if $^O eq 'MSWin32';
 }
 

commit 10c8294ddf901d34d63731fef40bb5dbc0f7a968
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 1 20:42:59 2009 +0800

    Must use our mechanize, no private LWP::UserAgent in tests.

diff --git a/t/TestApp-Plugin-PasswordAuth/t/12-i18n.t b/t/TestApp-Plugin-PasswordAuth/t/12-i18n.t
index 8cad243..d2afec5 100644
--- a/t/TestApp-Plugin-PasswordAuth/t/12-i18n.t
+++ b/t/TestApp-Plugin-PasswordAuth/t/12-i18n.t
@@ -24,16 +24,15 @@ my $mech = Jifty::Test::WWW::Mechanize->new();
 
 $mech->get_ok("$URL/login","Got login page");
 
-my $ua = LWP::UserAgent->new;
 my $res;
 
-$ua->default_header('Accept-Language' => "en");
-$res = $ua->get("$URL/login");
+$mech->default_header('Accept-Language' => "en");
+$res = $mech->get("$URL/login");
 ok $res->is_success, "can access login page";
 like $res->content, qr/Lost your password/, 'en works';
 
-$ua->default_header('Accept-Language' => "fr");
-$res = $ua->get("$URL/login");
+$mech->default_header('Accept-Language' => "fr");
+$res = $mech->get("$URL/login");
 ok $res->is_success, "can access login page";
 like adjust($res->content), qr/oublié/,'fr login works';
 
diff --git a/t/TestApp/t/i18n-standalone.t b/t/TestApp/t/i18n-standalone.t
index 760917b..69d4dec 100644
--- a/t/TestApp/t/i18n-standalone.t
+++ b/t/TestApp/t/i18n-standalone.t
@@ -17,47 +17,47 @@ isa_ok($server, 'Jifty::Server');
 my $base = URI->new($server->started_ok);
 
 
-my $ua = LWP::UserAgent->new;
+my $mech = Jifty::Test::WWW::Mechanize->new;
 my $res;
 
-$ua->default_header('Accept-Language' => "en");
-$res = $ua->get("$base/__jifty/admin/");
+$mech->default_header('Accept-Language' => "en");
+$res = $mech->get("$base/__jifty/admin/");
 ok $res->is_success, "can access admin console";
 like $res->content, qr/Models/, 'en works';
 
-$res = $ua->get("$base/concrete.html");
+$res = $mech->get("$base/concrete.html");
 ok $res->is_success, "can access concrete";
 like $res->content, qr/2 concrete mixers/, 'en works for an unknown string';
 
-$res = $ua->get("$base/concrete2.html");
+$res = $mech->get("$base/concrete2.html");
 ok $res->is_success, "can access concrete";
 like $res->content, qr/2 concrete mixers/, 'en works for an unknown string';
 
-$ua->default_header('Accept-Language' => "ja");
-$res = $ua->get("$base/__jifty/admin/");
+$mech->default_header('Accept-Language' => "ja");
+$res = $mech->get("$base/__jifty/admin/");
 ok $res->is_success, "can access admin console";
 like adjust($res->content), qr/モデル/, 'ja works';
 
-$res = $ua->get("$base/concrete.html");
+$res = $mech->get("$base/concrete.html");
 ok $res->is_success, "can access concrete";
 like $res->content, qr/2 concrete mixers/, 'ja works for an unknown string';
 
-$res = $ua->get("$base/concrete2.html");
+$res = $mech->get("$base/concrete2.html");
 ok $res->is_success, "can access concrete";
 like $res->content, qr/2 concrete mixers/, 'en works for an unknown string';
 
-$ua->default_header('Accept-Language' => "fr");
-$res = $ua->get("$base/__jifty/admin/");
+$mech->default_header('Accept-Language' => "fr");
+$res = $mech->get("$base/__jifty/admin/");
 ok $res->is_success, "can access admin console";
 like adjust($res->content), qr/Modèles/, 'fr locale works';
 
-$ua->default_header('Accept-Language' => "zh-cn");
-$res = $ua->get("$base/__jifty/admin/");
+$mech->default_header('Accept-Language' => "zh-cn");
+$res = $mech->get("$base/__jifty/admin/");
 ok $res->is_success, "can access admin console";
 like adjust($res->content), qr/数据库/, 'zh-cn works';
 
-$ua->default_header('Accept-Language' => "zh-tw");
-$res = $ua->get("$base/__jifty/admin/");
+$mech->default_header('Accept-Language' => "zh-tw");
+$res = $mech->get("$base/__jifty/admin/");
 ok $res->is_success, "can access admin console";
 like adjust($res->content), qr/資料庫/, 'zh-tw works';
 

commit bb0357401eded6d17563933fc580e4911fd9a918
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 1 20:58:24 2009 +0800

    Make TestServerWarnings work when test client and server are in same process.

diff --git a/lib/Jifty/Plugin/TestServerWarnings.pm b/lib/Jifty/Plugin/TestServerWarnings.pm
index 9740e67..bf39182 100644
--- a/lib/Jifty/Plugin/TestServerWarnings.pm
+++ b/lib/Jifty/Plugin/TestServerWarnings.pm
@@ -124,6 +124,11 @@ sub decoded_warnings {
     my $self = shift;
     my $base = shift;
 
+    my $Test = Jifty::Test->builder;
+    if ($Test->{Original_Pid} == $$) {
+        return splice @{ $self->{'stashed_warnings'} };
+    }
+
     my $uri = URI->new_abs( "/__jifty/test_warnings", $base );
     my $text = LWP::Simple::get($uri);
 

commit 13696fa40a453959791a1e93f9cc514507d98142
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 1 21:28:21 2009 +0800

    Hello, current_user!

diff --git a/Makefile.PL b/Makefile.PL
index e5604e2..c1a1f79 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -12,6 +12,7 @@ requires('Class::Data::Inheritable');
 requires('Class::Trigger' => '0.13');
 requires('Clone' => '0.27');
 requires('CGI' => '3.30');
+requires('CGI::Simple');
 requires('CGI::Cookie::Splitter');
 requires('Class::Inspector' => 1.20); # For File::ShareDir on Win32
 requires('Crypt::CBC');
diff --git a/lib/Jifty/Web/Session.pm b/lib/Jifty/Web/Session.pm
index 4415f35..8ef822e 100644
--- a/lib/Jifty/Web/Session.pm
+++ b/lib/Jifty/Web/Session.pm
@@ -3,7 +3,7 @@ use strict;
 
 package Jifty::Web::Session;
 use base qw/Jifty::Object/;
-use CGI::Cookie ();
+use CGI::Simple::Cookie ();
 use DateTime    ();
 use Storable    ();
 $Storable::Deparse    = 1;
@@ -111,10 +111,11 @@ sub load_by_kv {
 
 sub _get_session_id_from_client {
     my $self        = shift;
-    my %cookies     = CGI::Cookie->fetch();
+    my %cookies     = CGI::Simple::Cookie->parse(Jifty->web->request->env->{HTTP_COOKIE});
     my $cookie_name = $self->cookie_name;
     my $session_id
         = $cookies{$cookie_name} ? $cookies{$cookie_name}->value() : undef;
+    return $session_id;
 }
 
 =head2 unload
@@ -318,8 +319,8 @@ sub set_cookie {
     return if Jifty->web->response->header('Expires');
 
     my $cookie_name = $self->cookie_name;
-    my %cookies     = CGI::Cookie->fetch();
-    my $cookie      = CGI::Cookie->new(
+    my %cookies     = CGI::Simple::Cookie->parse(Jifty->web->request->env->{HTTP_COOKIE});
+    my $cookie      = CGI::Simple::Cookie->new(
         -name    => $cookie_name,
         -value   => $self->id,
         -expires => $self->expires,

commit 8b01a01b8214a8c95228f242f5704b9c8a2a104f
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 1 21:31:17 2009 +0800

    only parse cookie if there is psgi request.

diff --git a/lib/Jifty/Web/Session.pm b/lib/Jifty/Web/Session.pm
index 8ef822e..c7b0f36 100644
--- a/lib/Jifty/Web/Session.pm
+++ b/lib/Jifty/Web/Session.pm
@@ -111,7 +111,7 @@ sub load_by_kv {
 
 sub _get_session_id_from_client {
     my $self        = shift;
-    my %cookies     = CGI::Simple::Cookie->parse(Jifty->web->request->env->{HTTP_COOKIE});
+    my %cookies     = Jifty->web->request ? CGI::Simple::Cookie->parse(Jifty->web->request->env->{HTTP_COOKIE}) : ();
     my $cookie_name = $self->cookie_name;
     my $session_id
         = $cookies{$cookie_name} ? $cookies{$cookie_name}->value() : undef;
@@ -319,7 +319,8 @@ sub set_cookie {
     return if Jifty->web->response->header('Expires');
 
     my $cookie_name = $self->cookie_name;
-    my %cookies     = CGI::Simple::Cookie->parse(Jifty->web->request->env->{HTTP_COOKIE});
+    my %cookies     = Jifty->web->request ? CGI::Simple::Cookie->parse(Jifty->web->request->env->{HTTP_COOKIE}) : ();
+
     my $cookie      = CGI::Simple::Cookie->new(
         -name    => $cookie_name,
         -value   => $self->id,

commit 69ea18b5a6f17ead3a1eb75bc7ed1d89d5c091d6
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 1 21:36:52 2009 +0800

    Jifty::Request::StateVariable attributes fixup.

diff --git a/lib/Jifty/Request.pm b/lib/Jifty/Request.pm
index 1b86296..a5004e7 100644
--- a/lib/Jifty/Request.pm
+++ b/lib/Jifty/Request.pm
@@ -1021,8 +1021,8 @@ __PACKAGE__->meta->make_immutable;
 package Jifty::Request::StateVariable;
 use Any::Moose;
 
-has 'key';
-has 'value';
+has 'key', is => 'rw';
+has 'value', is => 'rw';
 
 no Any::Moose;
 __PACKAGE__->meta->make_immutable;

commit e11539d7e2d785fa94757f3edfdd8e49b9c58977
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Thu Dec 3 15:26:35 2009 +0800

    add testserver::plack

diff --git a/lib/Jifty/TestServer/Plack.pm b/lib/Jifty/TestServer/Plack.pm
new file mode 100644
index 0000000..850a5b1
--- /dev/null
+++ b/lib/Jifty/TestServer/Plack.pm
@@ -0,0 +1,14 @@
+package Jifty::TestServer::Plack;
+use strict;
+use warnings;
+use base 'Test::HTTP::Server::Simple';
+use Test::More;
+
+sub started_ok {
+    my $self = shift;
+    my $port = $self->port;
+    ok(1, "plack test server ok");
+    return "http://localhost:$port";
+}
+
+1;

commit 4d14de5ade9067fb8dfd415d2d5d21efb4fcd6b4
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon Dec 7 17:38:41 2009 -0500

    Add tests to ensure that we didn't enter an infinite redirect loop

diff --git a/t/Continuations/t/01-raw-api.t b/t/Continuations/t/01-raw-api.t
index 82b6b7c..1a8ee41 100644
--- a/t/Continuations/t/01-raw-api.t
+++ b/t/Continuations/t/01-raw-api.t
@@ -9,7 +9,7 @@ Continuations tests
 
 =cut
 
-use Jifty::Test::Dist tests => 47;
+use Jifty::Test::Dist tests => 49;
 
 use_ok('Jifty::Test::WWW::Mechanize');
 
@@ -67,6 +67,8 @@ ok($mech->continuation->response->result("cross")->failure, "Action's result was
 $mech->get("$URL/index-help.html?J:CALL=$first");
 like($mech->uri, qr/index.html/, "Back at original page");
 unlike($mech->uri, qr/J:CALL=$first/, "With new continuation parameter");
+is($mech->status, 200, "Got back happily");
+$mech->content_like(qr/Get help/, "Has content after redirect");
 my $next = $mech->continuation->id;
 
 # Now with return value

commit 2fe6a38dcdf259c0156ac775237c5ad23e9d625f
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon Dec 7 17:39:09 2009 -0500

    ->uri is the full uri, including host; we want request_uri

diff --git a/lib/Jifty/Continuation.pm b/lib/Jifty/Continuation.pm
index 9cbce3b..0ffc3d7 100644
--- a/lib/Jifty/Continuation.pm
+++ b/lib/Jifty/Continuation.pm
@@ -152,7 +152,7 @@ to ask "are we about to call a continuation?"
 
 sub return_path_matches {
     my $self = shift;
-    my $called_uri = Jifty->web->request->uri;
+    my $called_uri = Jifty->web->request->request_uri;
     my $request_path = $self->request->path;
 
     # XXX TODO: WE should be using URI canonicalization

commit e7e6e54e0b40291498caa618577356a3ca524d5f
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Dec 8 01:32:46 2009 -0500

    Restore use of request->request_uri, which is _not_ the same as request->uri

diff --git a/lib/Jifty/Web/Form.pm b/lib/Jifty/Web/Form.pm
index 7a68dec..2f2d26c 100644
--- a/lib/Jifty/Web/Form.pm
+++ b/lib/Jifty/Web/Form.pm
@@ -201,7 +201,7 @@ sub start {
     }
 
     my $root = $self->submit_to;
-    ($root) = Jifty->web->request->uri =~ /([^\?]*)/ unless defined $root;
+    ($root) = Jifty->web->request->request_uri =~ /([^\?]*)/ unless defined $root;
     my $form_start = qq!<form method="post" action="!  . Jifty->web->escape( $root ) . qq!"!;
     $form_start .= qq! name="@{[ $self->name ]}"! if defined $self->name;
     $form_start .= qq! target="@{[ $self->target ]}"! if defined $self->target;
diff --git a/lib/Jifty/Web/Form/Clickable.pm b/lib/Jifty/Web/Form/Clickable.pm
index ef0572a..eda8295 100644
--- a/lib/Jifty/Web/Form/Clickable.pm
+++ b/lib/Jifty/Web/Form/Clickable.pm
@@ -155,7 +155,7 @@ get an unexpected error from your browser.
 
 sub new {
     my $class = shift;
-    my $root = Jifty->web->request->path;
+    my ($root) = Jifty->web->request->request_uri =~ /([^\?]*)/;
 
     my %args = (
         parameters => {},
@@ -428,7 +428,7 @@ sub post_parameters {
     my %parameters
         = ( _map( %{ $self->{fallback} || {} } ), $self->parameters );
 
-    my $root = Jifty->web->request->request_uri;
+    my ($root) = Jifty->web->request->request_uri =~ /([^\?]*)/;
 
     # Submit actions should only show up once
     my %uniq;
@@ -479,7 +479,7 @@ sub complete_url {
 
     my %parameters = $self->get_parameters;
 
-    my ($root) = Jifty->web->request->request_uri;
+    my ($root) = Jifty->web->request->request_uri =~ /([^\?]*)/;
     my $url = $self->returns ? $root : $self->url;
     if (%parameters) {
         $url .= ( $url =~ /\?/ ) ? ";" : "?";
diff --git a/lib/Jifty/Web/Form/Link.pm b/lib/Jifty/Web/Form/Link.pm
index c0003f3..3c0c94e 100644
--- a/lib/Jifty/Web/Form/Link.pm
+++ b/lib/Jifty/Web/Form/Link.pm
@@ -69,7 +69,7 @@ Any parameter which L<Jifty::Web::Form::Element/new> can take.
 sub new {
     my $class = shift;
     my $args = ref($_[0]) ? $_[0] : {@_};
-    my ($root) = Jifty->web->request->uri =~ /([^\?]*)/;
+    my ($root) = Jifty->web->request->request_uri =~ /([^\?]*)/;
     my $self  = $class->SUPER::new(
       { url          => $root,
         label        => "Click me!",

commit 7efa8c4e889fc50ab22a03e6353c8632e2450d26
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 8 15:28:55 2009 +0800

    Disable gzip support as send_file calls print STDOUT.

diff --git a/lib/Jifty/View/Static/Handler.pm b/lib/Jifty/View/Static/Handler.pm
index 087977a..ecea375 100644
--- a/lib/Jifty/View/Static/Handler.pm
+++ b/lib/Jifty/View/Static/Handler.pm
@@ -104,7 +104,10 @@ sub handle_request {
     }
     my $mime_type = $self->mime_type($local_path);
 
-    if ( $self->client_accepts_gzipped_content and $mime_type =~ m!^(text/|application/x-javascript)! ) {
+    # XXX: gzipped sendfile is printing to STDOUT.
+    # port this to psgi or plack::app::file.
+    # gzip should be a separate middleware as well.
+    if ( 0 && $self->client_accepts_gzipped_content and $mime_type =~ m!^(text/|application/x-javascript)! ) {
         return $self->send_file($local_path, $mime_type, 'gzip');
     } else {
         return $self->send_file($local_path, $mime_type, 'uncompressed');

commit 89b6bee67dd5bbc163eb1ea30a5d931da49b64cb
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 8 15:29:28 2009 +0800

    Don't print in REST::outs

diff --git a/lib/Jifty/Plugin/REST/Dispatcher.pm b/lib/Jifty/Plugin/REST/Dispatcher.pm
index 0f270a1..1aae423 100644
--- a/lib/Jifty/Plugin/REST/Dispatcher.pm
+++ b/lib/Jifty/Plugin/REST/Dispatcher.pm
@@ -281,7 +281,7 @@ sub outs {
     my $format = output_format($prefix);
 
     Jifty->web->response->content_type($format->{content_type});
-    print $format->{freezer}->(@_);
+    Jifty->web->response->body($format->{freezer}->(@_));
 
     last_rule;
 }

commit 8a956562f97767956b5c160399ad552819eb26d4
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 8 16:22:26 2009 +0800

    Make REST plugin pass tests.

diff --git a/lib/Jifty/Plugin/REST/Dispatcher.pm b/lib/Jifty/Plugin/REST/Dispatcher.pm
index 1aae423..10a61b1 100644
--- a/lib/Jifty/Plugin/REST/Dispatcher.pm
+++ b/lib/Jifty/Plugin/REST/Dispatcher.pm
@@ -15,13 +15,13 @@ use Data::Dumper ();
 use XML::Simple;
 
 before qr{^ (/=/ .*) \. (js|json|yml|yaml|perl|pl|xml|html) $}x => run {
-    $ENV{HTTP_ACCEPT} = $2;
+    Jifty->web->request->env->{HTTP_ACCEPT} = $2;
     dispatch $1;
 };
 
 before POST qr{^ (/=/ .*) ! (DELETE|PUT|GET|POST|OPTIONS|HEAD|TRACE|CONNECT) $}x => run {
     Jifty->web->request->request_method($2);
-    $ENV{REST_REWROTE_METHOD} = 1;
+    Jifty->web->request->env->{REST_REWROTE_METHOD} = 1;
     dispatch $1;
 };
 
@@ -113,8 +113,7 @@ sub show_help_specific {
     __PACKAGE__->can($method) or abort(404);
 
     Jifty->web->response->content_type('text/plain; charset=utf-8');
-
-    print __PACKAGE__->$method;
+    Jifty->web->response->body(__PACKAGE__->$method);
     last_rule;
 }
 
@@ -196,7 +195,7 @@ Returns the user's desired output format. Returns a hashref of:
 
 sub output_format {
     my $prefix = shift;
-    my $accept = ($ENV{HTTP_ACCEPT} || '');
+    my $accept = (Jifty->web->request->env->{HTTP_ACCEPT} || '');
 
     my (@prefix, $url);
     if ($prefix) {
@@ -279,7 +278,7 @@ renders the content as yaml, json, javascript, perl, xml or html.
 sub outs {
     my $prefix = shift;
     my $format = output_format($prefix);
-
+    warn "==> using $format->{format}" if $main::DEBUG;
     Jifty->web->response->content_type($format->{content_type});
     Jifty->web->response->body($format->{freezer}->(@_));
 
@@ -877,22 +876,20 @@ sub show_action_form {
     my ($action) = action(shift);
     Jifty::Util->require($action) or abort(404);
     $action = $action->new or abort(404);
-
     # XXX - Encapsulation?  Someone please think of the encapsulation!
     no warnings 'redefine';
-    local *Jifty::Web::out = sub { shift; print @_ };
     local *Jifty::Action::form_field_name = sub { shift; $_[0] };
     local *Jifty::Action::register = sub { 1 };
     local *Jifty::Web::Form::Field::Unrendered::render = \&Jifty::Web::Form::Field::render;
 
-    print start_html(-encoding => 'UTF-8', -declare_xml => 1, -title => ref($action));
+    Jifty->web->response->{body} .= start_html(-encoding => 'UTF-8', -declare_xml => 1, -title => ref($action));
     Jifty->web->form->start;
     for my $name ($action->argument_names) {
-        print $action->form_field($name);
+        Jifty->web->response->{body} .= $action->form_field($name);
     }
     Jifty->web->form->submit( label => 'POST' );
     Jifty->web->form->end;
-    print end_html;
+    Jifty->web->response->{body} .= end_html;
     last_rule;
 }
 
diff --git a/t/TestApp-Plugin-REST/t/03-format.t b/t/TestApp-Plugin-REST/t/03-format.t
index 14ca829..50e440c 100644
--- a/t/TestApp-Plugin-REST/t/03-format.t
+++ b/t/TestApp-Plugin-REST/t/03-format.t
@@ -10,6 +10,7 @@ isa_ok($server, 'Jifty::Server');
 
 my $URL     = $server->started_ok;
 my $mech    = Jifty::Test::WWW::Mechanize->new();
+$mech->requests_redirectable([]);
 
 ok(1, 'Loaded the test script');
 
@@ -52,7 +53,7 @@ sub result_of {
         my $method = $request->{mech_method};
         my $response = $mech->$method($url, @{ $request->{mech_args} || [] });
 
-        ok($response->is_success, "$method successful");
+        ok($response->is_success || $response->is_redirect, "$method successful");
         my @contents = $response->content;
 
         if (my $location = $response->header('Location')) {
@@ -150,7 +151,7 @@ result_of_post '/=/model/user' => {
 
 # on POST   '/=/model/*'     => \&create_item;
 $mech->post( $URL . '/=/model/User', { name => "moose", email => 'moose at example.com' } );
-is($mech->status, 200, "create via POST to model worked");
+is($mech->status, 302, "create via POST to model worked");
 
 $mech->post( $URL . '/=/model/Group', { name => "moose" } );
 is($mech->status, 403, "create via POST to model with disallowed create action failed with 403");

commit 40547a695ff5e0e997752f4fa565b285e7989e25
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 8 16:24:46 2009 +0800

    Another print to Jifty->web->response->body

diff --git a/lib/Jifty/Plugin/REST/Dispatcher.pm b/lib/Jifty/Plugin/REST/Dispatcher.pm
index 10a61b1..3613634 100644
--- a/lib/Jifty/Plugin/REST/Dispatcher.pm
+++ b/lib/Jifty/Plugin/REST/Dispatcher.pm
@@ -60,7 +60,7 @@ Shows basic help about resources and formats available via this RESTian interfac
 sub show_help {
     Jifty->web->response->content_type('text/plain; charset=utf-8');
 
-    print qq{
+    Jifty->web->response->body(qq{
 Accessing resources:
 
 on GET    /=/model                                   list models
@@ -96,7 +96,7 @@ or appending one of the extensions to any resource:
 
 HTML is output only if the Accept: header or an extension does not request a
 specific format.
-};
+});
     last_rule;
 }
 

commit fc755e571d8ded29467b82e499d2a0fb034111f6
Author: Chia-liang Kao <clkao at clkao.org>
Date:   Tue Dec 8 23:57:53 2009 +0800

    Make TestApp-Dispatcher/t/under.t pass

diff --git a/lib/Jifty/Plugin/CompressedCSSandJS.pm b/lib/Jifty/Plugin/CompressedCSSandJS.pm
index 6b28edc..20d1fc4 100644
--- a/lib/Jifty/Plugin/CompressedCSSandJS.pm
+++ b/lib/Jifty/Plugin/CompressedCSSandJS.pm
@@ -190,6 +190,7 @@ sub _generate_javascript {
                 my $fh;
 
                 if ( open $fh, '<', $include ) {
+                    local $_;
                     $js .= "/* Including '$file' */\n\n";
                     $js .= $_ while <$fh>;
                     $js .= "\n/* End of '$file' */\n\n";

commit 4e544e0a248fbdc39d2c833415e4f609aec28e43
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Dec 8 12:38:22 2009 -0500

    Update test file for new request format

diff --git a/t/03-form-protocol.t b/t/03-form-protocol.t
index bd949b4..d84b106 100644
--- a/t/03-form-protocol.t
+++ b/t/03-form-protocol.t
@@ -10,8 +10,7 @@ J:A:F-id-mymoniker: 23
 J:A:F-something-mymoniker: else
 J:ACTIONS: mymoniker
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -39,8 +38,7 @@ J:A:F-id-second: 42
 J:A:F-something-second: bla
 J:ACTIONS: mymoniker!second
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -79,8 +77,7 @@ J:A:F-id-second: 42
 J:A:F-something-second: bla
 J:ACTIONS: mymoniker!second
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -118,8 +115,7 @@ J:A:F-id-second: 42
 J:A:F-something-second: bla
 J:ACTIONS: mymoniker!second
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -149,8 +145,7 @@ J:A:F-id-second: 42
 J:A:F-something-second: bla
 J:ACTIONS: second
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -188,8 +183,7 @@ J:A-second: DoThat
 J:A:F-id-second: 42
 J:A:F-something-second: bla
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -230,8 +224,7 @@ J:A-second: DoThat
 J:A:F-id-second: 42
 J:A:F-something-second: bla
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -272,8 +265,7 @@ J:A-second: DoThat
 J:A:F-something-mymoniker: else
 J:A-mymoniker: DoSomething
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -309,8 +301,7 @@ J:A:F:F-id-mymoniker: 96
 J:A:F-something-mymoniker: else
 J:ACTIONS: mymoniker
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -337,8 +328,7 @@ J:A:F-id-mymoniker: 23
 J:A:F-something-mymoniker: else
 J:ACTIONS: mymoniker
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -364,8 +354,7 @@ J:A:F:F-id-mymoniker: 96
 J:A:F-something-mymoniker: else
 J:ACTIONS: mymoniker
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -394,8 +383,7 @@ J:A:F-id-second: 42
 J:A:F-something-second: feepy
 J:ACTIONS: mymoniker!second
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:
@@ -436,8 +424,7 @@ J:A:F-id-second: 42
 J:A:F-something-second: bla
 J:ACTIONS: mymoniker;second
 --- request
-request_method: GET
-path: /
+uri: http:///
 state_variables: {}
 actions:
   mymoniker:

commit ad7f286bbb0720344606d840e321ea3a399d8f8f
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Dec 8 12:41:50 2009 -0500

    Update dependencies

diff --git a/META.yml b/META.yml
index 5c74f0e..db53a34 100644
--- a/META.yml
+++ b/META.yml
@@ -42,9 +42,11 @@ recommends:
   Test::MockObject: 1.07
   Test::WWW::Declare: 0.01
 requires:
+  Any::Moose: 0
   App::CLI: 0.08
   CGI: 3.30
   CGI::Cookie::Splitter: 0
+  CGI::Simple: 0
   CSS::Squish: 0.07
   Cache::Cache: 0
   Calendar::Simple: 0
@@ -109,6 +111,8 @@ requires:
   Module::ScanDeps: 0
   Object::Declare: 0.13
   Params::Validate: 0
+  Plack: 0
+  Plack::Request: 0
   SQL::ReservedWords: 0
   SUPER: 0
   Scalar::Defer: 0.12
diff --git a/Makefile.PL b/Makefile.PL
index c1a1f79..7b06367 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -2,6 +2,7 @@ use inc::Module::Install 0.46;
 name('Jifty');
 license('Perl');
 perl_version '5.8.3';
+requires('Any::Moose');
 requires('App::CLI' => 0.08 ); # App::CLI::Command::Help App::CLI::Command
 requires('Cache::Cache'); #Cache::FileCache
 requires('Calendar::Simple');
@@ -12,7 +13,7 @@ requires('Class::Data::Inheritable');
 requires('Class::Trigger' => '0.13');
 requires('Clone' => '0.27');
 requires('CGI' => '3.30');
-requires('CGI::Simple');
+requires('CGI::Simple'); # CGI::Simple::Cookie
 requires('CGI::Cookie::Splitter');
 requires('Class::Inspector' => 1.20); # For File::ShareDir on Win32
 requires('Crypt::CBC');
@@ -69,6 +70,8 @@ requires('Module::Refresh');
 requires('Module::ScanDeps');
 requires('Object::Declare' => '0.13');
 requires('Params::Validate');
+requires('Plack'); # Plack::Loader Plack::Test Plack::Util
+requires('Plack::Request');
 requires('Scalar::Defer' => '0.12');
 requires('Shell::Command');
 requires('String::BufferStack' => '1.12');

commit 15c1dc78bd1593aacb149a3a02528baca4759335
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Dec 8 13:28:03 2009 -0500

    I18N::LangTags::Detect goes looking for CGI environment variables
    
    Make client-side language negotiation work again, by faking the CGI
    environment variables that I18N::LangTags::Detect looks at.

diff --git a/lib/Jifty/I18N.pm b/lib/Jifty/I18N.pm
index 8bc6197..f60b201 100644
--- a/lib/Jifty/I18N.pm
+++ b/lib/Jifty/I18N.pm
@@ -198,6 +198,8 @@ sub get_language_handle {
         }
     }
 
+    local $ENV{REQUEST_METHOD} = Jifty->web->request->method;
+    local $ENV{HTTP_ACCEPT_LANGUAGE} = Jifty->web->request->header("Accept-Language") || "";
     $$DynamicLH = $self->get_handle($lang ? $lang : ()) if $DynamicLH;
 }
 

commit 3a834f8276ac88d6880e583d90ad8ba7a797c453
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Dec 8 14:18:21 2009 -0500

    Creat users as the superuser; this only worked because of AdminMode

diff --git a/t/TestApp-Plugin-ActorMetadata/t/actormetadata.t b/t/TestApp-Plugin-ActorMetadata/t/actormetadata.t
index 5dbb105..8a174a6 100644
--- a/t/TestApp-Plugin-ActorMetadata/t/actormetadata.t
+++ b/t/TestApp-Plugin-ActorMetadata/t/actormetadata.t
@@ -9,11 +9,11 @@ my $has_mock_time;
 eval "use Test::MockTime qw/set_relative_time/";
 $has_mock_time = 1 unless $@;
 
-$user_foo = TestApp::Plugin::ActorMetadata::Model::User->new;
+$user_foo = TestApp::Plugin::ActorMetadata::Model::User->new->as_superuser;
 $user_foo->create( name => 'foo', email => 'foo at example.com' );
 ok( $user_foo->id, 'created user foo' );
 
-$user_bar = TestApp::Plugin::ActorMetadata::Model::User->new;
+$user_bar = TestApp::Plugin::ActorMetadata::Model::User->new->as_superuser;
 $user_bar->create( name => 'bar', email => 'bar at example.com' );
 ok( $user_bar->id, 'created user bar' );
 

commit ec72c8b5f75b5d691adf3d8b02be183c330abbbe
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Dec 8 14:20:17 2009 -0500

    Turn off AdminMode and DevelMode on test apps whenever possible
    
    This turns off halos, for example, which makes it easier to look for
    specific content -- as well as providing a small speedup to all the
    tests.

diff --git a/t/TestApp-Collection-Select/etc/config.yml b/t/TestApp-Collection-Select/etc/config.yml
index 0bca5ef..833635a 100644
--- a/t/TestApp-Collection-Select/etc/config.yml
+++ b/t/TestApp-Collection-Select/etc/config.yml
@@ -15,7 +15,7 @@ framework:
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: INFO
diff --git a/t/TestApp-JiftyJS/etc/config.yml b/t/TestApp-JiftyJS/etc/config.yml
index c6f34e5..a7c14cb 100644
--- a/t/TestApp-JiftyJS/etc/config.yml
+++ b/t/TestApp-JiftyJS/etc/config.yml
@@ -1,6 +1,6 @@
 --- 
 framework: 
-  AdminMode: 1
+  AdminMode: 0
   ApplicationClass: TestApp::JiftyJS
   ApplicationName: TestApp::JiftyJS
   ApplicationUUID: F43CA57E-A4BE-11DC-A07C-465A83BE23AB
@@ -14,7 +14,7 @@ framework:
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
     AllowedLang:
diff --git a/t/TestApp-Mason/etc/config.yml b/t/TestApp-Mason/etc/config.yml
index 304c7bc..4f034c8 100644
--- a/t/TestApp-Mason/etc/config.yml
+++ b/t/TestApp-Mason/etc/config.yml
@@ -1,6 +1,6 @@
 --- 
 framework: 
-  AdminMode: 1
+  AdminMode: 0
   ApplicationClass: TestApp::Mason
   ApplicationName: TestApp-Mason
   ApplicationUUID: 691A2590-F25E-11DD-9995-406635203BE5
@@ -15,7 +15,7 @@ framework:
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: INFO
diff --git a/t/TestApp-Plugin-ActorMetadata/etc/config.yml b/t/TestApp-Plugin-ActorMetadata/etc/config.yml
index 33abd94..dd53423 100644
--- a/t/TestApp-Plugin-ActorMetadata/etc/config.yml
+++ b/t/TestApp-Plugin-ActorMetadata/etc/config.yml
@@ -1,6 +1,6 @@
 --- 
 framework: 
-  AdminMode: 1
+  AdminMode: 0
   ApplicationClass: TestApp::Plugin::ActorMetadata
   ApplicationName: TestApp::Plugin::ActorMetadata
   ApplicationUUID: C4418A2E-DE0B-11DD-96DC-F9E9C3E98ACD
@@ -15,7 +15,7 @@ framework:
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: INFO
diff --git a/t/TestApp-Plugin-AppPluginHasModels/etc/config.yml b/t/TestApp-Plugin-AppPluginHasModels/etc/config.yml
index 507ae79..b7e1fe0 100644
--- a/t/TestApp-Plugin-AppPluginHasModels/etc/config.yml
+++ b/t/TestApp-Plugin-AppPluginHasModels/etc/config.yml
@@ -1,6 +1,6 @@
 --- 
 framework: 
-  AdminMode: 1
+  AdminMode: 0
   ApplicationClass: TestApp::Plugin::AppPluginHasModels
   ApplicationName: TestApp-Plugin-AppPluginHasModels
   ApplicationUUID: 646FD662-32DD-11DC-AD79-2A0157C3B83B
@@ -15,7 +15,7 @@ framework:
     RecordUUIDs: active
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: INFO
diff --git a/t/TestApp-Plugin-CompressedCSSandJS/etc/config.yml b/t/TestApp-Plugin-CompressedCSSandJS/etc/config.yml
index 272e37d..44a4101 100644
--- a/t/TestApp-Plugin-CompressedCSSandJS/etc/config.yml
+++ b/t/TestApp-Plugin-CompressedCSSandJS/etc/config.yml
@@ -1,6 +1,6 @@
 --- 
 framework: 
-  AdminMode: 1
+  AdminMode: 0
   ApplicationClass: TestApp::Plugin::CompressedCSSandJS
   ApplicationName: TestApp::Plugin::CompressedCSSandJS
   ApplicationUUID: DC3B58E4-4F3C-11DC-9ECB-E5DB6F105773
@@ -15,7 +15,7 @@ framework:
     RecordUUIDs: active
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: DEBUG
diff --git a/t/TestApp-Plugin-News/etc/config.yml b/t/TestApp-Plugin-News/etc/config.yml
index a14c0af..2412cbc 100644
--- a/t/TestApp-Plugin-News/etc/config.yml
+++ b/t/TestApp-Plugin-News/etc/config.yml
@@ -1,6 +1,6 @@
 --- 
 framework: 
-  AdminMode: 1
+  AdminMode: 0
   ApplicationClass: TestApp::Plugin::News
   ApplicationName: TestApp-Plugin-News
   ApplicationUUID: 09757060-0564-11DC-AD52-CB2C768159CC
@@ -13,7 +13,7 @@ framework:
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: INFO
diff --git a/t/TestApp-Plugin-OnClick/etc/config.yml b/t/TestApp-Plugin-OnClick/etc/config.yml
index 9851fc4..d914140 100644
--- a/t/TestApp-Plugin-OnClick/etc/config.yml
+++ b/t/TestApp-Plugin-OnClick/etc/config.yml
@@ -1,6 +1,6 @@
 --- 
 framework: 
-  AdminMode: 1
+  AdminMode: 0
   ApplicationClass: TestApp::Plugin::OnClick
   ApplicationName: TestApp-Plugin-OnClick
   ApplicationUUID: 45E1B0FE-820A-11DC-9905-76B28F38D863
@@ -14,7 +14,7 @@ framework:
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: INFO
diff --git a/t/TestApp-Plugin-PasswordAuth/etc/config.yml b/t/TestApp-Plugin-PasswordAuth/etc/config.yml
index 308ee3b..a655abb 100644
--- a/t/TestApp-Plugin-PasswordAuth/etc/config.yml
+++ b/t/TestApp-Plugin-PasswordAuth/etc/config.yml
@@ -1,6 +1,6 @@
 --- 
 framework: 
-  AdminMode: 1
+  AdminMode: 0
   ApplicationClass: TestApp::Plugin::PasswordAuth
   ApplicationName: TestApp-Plugin-PasswordAuth
   ApplicationUUID: E6B4180A-C68F-11DB-893B-FEFB1AECF28B
@@ -13,7 +13,7 @@ framework:
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: DEBUG
diff --git a/t/TestApp-Plugin-SinglePage/etc/config.yml b/t/TestApp-Plugin-SinglePage/etc/config.yml
index 971e87d..c14e78e 100644
--- a/t/TestApp-Plugin-SinglePage/etc/config.yml
+++ b/t/TestApp-Plugin-SinglePage/etc/config.yml
@@ -1,6 +1,6 @@
 --- 
 framework: 
-  AdminMode: 1
+  AdminMode: 0
   ApplicationClass: TestApp::Plugin::SinglePage
   ApplicationName: TestApp::Plugin::SinglePage
   ApplicationUUID: DC3B58E4-4F3C-11DC-9ECB-E5DB6F105773
@@ -15,7 +15,7 @@ framework:
     RecordUUIDs: active
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: INFO
diff --git a/t/TestApp-RestartServer/etc/config.yml b/t/TestApp-RestartServer/etc/config.yml
index cd37d5e..6188904 100644
--- a/t/TestApp-RestartServer/etc/config.yml
+++ b/t/TestApp-RestartServer/etc/config.yml
@@ -1,6 +1,6 @@
 --- 
 framework: 
-  AdminMode: 1
+  AdminMode: 0
   ApplicationClass: TestApp::RestartServer
   ApplicationName: TestApp-RestartServer
   ApplicationUUID: 691A2590-F25E-11DD-9995-406635203BE5
@@ -15,7 +15,7 @@ framework:
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: FATAL
diff --git a/t/TestApp-Template-Declare/etc/config.yml b/t/TestApp-Template-Declare/etc/config.yml
index 0d6da8b..93c1e91 100644
--- a/t/TestApp-Template-Declare/etc/config.yml
+++ b/t/TestApp-Template-Declare/etc/config.yml
@@ -1,6 +1,6 @@
 --- 
 framework: 
-  AdminMode: 1
+  AdminMode: 0
   ApplicationClass: TestApp
   ApplicationName: TestApp
   ApplicationUUID: CE9AD926-F2A1-11DD-BB2C-5CD7FE13D77C
@@ -15,7 +15,7 @@ framework:
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: INFO

commit 1654b73062cfbd9a0d66f1e2d785accfcf038bb7
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Dec 8 14:41:35 2009 -0500

    Only set CGI-like headers for I18N if we have a Jifty->web->request

diff --git a/lib/Jifty/I18N.pm b/lib/Jifty/I18N.pm
index f60b201..a8e484d 100644
--- a/lib/Jifty/I18N.pm
+++ b/lib/Jifty/I18N.pm
@@ -198,8 +198,10 @@ sub get_language_handle {
         }
     }
 
-    local $ENV{REQUEST_METHOD} = Jifty->web->request->method;
-    local $ENV{HTTP_ACCEPT_LANGUAGE} = Jifty->web->request->header("Accept-Language") || "";
+    local $ENV{REQUEST_METHOD} = Jifty->web->request->method
+        if Jifty->web->request;
+    local $ENV{HTTP_ACCEPT_LANGUAGE} = Jifty->web->request->header("Accept-Language") || ""
+        if Jifty->web->request;
     $$DynamicLH = $self->get_handle($lang ? $lang : ()) if $DynamicLH;
 }
 

-----------------------------------------------------------------------


More information about the Jifty-commit mailing list