X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FEngine.pm;h=c881d554740fd9c7b1d08638edfb285ddf19b71e;hb=1565e158ff4a868e199a99b779e6669ca1d9c53c;hp=c51640905f65de227ea92fed9b3fcb8a6615d27c;hpb=b21bc4683a90d1d69b295b51472b95b269fb0ad5;p=catagits%2FCatalyst-Runtime.git
diff --git a/lib/Catalyst/Engine.pm b/lib/Catalyst/Engine.pm
index c516409..c881d55 100644
--- a/lib/Catalyst/Engine.pm
+++ b/lib/Catalyst/Engine.pm
@@ -48,10 +48,12 @@ sub finalize_body {
my $body = $c->response->body;
no warnings 'uninitialized';
if ( blessed($body) && $body->can('read') or ref($body) eq 'GLOB' ) {
- while ( !eof $body ) {
- read $body, my ($buffer), $CHUNKSIZE;
- last unless $self->write( $c, $buffer );
- }
+ my $got;
+ do {
+ $got = read $body, my ($buffer), $CHUNKSIZE;
+ $got = 0 unless $self->write( $c, $buffer );
+ } while $got > 0;
+
close $body;
}
else {
@@ -106,11 +108,29 @@ is in debug mode, or a `please come back later` message otherwise.
=cut
+sub _dump_error_page_element {
+ my ($self, $i, $element) = @_;
+ my ($name, $val) = @{ $element };
+
+ # This is fugly, but the metaclass is _HUGE_ and demands waaay too much
+ # scrolling. Suggestions for more pleasant ways to do this welcome.
+ local $val->{'__MOP__'} = "Stringified: "
+ . $val->{'__MOP__'} if ref $val eq 'HASH' && exists $val->{'__MOP__'};
+
+ my $text = encode_entities( dump( $val ));
+ sprintf <<"EOF", $name, $text;
+
+
+EOF
+}
+
sub finalize_error {
my ( $self, $c ) = @_;
$c->res->content_type('text/html; charset=utf-8');
- my $name = $c->config->{name} || join(' ', split('::', ref $c));
+ my $name = ref($c)->config->{name} || join(' ', split('::', ref $c));
my ( $title, $error, $infos );
if ( $c->debug ) {
@@ -136,14 +156,7 @@ sub finalize_error {
my @infos;
my $i = 0;
for my $dump ( $c->dump_these ) {
- my $name = $dump->[0];
- my $value = encode_entities( dump( $dump->[1] ));
- push @infos, sprintf <<"EOF", $name, $value;
-
-
-EOF
+ push @infos, $self->_dump_error_page_element($i, $dump);
$i++;
}
$infos = join "\n", @infos;
@@ -248,7 +261,7 @@ EOF
}
/* from http://users.tkk.fi/~tkarvine/linux/doc/pre-wrap/pre-wrap-css3-mozilla-opera-ie.html */
/* Browser specific (not valid) styles to make preformatted text wrap */
- pre {
+ pre {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
@@ -315,16 +328,18 @@ sets up the L object body using L
sub prepare_body {
my ( $self, $c ) = @_;
+ my $appclass = ref($c) || $c;
if ( my $length = $self->read_length ) {
my $request = $c->request;
unless ( $request->_body ) {
my $type = $request->header('Content-Type');
$request->_body(HTTP::Body->new( $type, $length ));
- $request->_body->tmpdir( $c->config->{uploadtmp} )
- if exists $c->config->{uploadtmp};
+ $request->_body->tmpdir( $appclass->config->{uploadtmp} )
+ if exists $appclass->config->{uploadtmp};
}
-
- while ( my $buffer = $self->read($c) ) {
+
+ # Check for definedness as you could read '0'
+ while ( defined ( my $buffer = $self->read($c) ) ) {
$c->prepare_body_chunk($buffer);
}
@@ -356,15 +371,15 @@ sub prepare_body_chunk {
=head2 $self->prepare_body_parameters($c)
-Sets up parameters from body.
+Sets up parameters from body.
=cut
sub prepare_body_parameters {
my ( $self, $c ) = @_;
-
+
return unless $c->request->_body;
-
+
$c->request->body_parameters( $c->request->_body->param );
}
@@ -444,7 +459,7 @@ process the query string and extract query parameters.
sub prepare_query_parameters {
my ( $self, $c, $query_string ) = @_;
-
+
# Check for keywords (no = signs)
# (yes, index() is faster than a regex :))
if ( index( $query_string, '=' ) < 0 ) {
@@ -456,17 +471,17 @@ sub prepare_query_parameters {
# replace semi-colons
$query_string =~ s/;/&/g;
-
+
my @params = grep { length $_ } split /&/, $query_string;
for my $item ( @params ) {
-
- my ($param, $value)
+
+ my ($param, $value)
= map { $self->unescape_uri($_) }
split( /=/, $item, 2 );
-
+
$param = $self->unescape_uri($item) unless defined $param;
-
+
if ( exists $query{$param} ) {
if ( ref $query{$param} ) {
push @{ $query{$param} }, $value;
@@ -494,7 +509,7 @@ sub prepare_read {
# Initialize the read position
$self->read_position(0);
-
+
# Initialize the amount of data we think we need to read
$self->read_length( $c->request->header('Content-Length') || 0 );
}
@@ -563,6 +578,10 @@ sub prepare_write { }
=head2 $self->read($c, [$maxlength])
+Reads from the input stream by calling C<< $self->read_chunk >>.
+
+Maintains the read_length and read_position counters as data is read.
+
=cut
sub read {
@@ -580,6 +599,11 @@ sub read {
my $readlen = ( $remaining > $maxlength ) ? $maxlength : $remaining;
my $rc = $self->read_chunk( $c, my $buffer, $readlen );
if ( defined $rc ) {
+ if (0 == $rc) { # Nothing more to read even though Content-Length
+ # said there should be. FIXME - Warn in the log here?
+ $self->finalize_read;
+ return;
+ }
$self->read_position( $self->read_position + $rc );
return $buffer;
}
@@ -592,7 +616,8 @@ sub read {
=head2 $self->read_chunk($c, $buffer, $length)
Each engine implements read_chunk as its preferred way of reading a chunk
-of data.
+of data. Returns the number of bytes read. A return of 0 indicates that
+there is no more data to be read.
=cut
@@ -628,17 +653,17 @@ sub write {
$self->prepare_write($c);
$self->_prepared_write(1);
}
-
+
return 0 if !defined $buffer;
-
+
my $len = length($buffer);
my $wrote = syswrite STDOUT, $buffer;
-
+
if ( !defined $wrote && $! == EWOULDBLOCK ) {
# Unable to write on the first try, will retry in the loop below
$wrote = 0;
}
-
+
if ( defined $wrote && $wrote < $len ) {
# We didn't write the whole buffer
while (1) {
@@ -650,11 +675,11 @@ sub write {
next if $! == EWOULDBLOCK;
return;
}
-
+
last if $wrote >= $len;
}
}
-
+
return $wrote;
}
@@ -695,7 +720,7 @@ Catalyst Contributors, see Catalyst.pm
=head1 COPYRIGHT
-This program is free software, you can redistribute it and/or modify it under
+This library is free software. You can redistribute it and/or modify it under
the same terms as Perl itself.
=cut