When from_psgi_response, a bug when headers are already output and charset is set...
Tomohiro Hosaka [Wed, 2 Jan 2019 09:43:55 +0000 (18:43 +0900)]
[error] Caught exception in MyApp::Controller::Docs->stream_and_charset "You may not change the encoding once the headers are finalized at /usr/home/bokutin/code/reading/catalyst-runtime/lib/Catalyst/Response.pm line 202."
[warn] Useless setting a header value after finalize_headers and the response callback has been called. Since we don't support tail headers this will not work as you might expect.

lib/Catalyst/Response.pm
t/psgi_utils.t

index 2399ae5..a9277b5 100644 (file)
@@ -196,6 +196,8 @@ sub from_psgi_response {
         die "You can't set a Catalyst response from that, expect a valid PSGI response";
     }
 
+    return if $self->finalized_headers;
+
     # Encoding compatibilty.   If the response set a charset, well... we need
     # to assume its properly encoded and NOT encode for this response.  Otherwise
     # We risk double encoding.
index 6508886..e5ab61c 100644 (file)
@@ -55,6 +55,27 @@ my $psgi_app = sub {
     $c->res->from_psgi_response([200, ['Content-Type'=>'text/html'], ["hello","world"]]);
   }
 
+  sub streaming_body :Local {
+    my ($self, $c) = @_;
+    my $psgi_app = sub {
+        my $respond = shift;
+        my $writer = $respond->([200,["Content-Type" => "text/plain"]]);
+        $writer->write("body");
+        $writer->close;
+    };
+    $c->res->from_psgi_response($psgi_app);
+  }
+  sub streaming_body_with_charset :Local {
+    my ($self, $c) = @_;
+    my $psgi_app = sub {
+        my $respond = shift;
+        my $writer = $respond->([200,["Content-Type" => "text/plain; charset=utf-8"]]);
+        $writer->write("body");
+        $writer->close;
+    };
+    $c->res->from_psgi_response($psgi_app);
+  }
+
   package MyApp::Controller::User;
   $INC{'MyApp/Controller/User.pm'} = __FILE__;
 
@@ -407,4 +428,13 @@ use Catalyst::Test 'MyApp';
   is $res->content, "helloworld";
 }
 
+{
+  my ($res, $c) = ctx_request('/docs/streaming_body');
+  is $res->content, "body";
+}
+{
+  my ($res, $c) = ctx_request('/docs/streaming_body_with_charset');
+  is $res->content, "body";
+}
+
 done_testing();