Add stream_chunked middleware parameter #251

Open
wants to merge 2 commits into
from
View
43 lib/Plack/Middleware/BufferedStreaming.pm
@@ -5,6 +5,7 @@ use Carp;
use Plack::Util;
use Scalar::Util qw(weaken);
use parent qw(Plack::Middleware);
+use Plack::Util::Accessor qw( stream_chunked );
sub call {
my ( $self, $env ) = @_;
@@ -13,7 +14,14 @@ sub call {
$env->{'psgi.streaming'} = Plack::Util::TRUE;
my $res = $self->app->($env);
- return $res if $caller_supports_streaming;
+ if ( $self->stream_chunked ) {
+ unless ( $caller_supports_streaming ) {
+ die "stream_chunked was specified but server doesn't support it"
+ }
+ }
+ elsif ( $caller_supports_streaming ) {
+ return $res;
+ }
if ( ref($res) eq 'CODE' ) {
my $ret;
@@ -24,19 +32,32 @@ sub call {
if ( @$write == 2 ) {
my @body;
- $ret = [ @$write, \@body ];
-
return Plack::Util::inline_object(
write => sub { push @body, $_[0] },
- close => sub { },
+ close => sub {
+ if ($ret) {
+ $ret->([ @$write, \@body ]);
+ undef $ret;
+ }
+ else {
+ $ret = [ @$write, \@body ];
+ }
+ },
);
} else {
$ret = $write;
return;
}
});
- return $ret;
+ if ($ret) {
+ return $ret;
+ }
+ else {
+ return sub {
+ $ret = shift;
+ };
+ }
} else {
return $res;
}
@@ -61,13 +82,21 @@ that wraps the application that uses C<psgi.streaming> interface to
run on the servers that do not support the interface, by buffering the
writer output to a temporary buffer.
-This middleware doesn't do anything and bypass the application if the
-server supports C<psgi.streaming> interface.
+If the server supports the C<psgi.streaming> interface, the middleware will be
+bypassed unless the C<stream_chunked> parameter is passed. In that case, the
+server must support C<psgi.streaming>, and the middleware will transform a
+chunked streaming response (i.e. a streaming response where C<$writer> is
+called with only code and headers) into an unchunked streaming response that
+calls its C<$writer> callback with the entire response, including the
+(buffered) body. This is useful if the server supports streaming responses, but
+an upstream middleware (e.g. Deflater) does not support chunked responses.
=head1 AUTHOR
Yuval Kogman
Tatsuhiko Miyagawa
+Adam Thomason
+
=cut