Skip to content

Commit

Permalink
added input streaming support to Mojo::Content
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Nov 2, 2009
1 parent c745381 commit 717333d
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 12 deletions.
1 change: 1 addition & 0 deletions Changes
Expand Up @@ -20,6 +20,7 @@ This file documents the revision history for Perl extension Mojo.
- Added callback tests. (melo)
- Added support for MOJO_CHUNK_SIZE=1. (melo)
- Added not_found.html.* templates.
- Added input streaming support to Mojo::Content.
- Updated Mojolicious lite_app generator to use .ep templates.
- Fixed param to be CGI.pm compatible.
- Fixed a few cases where exceptions and not found events would
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/Command/Cgi.pm
Expand Up @@ -33,7 +33,7 @@ sub run {
# Run
$cgi->run;

return shift;
return $self;
}

1;
Expand Down
84 changes: 84 additions & 0 deletions lib/Mojo/Command/Get.pm
@@ -0,0 +1,84 @@
# Copyright (C) 2008-2009, Sebastian Riedel.

package Mojo::Command::Get;

use strict;
use warnings;

use base 'Mojo::Command';

use Mojo::Client;
use Mojo::Transaction::Single;

__PACKAGE__->attr(description => <<'EOF');
Get file from URL.
EOF
__PACKAGE__->attr(usage => <<"EOF");
usage: $0 get [URL]
EOF

# I hope this has taught you kids a lesson: kids never learn.
sub run {
my ($self, $url) = @_;

# URL
die $self->usage unless $url;

# Client
my $client = Mojo::Client->new;

# Transaction
my $tx = Mojo::Transaction::Single->new;
$tx->req->method('GET');
$tx->req->url->parse($url);
$tx->res->body(sub { print $_[1] });

# Request
$client->process($tx);

return $self;
}

1;
__END__
=head1 NAME
Mojo::Command::Get - Get Command
=head1 SYNOPSIS
use Mojo::Command::Get;
my $get = Mojo::Command::Get->new;
$get->run(@ARGV);
=head1 DESCRIPTION
L<Mojo::Command::Get> is a command interface to L<Mojo::Client>.
=head1 ATTRIBUTES
L<Mojo::Command::Get> inherits all attributes from L<Mojo::Command> and
implements the following new ones.
=head2 C<description>
my $description = $get->description;
$get = $get->description('Foo!');
=head2 C<usage>
my $usage = $get->usage;
$get = $get->usage('Foo!');
=head1 METHODS
L<Mojo::Command::Get> inherits all methods from L<Mojo::Command> and implements
the following new ones.
=head2 C<run>
$get = $get->run(@ARGV);
=cut
39 changes: 39 additions & 0 deletions lib/Mojo/Content.pm
Expand Up @@ -19,7 +19,9 @@ __PACKAGE__->attr([qw/body_cb filter progress_cb/]);
__PACKAGE__->attr([qw/buffer filter_buffer/] => sub { Mojo::Buffer->new });
__PACKAGE__->attr(headers => sub { Mojo::Headers->new });
__PACKAGE__->attr(raw_header_size => 0);
__PACKAGE__->attr(relaxed => 0);

__PACKAGE__->attr(_body_size => 0);
__PACKAGE__->attr('_eof');

sub body_contains {
Expand Down Expand Up @@ -180,6 +182,38 @@ sub parse {
# Not chunked, pass through
else { $self->buffer($self->filter_buffer) }

# Custom body parser
if (my $cb = $self->body_cb) {

# Chunked or relaxed content
if ($self->is_chunked || $self->relaxed) {
$self->$cb($self->buffer->empty);
}

# Normal content
else {

# Need
my $length = $self->headers->content_length || 0;
my $need = $length - $self->_body_size;

# Slurp
if ($need > 0) {
my $chunk = $self->buffer->remove($need);
$self->_body_size($self->_body_size + length $chunk);
$self->$cb($chunk);
}

# Done
$self->done if $length <= $self->raw_body_size;
}
}

# Leftovers
if ($self->is_done) {
$self->state('done_with_leftovers') if $self->has_leftovers;
}

return $self;
}

Expand Down Expand Up @@ -294,6 +328,11 @@ implements the following new ones.
print '+';
});
=head2 C<relaxed>
my $relaxed = $content->relaxed;
$content = $content->relaxed(1);
=head2 C<raw_header_size>
my $size = $content->raw_header_size;
Expand Down
10 changes: 7 additions & 3 deletions lib/Mojo/Content/MultiPart.pm
Expand Up @@ -128,12 +128,16 @@ sub get_body_chunk {
sub parse {
my $self = shift;

# Upgrade state
$self->state('multipart_preamble') if $self->is_state('body');

# Parse headers and filter body
$self->SUPER::parse(@_);

# Custom body parser
return $self if $self->body_cb;

# Upgrade state
$self->state('multipart_preamble') if $self->is_state('body');

# Parse multipart content
$self->_parse_multipart;

return $self;
Expand Down
10 changes: 2 additions & 8 deletions lib/Mojo/Content/Single.pm
Expand Up @@ -15,7 +15,6 @@ use Mojo::Content::MultiPart;
use constant MAX_MEMORY_SIZE => $ENV{MOJO_MAX_MEMORY_SIZE} || 10240;

__PACKAGE__->attr(asset => sub { Mojo::Asset::Memory->new });
__PACKAGE__->attr(relaxed => 0);

sub body_contains {
my ($self, $chunk) = @_;
Expand Down Expand Up @@ -48,8 +47,8 @@ sub parse {
# Parse headers and filter body
$self->SUPER::parse(@_);

# Still parsing headers
return $self if $self->is_state('headers');
# Still parsing headers or using a custom body parser
return $self if $self->is_state('headers') || $self->body_cb;

# Make sure we don't waste memory
if ($self->asset->isa('Mojo::Asset::Memory')) {
Expand Down Expand Up @@ -121,11 +120,6 @@ implements the following new ones.
my $asset = $content->asset;
$content = $content->asset(Mojo::Asset::Memory->new);
=head2 C<relaxed>
my $relaxed = $content->relaxed;
$content = $content->relaxed(1);
=head1 METHODS
L<Mojo::Content::Single> inherits all methods from L<Mojo::Content> and
Expand Down

0 comments on commit 717333d

Please sign in to comment.