AnyEvent-HTTPD-ExtDirect
view release on metacpan or search on metacpan
lib/AnyEvent/HTTPD/ExtDirect.pm view on Meta::CPAN
# Pluck all parameters from the Request object
for my $param ( $req->params ) {
my @values = $req->param($param);
$keyword{ $param } = @values == 0 ? undef
: @values == 1 ? $values[0]
: [ @values ]
;
};
# Find all file uploads
for ( $has_uploads ? ($has_uploads) : () ) {
# The list of fields that contain file uploads
my @upload_fields = $req->upload_fields;
last unless @upload_fields;
my @uploaded_files;
for my $field_name ( @upload_fields ) {
my $uploads = $req->raw_param($field_name);
# We need files as a formatted list
my @field_uploads = map { $self->_format_upload($_) } @$uploads;
push @uploaded_files, @field_uploads;
# Now remove the field that contained files
delete @keyword{ $field_name };
}
$keyword{ '_uploads' } = \@uploaded_files if @uploaded_files;
};
# Metadata is JSON encoded; decode_metadata lives by side effects!
if ( exists $keyword{metadata} ) {
RPC::ExtDirect::Util::decode_metadata($self, \%keyword);
}
# Remove extType because it's meaningless later on
delete $keyword{ extType };
# Fix TID so that it comes as number (JavaScript is picky)
$keyword{ extTID } += 0 if exists $keyword{ extTID };
return \%keyword;
}
### PRIVATE INSTANCE METHOD ###
#
# Take the file content and metadata and format it in a way
# that RPC::ExtDirect handlers expect
#
sub _format_upload {
my ($self, $upload) = @_;
my $content_length = do { use bytes; length $upload->[0] };
my ($fh, $fname) = File::Temp::tempfile;
binmode $fh;
syswrite $fh, $upload->[0], $content_length;
sysseek $fh, 0, 0;
# We don't need the file content anymore, so try to release
# the memory it takes
$upload->[0] = undef;
my $filename = $upload->[2];
my $basename = File::Basename::basename($filename);
my $type = $upload->[1];
my $handle = IO::File->new_from_fd($fh->fileno, '<');
return {
filename => $filename,
basename => $basename,
type => $type,
size => $content_length,
path => $fname,
handle => $handle,
};
}
### PRIVATE INSTANCE METHOD ###
#
# Return an error response formatted to AnyEvent::HTTPD likes
#
sub _error_response {
[ 500, 'Internal Server Error', { 'Content-Type' => 'text/html' }, '' ]
}
package
AnyEvent::HTTPD::ExtDirect::Env;
use parent 'AnyEvent::HTTPD::Request';
#
# AnyEvent::HTTPD::Request stores the form parameters in a peculiar format:
# $self->{parm} is a hashref of arrayrefs; each arrayref contain one
# or more values, again in arrayrefs with fixed number of items:
# [ content, content-type, file-name ]
#
# For anything but file uploads, the last 2 elements are undef; for the
# file uploads they're the file MIME type and name, respectively.
#
# A dump might look like this:
#
# $self->{parm}:
# 0 HASH
# 'formFieldName' => ARRAY
# 0 ARRAY =>
# 0 'form field value'
# 1 undef
# 2 undef
# 'fieldWithMultipleValues' => ARRAY # SURMISED!
# 0 ARRAY =>
# 0 'form field value 0'
# 1 undef
# 2 undef
( run in 3.211 seconds using v1.01-cache-2.11-cpan-8f98c5d2c55 )