Permalink
Browse files

Copied Plack::Request, Response and its tests from Plack-Request dist.

Tests are adjusted to work with Plack::Test or standalone. All tests
are unmodified YET, to make all the backward incompatilbe changes can
be visible from now on, on this 'plack-request' branch.
  • Loading branch information...
1 parent 04a11b6 commit c3b071823cccdcead9807381e7517d9237eaa3cc @miyagawa miyagawa committed Jan 20, 2010
View
Oops, something went wrong.
@@ -0,0 +1,105 @@
+package Plack::Request::BodyParser;
+use strict;
+use warnings;
+BEGIN { require Carp }; # do not call Carp->import for performance
+use HTTP::Body;
+
+# ABOUT: This is internal class. Do not call directly.
+
+sub new {
+ my($class, $env) = @_;
+
+ Carp::confess q{Attribute ($env->{'psgi.input'}) is required}
+ unless defined $env->{'psgi.input'};
+
+ bless {
+ content_length => $env->{'CONTENT_LENGTH'} || 0,
+ content_type => $env->{'CONTENT_TYPE'} || '',
+ input_handle => $env->{'psgi.input'},
+ _read_position => 0,
+ chunk_size => 4096,
+ }, $class;
+}
+
+# tempolary file path for upload file.
+sub upload_tmp {
+ $_[0]->{upload_tmp} = defined $_[1] ? $_[1] : $_[0]->{upload_tmp};
+}
+
+sub http_body {
+ my ( $self, ) = @_;
+
+ $self->_read_to_end();
+ return $self->_http_body;
+}
+
+sub raw_body {
+ my ( $self, ) = @_;
+
+ $self->_read_to_end();
+ return $self->{_raw_body};
+}
+
+sub _http_body {
+ my($self, ) = @_;
+ unless (defined $self->{_http_body}) {
+ my $body = HTTP::Body->new($self->{content_type}, $self->{content_length});
+ $body->tmpdir( $self->upload_tmp ) if $self->upload_tmp;
+ $self->{_http_body} = $body;
+ }
+ $self->{_http_body};
+}
+
+sub _read_position { $_[0]->{_read_position} }
+
+sub input_handle { $_[0]->{input_handle} }
+
+sub _read_to_end {
+ my ( $self, ) = @_;
+
+ my $content_length = $self->{content_length};
+
+ if ($content_length > 0) {
+ while (my $buffer = $self->_read() ) {
+ $self->{_raw_body} .= $buffer;
+ $self->_http_body->add($buffer);
+ }
+
+ # paranoia against wrong Content-Length header
+ my $diff = $content_length - $self->_read_position;
+
+ if ($diff != 0) {
+ if ( $diff > 0) {
+ die "Wrong Content-Length value: " . $content_length;
+ } else {
+ die "Premature end of request body, $diff bytes remaining";
+ }
+ }
+ }
+}
+
+sub _read {
+ my ($self, ) = @_;
+
+ my $remaining = $self->{content_length} - $self->_read_position();
+
+ my $maxlength = $self->{chunk_size};
+
+ # Are we done reading?
+ if ($remaining <= 0) {
+ return;
+ }
+
+ my $readlen = ($remaining > $maxlength) ? $maxlength : $remaining;
+
+ my $rc = $self->input_handle->read(my $buffer, $readlen);
+
+ if (defined $rc) {
+ $self->{_read_position} += $rc;
+ return $buffer;
+ } else {
+ die "Unknown error reading input: $!";
+ }
+}
+
+1;
View
@@ -0,0 +1,126 @@
+package Plack::Request::Upload;
+use strict;
+use warnings;
+BEGIN { require Carp }; # do not call Carp->import for performance
+
+sub new {
+ my($class, %args) = @_;
+
+ bless {
+ headers => $args{headers},
+ tempname => $args{tempname},
+ size => $args{size},
+ filename => $args{filename},
+ }, $class;
+}
+
+sub filename { $_[0]->{filename} }
+sub headers { $_[0]->{headers} }
+sub size { $_[0]->{size} }
+sub tempname { $_[0]->{tempname} }
+
+sub type {
+ my $self = shift;
+ unless ($self->{headers} && $self->{headers}->can('content_type')) {
+ Carp::croak 'Cannot delegate type to content_type because the value of headers is not defined';
+ }
+ $self->{headers}->content_type(@_);
+}
+
+sub basename {
+ my $self = shift;
+ unless (defined $self->{basename}) {
+ require File::Spec::Unix;
+ my $basename = $self->{filename};
+ $basename =~ s|\\|/|g;
+ $basename = ( File::Spec::Unix->splitpath($basename) )[2];
+ $basename =~ s|[^\w\.-]+|_|g;
+ $self->{basename} = $basename;
+ }
+ $self->{basename};
+}
+
+sub fh {
+ my $self = shift;
+ unless (defined $self->{fh}) {
+ open my $fh, '<', $self->{tempname} or die "Can't open '@{[ $self->tempname ]}': '$!'";
+ $self->{fh} = $fh;
+ }
+ $self->{fh};
+}
+
+sub copy_to {
+ my $self = shift;
+ require File::Copy;
+ File::Copy::copy( $self->{tempname}, @_ );
+}
+
+sub link_to {
+ my ( $self, $target ) = @_;
+ CORE::link( $self->{tempname}, $target );
+}
+
+sub slurp {
+ my ( $self, $layer ) = @_;
+
+ $layer = ':raw' unless $layer;
+
+ my $content = undef;
+ my $handle = $self->fh;
+
+ binmode( $handle, $layer );
+
+ while ( $handle->read( my $buffer, 8192 ) ) {
+ $content .= $buffer;
+ }
+
+ $content;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Plack::Request::Upload - handles file upload requests
+
+=head1 METHODS
+
+=over 4
+
+=item basename
+
+Returns basename for "filename".
+
+=item link_to
+
+Creates a hard link to the temporary file. Returns true for success,
+false for failure.
+
+ $upload->link_to('/path/to/target');
+
+=item slurp
+
+Returns a scalar containing the contents of the temporary file.
+
+=item copy_to
+
+Copies the temporary file using File::Copy. Returns true for success,
+false for failure.
+
+ $upload->copy_to('/path/to/targe')
+
+=back
+
+=head1 AUTHORS
+
+Kazuhiro Osawa and Plack authors.
+
+=head1 THANKS TO
+
+the authors of L<Catalyst::Request::Upload>.
+
+=head1 SEE ALSO
+
+L<Plack>, L<Catalyst::Request::Upload>
+
Oops, something went wrong.

0 comments on commit c3b0718

Please sign in to comment.