Plack::Middleware::AdaptFilehandleRead - Give a filehandle a getline method when its missing
use Plack::Builder;
use AppReturnsFileHandleWithRead;
my $app = AppReturnsFileHandleWithRead->new;
builder {
enable 'AdaptFilehandleRead';
$app;
};
PSGI allows for the body content to be a glob filehandle or a Filehandle
like object. For the later case the object must have a method getline
which works as described in IO::Handle. However sometimes you may have
a custom filehandle like object that support the common read
method. For
example many versions of Catalyst allowed the body of a response to be a
glob or object that does read
. People might have written custom streaming
applications that had this read
method but not getline
. As a result
these custom Filehandle like objects are not compatible with the expectations
of PSGI.
This middleware exists to help you convert such a custom made filehandle like
object. If you have created something like this (or for example using some
shared code like MogileFS::Client that returns a filehandle that does read
but not getline
) you can use this middleware to wrap said object in a proxy
that does the getline
method by reading from the exising read
method.
By default, if this middleware is enabled, it will examine any body values and
check if they are 1) an object, 2) that does read
and 3) doesn't do getline
If such a case exists it will create an instance of Plack::Middleware::AdaptFilehandleRead::Proxy
which had the getline
method. It also will delegate any other method calls
to the wrapped object via AUTOLOAD so if you have some additional custom methods
it will still work as expected. It does not currently proxy any overloading.
If for some reason your custom filehandle like object does getline
but its
faulty and the read
method is correct, you can set always_adapt
to true
and the proxy will be applied even if a getline
method is detected.
builder {
enable 'AdaptFilehandleRead', always_adapt=>1;
$app;
};
This middleware will do its best to respect the various allowed values of
$/
for deciding how to return content from getline
Currently we support
$/
values of scalar ref (like \8192 for reading fixed length chunks) or
simple scalars (like \n for reading newline delimited records). Currently
we don't support $/
as undef (for slurping full content) and some of the other
more esoteric values of $/
as the author percieves that support was not needed
withing the context of adapting read
for PSGI uses (all exampled Plack
handlers seemed to use the scalar ref fixed length chunk value for $/
, but
we choose to also support the scalar record deliminator option since its very
commonly seen elsewhere).
This middleware has the following attributes:
Defaults to false, Optional.
Set this to any true value and the proxy will always wrap any filehandle like
object, as long as it has a read
method (even it if already has a getline
method.) Use this if you have a custom filehandle like object that you are using
as the body of a PSGI reponse that has both read
and getline
but the
getline
is broken in some way (but read
isn't).
Defaults to 65536, Optional.
When adapting read
, we call for chunks of data 65536 in length. This may not be the
most efficient way to read your files based on your specific requirements. If so, you
may override the size of the chunks:
builder {
enable 'AdaptFilehandleRead', chunksize=>65536;
$app;
};
NOTE: Be aware that the chunk is read into memory as each chunk is read. Should a
chunk fail to find the deliminator indicated by $/
, another chunk would be read.
If you entire file contains no match, it is not impossible for the entire file to be
thus read into memory should getline
be used. In these cases you might wish to
make sure your underlying Plack server has other ways to handle these types of
files (for example using XSendfile or via some other optimization.) or instead be sure
to use the fixed chunk sized option for $/
.
NOTE: For most Plack handlers, "$/" is set to a scalar refer, such as:
local $/ = \'4096'
which is a flag indicating we'd prefer ->getline to return fixed length chunks instead of variable length lines. In this case the 'chunksize' attribute is ignored. Which means if you are using this with Plack chances are this attribute will not be respected :) You probably should not worry about this!
Plack, Plack::Middleware, IO::File.
See 'perlvar' docs for more on the possible values of $/
.
John Napiorkowski email:jjnapiork@cpan.org
Copyright 2014, John Napiorkowski email:jjnapiork@cpan.org
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.