as_psgi and to_app
John Napiorkowski [Fri, 26 Sep 2014 17:21:59 +0000 (12:21 -0500)]
Changes
lib/Catalyst/Response.pm
t/psgi_utils.t

diff --git a/Changes b/Changes
index a9ed970..4dd30c5 100644 (file)
--- a/Changes
+++ b/Changes
@@ -3,6 +3,8 @@
 5.90080_001 - TBD
   - MyApp->to_app is now an alias for MyApp->psgi_app in order to better support
     existing Plack conventions.
+  - Modify Catayst::Response->from_psgi_response to allow the first argument to
+    be an object that does ->as_psgi.
 
 5.90073 - 2014-09-23
   - Fixed a regression caused by the last release where we broke what happened
index f049ebf..709f0ad 100644 (file)
@@ -4,6 +4,7 @@ use Moose;
 use HTTP::Headers;
 use Moose::Util::TypeConstraints;
 use namespace::autoclean;
+use Scalar::Util 'blessed';
 
 with 'MooseX::Emulate::Class::Accessor::Fast';
 
@@ -116,6 +117,9 @@ sub finalize_headers {
 
 sub from_psgi_response {
     my ($self, $psgi_res) = @_;
+    if(blessed($psgi_res) && $psgi_res->can('as_psgi')) {
+      $psgi_res = $psgi_res->as_psgi;
+    }
     if(ref $psgi_res eq 'ARRAY') {
         my ($status, $headers, $body) = @$psgi_res;
         $self->status($status);
@@ -430,6 +434,8 @@ a $responder) set the response from it.
 Properly supports streaming and delayed response and / or async IO if running
 under an expected event loop.
 
+If passed an object, will expect that object to do a method C<as_psgi>.
+
 Example:
 
     package MyApp::Web::Controller::Test;
index 078dd82..9c05559 100644 (file)
@@ -9,6 +9,12 @@ my $psgi_app = sub {
 };
 
 {
+  package MyApp::PSGIObject;
+
+  sub as_psgi {
+    return [200, ['Content-Type' => 'text/plain'], ['as_psgi']];
+  };
+
   package MyApp::Controller::Docs;
   $INC{'MyApp/Controller/Docs.pm'} = __FILE__;
 
@@ -16,6 +22,12 @@ my $psgi_app = sub {
   use Plack::Request;
   use Catalyst::Utils;
 
+  sub as_psgi :Local {
+    my ($self, $c) = @_;
+    my $as_psgi = bless +{}, 'MyApp::PSGIObject';
+    $c->res->from_psgi_response($as_psgi);
+  }
+
   sub name :Local {
     my ($self, $c) = @_;
     my $env = $c->Catalyst::Utils::env_at_action;
@@ -122,6 +134,11 @@ use Test::More;
 use Catalyst::Test 'MyApp';
 
 {
+  my ($res, $c) = ctx_request('/docs/as_psgi');
+  is $res->content, 'as_psgi';
+}
+
+{
   my ($res, $c) = ctx_request('/user/mounted/111?path_prefix=1');
   is $c->action, 'user/mounted';
   is $res->content, 'http://localhost/user/user/local_example_args1/111';
@@ -367,32 +384,3 @@ use Catalyst::Test 'MyApp';
 }
 
 done_testing();
-
-__END__
-
-
-use Plack::App::URLMap;
-use HTTP::Request::Common;
-use HTTP::Message::PSGI;
-
-my $urlmap = Plack::App::URLMap->new;
-
-my $app1 = sub {
-  my $env = shift;
-  return [200, [], [
-    "REQUEST_URI: $env->{REQUEST_URI}, FROM: $env->{MAP_TO}, PATH_INFO: $env->{PATH_INFO}, SCRIPT_NAME $env->{SCRIPT_NAME}"]];
-};
-
-$urlmap->map("/" => sub { my $env = shift; $env->{MAP_TO} = '/'; $app1->($env)});
-$urlmap->map("/foo" => sub { my $env = shift; $env->{MAP_TO} = '/foo'; $app1->($env)});
-$urlmap->map("/bar/baz" => sub { my $env = shift; $env->{MAP_TO} = '/foo/bar'; $app1->($env)});
-
-my $app = $urlmap->to_app;
-
-warn $app->(req_to_psgi(GET '/'))->[2]->[0];
-warn $app->(req_to_psgi(GET '/111'))->[2]->[0];
-warn $app->(req_to_psgi(GET '/foo'))->[2]->[0];
-warn $app->(req_to_psgi(GET '/foo/222'))->[2]->[0];
-warn $app->(req_to_psgi(GET '/bar/baz'))->[2]->[0];
-warn $app->(req_to_psgi(GET '/bar/baz/333'))->[2]->[0];
-