PSGI规范将 HTTP 响应定义为由三部分组成,其中第三部分可以是数组引用或文件句柄。文件句柄可能是:
一个 IO::Handle 类对象或内置文件句柄。
规范继续说:
服务器可以使用 fileno 和 Scalar::Util::reftype 检查主体是否是真实的文件句柄,如果它是具有文件描述符的真实文件句柄,它可以使用 sendfile(2) 等技术优化文件服务。
现在,我使用plackup
(Plack 版本 0.9978)拼凑了一个命令行示例,似乎检查正文是否是真正的文件句柄会导致致命错误:
Can't locate object method "FILENO" via package "IO::Scalar" at /usr/lib/perl5/5.10/i686-cygwin/IO/Handle.pm line 390
这是命令行示例:
plackup -MData::Dumper -MIO::Scalar -e \
'sub { $env=shift; return [200, [], IO::Scalar->new(\Dumper $env) ] }'
当然我不能使用文件句柄:
plackup --port 9999 -MData::Dumper -e \
'sub { $env=shift; return [200, [], [Dumper $env] ] }'
但我对什么有效,什么无效感兴趣。那么,Plack 在调用句柄时是否应该更加小心,FILENO
以免遇到异常?
并添加另一个:
plackup --port 9999 -MData::Dumper -e \
'sub{$env=shift; $s=Dumper $env; open $fh,q(<),\$s or die; return [200,[],$fh ]}'
看起来文件句柄没有被识别为这样。错误信息是:
body should be an array ref or filehandle at /usr/lib/perl5/site_perl/5.10/Plack/Middleware/StackTrace.pm line 35
更新:
正如 ysth 在他的回答中所说,以下将起作用(至少在 Cygwin 上的 5.10.1 上):
plackup -p 9999 -MData::Dumper -MIO::String -e \
'sub { return [200, [], IO::String->new(\Dumper shift) ] }'
但很明显,从失败的示例中可以看出某个地方存在问题,一旦我确定它实际上是什么,就会报告它。