Skip to content

Commit

Permalink
Add stream_chunked middleware parameter
Browse files Browse the repository at this point in the history
* This option allows transformation of chunked streaming responses into
  unchunked streaming responses by buffering calls to $writer->write. Only
  works with servers that support streamed responses.
  • Loading branch information
athomason authored and ssmccoy committed Aug 13, 2012
1 parent 9b7b2fe commit 04dc25e
Showing 1 changed file with 35 additions and 7 deletions.
42 changes: 35 additions & 7 deletions lib/Plack/Middleware/BufferedStreaming.pm
Expand Up @@ -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 ) = @_;
Expand All @@ -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;
Expand All @@ -24,19 +32,31 @@ 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 ]);
}
else {
$ret = [ @$write, \@body ];
}
},
);
} else {
$ret = $write;
return;
}
});

return $ret;
if ($ret) {
return $ret;
}
else {
return sub {
$ret = shift;
};
}
} else {
return $res;
}
Expand All @@ -61,13 +81,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

0 comments on commit 04dc25e

Please sign in to comment.