Skip to content

Proposal: Return values for PSGI streaming functions

doy edited this page Jan 7, 2013 · 3 revisions

Add comments to: https://github.com/plack/psgi-specs/issues/27

The streaming interface specified in the PSGI spec. Just mentions that you have to implement write & close methods, but doesn't make any mention of their return values.

Many web servers are able to give you info on how many bytes were successfully written to the client when you print something, and when you close the connection you can sometimes check if the connection has been aborted.

I'm currently hacking around this by just monkeypatching my local Plack::Handler::Apache2 (and the equivalent code for other servers I use):

diff --git a/lib/Plack/Handler/Apache2.pm b/lib/Plack/Handler/Apache2.pm
index 9ab871d..8a0e593 100644
--- a/lib/Plack/Handler/Apache2.pm
+++ b/lib/Plack/Handler/Apache2.pm
@@ -5,6 +5,7 @@ use Apache2::RequestRec;
 use Apache2::RequestIO;
 use Apache2::RequestUtil;
 use Apache2::Response;
+use Apache2::Connection;
 use Apache2::Const -compile => qw(OK);
 use Apache2::Log;
 use APR::Table;
@@ -176,8 +177,15 @@ sub _handle_response {
     }
     else {
         return Plack::Util::inline_object
-            write => sub { $r->print(@_); $r->rflush },
-            close => sub { $r->rflush };
+            write => sub {
+                my $cnt = $r->print(@_);
+                $r->rflush;
+                return $cnt;
+            },
+            close => sub {
+                $r->rflush;
+                return ! $r->connection->aborted;
+            };
     }

     return Apache2::Const::OK;

I think it would make sense to amend the spec to say that PSGI servers MAY return some sensible return values from these functions.

If there's multiple sensible ways different servers could return from these functions maybe indicating what flavor they support via optional psgi.streaming.$foo variables. Maybe something like:

Optional[psgi.streaming.write.return_value = enum(undef bool bytes_written chars_written )]
Optional[psgi.streaming.close.return_value = enum(undef bool)]

So under servers set that to 'undef' (or don't set it) you wouldn't check the return value, you'd check ones with 'bool' for truth, bytes_written would be $ret == bytes::length($buffer_i_think_i_wrote) and chars_written $ret == length($buffer_i_think_i_wrote).

Alternate proposal

If psgix.streaming_return_values is set, then the server MUST return a useful value from write. This value should be the number of bytes written. Additionally, writer objects can optionally implement an aborted method, which returns true if the connection has been closed and false otherwise. Applications should test for this API being implemented by checking the writer object for $w->can('aborted').