use strict;
use base 'Class::Accessor::Fast';
-use CGI::Cookie;
+use CGI::Simple::Cookie;
use Data::Dump qw/dump/;
use HTML::Entities;
use HTTP::Body;
use HTTP::Headers;
use URI::QueryParam;
+use Scalar::Util ();
# input position and length
__PACKAGE__->mk_accessors(qw/read_position read_length/);
use overload '""' => sub { return ref shift }, fallback => 1;
# Amount of data to read from input on each pass
-our $CHUNKSIZE = 4096;
+our $CHUNKSIZE = 64 * 1024;
=head1 NAME
sub finalize_body {
my ( $self, $c ) = @_;
my $body = $c->response->body;
- if ( ref $body && ( $body->can('read') || ref($body) eq 'GLOB' ) ) {
+ no warnings 'uninitialized';
+ if ( Scalar::Util::blessed($body) && $body->can('read') or ref($body) eq 'GLOB' ) {
while ( !eof $body ) {
read $body, my ($buffer), $CHUNKSIZE;
last unless $self->write( $c, $buffer );
=head2 $self->finalize_cookies($c)
-Create CGI::Cookies from $c->res->cookies, and set them as response headers.
+Create CGI::Simple::Cookie objects from $c->res->cookies, and set them as
+response headers.
=cut
my $val = $c->response->cookies->{$name};
- my $cookie = CGI::Cookie->new(
- -name => $name,
- -value => $val->{value},
- -expires => $val->{expires},
- -domain => $val->{domain},
- -path => $val->{path},
- -secure => $val->{secure} || 0
+ my $cookie = (
+ Scalar::Util::blessed($val)
+ ? $val
+ : CGI::Simple::Cookie->new(
+ -name => $name,
+ -value => $val->{value},
+ -expires => $val->{expires},
+ -domain => $val->{domain},
+ -path => $val->{path},
+ -secure => $val->{secure} || 0
+ )
);
push @cookies, $cookie->as_string;
sub prepare_body {
my ( $self, $c ) = @_;
+
+ my $length = $c->request->header('Content-Length') || 0;
- $self->read_length( $c->request->header('Content-Length') || 0 );
- my $type = $c->request->header('Content-Type');
+ $self->read_length( $length );
- unless ( $c->request->{_body} ) {
- $c->request->{_body} = HTTP::Body->new( $type, $self->read_length );
- $c->request->{_body}->{tmpdir} = $c->config->{uploadtmp}
- if exists $c->config->{uploadtmp};
- }
-
- if ( $self->read_length > 0 ) {
+ if ( $length > 0 ) {
+ unless ( $c->request->{_body} ) {
+ my $type = $c->request->header('Content-Type');
+ $c->request->{_body} = HTTP::Body->new( $type, $length );
+ $c->request->{_body}->{tmpdir} = $c->config->{uploadtmp}
+ if exists $c->config->{uploadtmp};
+ }
+
while ( my $buffer = $self->read($c) ) {
$c->prepare_body_chunk($buffer);
}
# paranoia against wrong Content-Length header
- my $remaining = $self->read_length - $self->read_position;
+ my $remaining = $length - $self->read_position;
if ( $remaining > 0 ) {
$self->finalize_read($c);
Catalyst::Exception->throw(
- "Wrong Content-Length value: " . $self->read_length );
+ "Wrong Content-Length value: $length" );
}
}
+ else {
+ # Defined but will cause all body code to be skipped
+ $c->request->{_body} = 0;
+ }
}
=head2 $self->prepare_body_chunk($c)
sub prepare_body_parameters {
my ( $self, $c ) = @_;
+
+ return unless $c->request->{_body};
+
$c->request->body_parameters( $c->request->{_body}->param );
}
=head2 $self->prepare_cookies($c)
-Parse cookies from header. Sets a L<CGI::Cookie> object.
+Parse cookies from header. Sets a L<CGI::Simple::Cookie> object.
=cut
my ( $self, $c ) = @_;
if ( my $header = $c->request->header('Cookie') ) {
- $c->req->cookies( { CGI::Cookie->parse($header) } );
+ $c->req->cookies( { CGI::Simple::Cookie->parse($header) } );
}
}
sub prepare_uploads {
my ( $self, $c ) = @_;
+
+ return unless $c->request->{_body};
+
my $uploads = $c->request->{_body}->upload;
for my $name ( keys %$uploads ) {
my $files = $uploads->{$name};
# support access to the filename as a normal param
my @filenames = map { $_->{filename} } @uploads;
- $c->request->parameters->{$name} =
- @filenames > 1 ? \@filenames : $filenames[0];
+ # append, if there's already params with this name
+ if (exists $c->request->parameters->{$name}) {
+ if (ref $c->request->parameters->{$name} eq 'ARRAY') {
+ push @{ $c->request->parameters->{$name} }, @filenames;
+ }
+ else {
+ $c->request->parameters->{$name} =
+ [ $c->request->parameters->{$name}, @filenames ];
+ }
+ }
+ else {
+ $c->request->parameters->{$name} =
+ @filenames > 1 ? \@filenames : $filenames[0];
+ }
}
}