Skip to content

Loading…

Add stream_chunked middleware parameter #251

Open
wants to merge 2 commits into from

2 participants

@athomason

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.

The motivation of this is to allow Deflater to work with the chunked responses generated by Plack::App::Proxy::Backend::AnyEvent::HTTP under Twiggy.

athomason added some commits
@athomason athomason Add stream_chunked middleware parameter
* 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.
735e799
@athomason athomason Prevent memory leak 181193b
@miyagawa
plack member

Looks good - can you supply a test?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 11, 2011
  1. @athomason

    Add stream_chunked middleware parameter

    athomason committed
    * 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.
Commits on Oct 15, 2011
  1. @athomason

    Prevent memory leak

    athomason committed
Showing with 36 additions and 7 deletions.
  1. +36 −7 lib/Plack/Middleware/BufferedStreaming.pm
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,11 +32,17 @@ 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;
@@ -36,7 +50,14 @@ sub call {
}
});
- return $ret;
+ if ($ret) {
+ return $ret;
+ }
+ else {
+ return sub {
+ $ret = shift;
+ };
+ }
} else {
return $res;
}
@@ -61,8 +82,14 @@ 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
@@ -70,4 +97,6 @@ Yuval Kogman
Tatsuhiko Miyagawa
+Adam Thomason
+
=cut
Something went wrong with that request. Please try again.