The PSGI specification defines the HTTP response as consisting of three parts, the third of which may be either an array reference or a filehandle. The filehandle may be:
An IO::Handle-like object or a built-in filehandle.
And the spec goes on to say:
Servers MAY check if the body is a real filehandle using fileno and Scalar::Util::reftype and if it's a real filehandle that has a file descriptor, it MAY optimize the file serving using techniques like sendfile(2).
Now I've cobbled together a command-line example using plackup
(Plack version 0.9978), and it appears that checking if the body is a real filehandle results in a fatal error:
Can't locate object method "FILENO" via package "IO::Scalar" at /usr/lib/perl5/5.10/i686-cygwin/IO/Handle.pm line 390
Here's the command-line example:
plackup -MData::Dumper -MIO::Scalar -e \
'sub { $env=shift; return [200, [], IO::Scalar->new(\Dumper $env) ] }'
Of course I could just not use a filehandle:
plackup --port 9999 -MData::Dumper -e \
'sub { $env=shift; return [200, [], [Dumper $env] ] }'
But I'm interested in what works and what doesn't. So shouldn't Plack exercise more caution when calling FILENO
on the handle so it wouldn't run into an exception?
And to add another one:
plackup --port 9999 -MData::Dumper -e \
'sub{$env=shift; $s=Dumper $env; open $fh,q(<),\$s or die; return [200,[],$fh ]}'
Looks like the filehandle isn't recognized as such. The error message is:
body should be an array ref or filehandle at /usr/lib/perl5/site_perl/5.10/Plack/Middleware/StackTrace.pm line 35
Update:
As ysth stated in his answer, the following will work (at least on 5.10.1 on Cygwin):
plackup -p 9999 -MData::Dumper -MIO::String -e \
'sub { return [200, [], IO::String->new(\Dumper shift) ] }'
But clearly, there is an issue someplace as can be seen from the failing examples, and it will be reported once I've made up my mind what it actually is.