Catalyst-Runtime
view release on metacpan or search on metacpan
lib/Catalyst/Engine.pm view on Meta::CPAN
package Catalyst::Engine;
use Moose;
with 'MooseX::Emulate::Class::Accessor::Fast';
use CGI::Simple::Cookie;
use Data::Dump qw/dump/;
use Errno 'EWOULDBLOCK';
use HTML::Entities;
use HTTP::Headers;
use Plack::Loader;
use Catalyst::EngineLoader;
use Encode 2.21 'decode_utf8', 'encode', 'decode';
use Plack::Request::Upload;
use Hash::MultiValue;
use namespace::clean -except => 'meta';
use utf8;
# Amount of data to read from input on each pass
our $CHUNKSIZE = 64 * 1024;
# XXX - this is only here for compat, do not use!
has env => ( is => 'rw', writer => '_set_env' , weak_ref=>1);
my $WARN_ABOUT_ENV = 0;
around env => sub {
my ($orig, $self, @args) = @_;
if(@args) {
warn "env as a writer is deprecated, you probably need to upgrade Catalyst::Engine::PSGI"
unless $WARN_ABOUT_ENV++;
return $self->_set_env(@args);
}
return $self->$orig;
};
# XXX - Only here for Engine::PSGI compat
sub prepare_connection {
my ($self, $ctx) = @_;
$ctx->request->prepare_connection;
}
=head1 NAME
Catalyst::Engine - The Catalyst Engine
=head1 SYNOPSIS
See L<Catalyst>.
=head1 DESCRIPTION
=head1 METHODS
=head2 $self->finalize_body($c)
Finalize body. Prints the response output as blocking stream if it looks like
a filehandle, otherwise write it out all in one go. If there is no body in
the response, we assume you are handling it 'manually', such as for nonblocking
style or asynchronous streaming responses. You do this by calling L</write>
several times (which sends HTTP headers if needed) or you close over
C<< $response->write_fh >>.
See L<Catalyst::Response/write> and L<Catalyst::Response/write_fh> for more.
=cut
sub finalize_body {
my ( $self, $c ) = @_;
my $res = $c->response; # We use this all over
## If we've asked for the write 'filehandle' that means the application is
## doing something custom and is expected to close the response
return if $res->_has_write_fh;
my $body = $res->body; # save some typing
if($res->_has_response_cb) {
## we have not called the response callback yet, so we are safe to send
## the whole body to PSGI
my @headers;
$res->headers->scan(sub { push @headers, @_ });
# We need to figure out what kind of body we have and normalize it to something
# PSGI can deal with
if(defined $body) {
# Handle objects first
if(blessed($body)) {
if($body->can('getline')) {
# Body is an IO handle that meets the PSGI spec. Nothing to normalize
} elsif($body->can('read')) {
# In the past, Catalyst only looked for ->read not ->getline. It is very possible
# that one might have an object that respected read but did not have getline.
# As a result, we need to handle this case for backcompat.
# We will just do the old loop for now. In a future version of Catalyst this support
# will be removed and one will have to rewrite their custom object or use
# Plack::Middleware::AdaptFilehandleRead. In anycase support for this is officially
# deprecated and described as such as of 5.90060
my $got;
do {
$got = read $body, my ($buffer), $CHUNKSIZE;
$got = 0 unless $self->write($c, $buffer );
} while $got > 0;
close $body;
return;
} else {
# Looks like for backcompat reasons we need to be able to deal
# with stringyfiable objects.
$body = ["$body"];
}
} elsif(ref $body) {
if( (ref($body) eq 'GLOB') or (ref($body) eq 'ARRAY')) {
# Again, PSGI can just accept this, no transform needed. We don't officially
# document the body as arrayref at this time (and there's not specific test
# cases. we support it because it simplifies some plack compatibility logic
# and we might make it official at some point.
( run in 0.803 second using v1.01-cache-2.11-cpan-39bf76dae61 )