Skip to content

Commit

Permalink
added experimental upgrade and part events to content objects
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Oct 19, 2011
1 parent 687fe3d commit 590e098
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 5 deletions.
2 changes: 2 additions & 0 deletions Changes
@@ -1,6 +1,8 @@
This file documents the revision history for Perl extension Mojolicious.

2.01 2011-10-19 00:00:00
- Added EXPERIMENTAL upgrade event to Mojo::Content::Single.
- Added EXPERIMENTAL part event to Mojo::Content::MultiPart.
- Improved documentation.

2.0 2011-10-17 00:00:00
Expand Down
15 changes: 13 additions & 2 deletions lib/Mojo/Content/MultiPart.pm
Expand Up @@ -195,7 +195,8 @@ sub _parse_multipart_boundary {
substr $self->{buffer}, 0, length($boundary) + 6, '';

# New part
push @{$self->parts}, Mojo::Content::Single->new(relaxed => 1);
$self->emit(part => my $part = Mojo::Content::Single->new(relaxed => 1));
push @{$self->parts}, $part;
$self->{multi_state} = 'multipart_body';
return 1;
}
Expand Down Expand Up @@ -251,7 +252,17 @@ described in RFC 2616.
=head1 EVENTS
L<Mojo::Content::Multipart> inherits all events from L<Mojo::Content>.
L<Mojo::Content::Multipart> inherits all events from L<Mojo::Content> and can
emit the following new ones.
=head2 C<part>
$content->on(part => sub {
my ($content, $part) = @_;
});
Emitted when a new part starts.
Note that this event is EXPERIMENTAL and might change without warning!
=head1 ATTRIBUTES
Expand Down
16 changes: 14 additions & 2 deletions lib/Mojo/Content/Single.pm
Expand Up @@ -49,7 +49,9 @@ sub parse {
# Content needs to be upgraded to multipart
if ($self->auto_upgrade && defined($self->boundary)) {
return $self if $self->isa('Mojo::Content::MultiPart');
return Mojo::Content::MultiPart->new($self)->parse;
my $multipart = Mojo::Content::MultiPart->new($self)->parse;
$self->emit(upgrade => $multipart);
return $multipart;
}

# Don't waste memory and upgrade to file based storage on demand
Expand Down Expand Up @@ -98,7 +100,17 @@ RFC 2616.
=head1 EVENTS
L<Mojo::Content::Single> inherits all events from L<Mojo::Content>.
L<Mojo::Content::Single> inherits all events from L<Mojo::Content> and can
emit the following new ones.
=head2 C<upgrade>
$content->on(upgrade => sub {
my ($content, $multipart) = @_;
});
Emitted when content gets upgraded.
Note that this event is EXPERIMENTAL and might change without warning!
=head1 ATTRIBUTES
Expand Down
83 changes: 82 additions & 1 deletion t/mojo/message.t
Expand Up @@ -3,7 +3,7 @@ use Mojo::Base -strict;

use utf8;

use Test::More tests => 1236;
use Test::More tests => 1258;

use File::Spec;
use File::Temp;
Expand Down Expand Up @@ -640,6 +640,87 @@ my $file = File::Spec->catfile(File::Temp::tempdir(CLEANUP => 1),
ok $req->upload('upload')->move_to($file), 'moved file';
is unlink($file), 1, 'unlinked file';

# Parse HTTP 1.1 multipart request (with callbacks and stream)
$req = Mojo::Message::Request->new;
my $stream = '';
$req->content->on(
body => sub {
my $content = shift;
$content->on(
upgrade => sub {
my ($content, $multipart) = @_;
$multipart->on(
part => sub {
my ($multipart, $part) = @_;
$part->on(
body => sub {
my $part = shift;
return
unless $part->headers->content_disposition =~ /hello\.pl/;
$part->on(
read => sub {
my ($part, $chunk) = @_;
$stream .= $chunk;
}
);
}
);
}
);
}
);
}
);
$req->parse("GET /foo/bar/baz.html?foo13#23 HTTP/1.1\x0d\x0a");
$req->parse("Content-Length: 418\x0d\x0a");
$req->parse('Content-Type: multipart/form-data; bo');
$req->parse("undary=----------0xKhTmLbOuNdArY\x0d\x0a\x0d\x0a");
$req->parse("\x0d\x0a------------0xKhTmLbOuNdArY\x0d\x0a");
$req->parse("Content-Disposition: form-data; name=\"text1\"\x0d\x0a");
$req->parse("\x0d\x0ahallo welt test123\n");
$req->parse("\x0d\x0a------------0xKhTmLbOuNdArY\x0d\x0a");
$req->parse("Content-Disposition: form-data; name=\"text2\"\x0d\x0a");
$req->parse("\x0d\x0a\x0d\x0a------------0xKhTmLbOuNdArY\x0d\x0a");
$req->parse('Content-Disposition: form-data; name="upload"; file');
$req->parse("name=\"hello.pl\"\x0d\x0a");
$req->parse("Content-Type: application/octet-stream\x0d\x0a\x0d\x0a");
is $stream, '', 'no content';
$req->parse("#!/usr/bin/perl\n\n");
is $stream, '', 'no content';
$req->parse("use strict;\n");
is $stream, '', 'no content';
$req->parse("use warnings;\n\n");
is $stream, '#!/usr/bin/', 'right content';
$req->parse("print \"Hello World :)\\n\"\n");
is $stream, "#!/usr/bin/perl\n\nuse strict;\nuse war", 'right content';
$req->parse("\x0d\x0a------------0xKhTmLbOuNdArY--");
ok $req->is_done, 'request is done';
is $req->is_multipart, 1, 'multipart content';
is $req->method, 'GET', 'right method';
is $req->version, '1.1', 'right version';
is $req->at_least_version('1.0'), 1, 'at least version 1.0';
is $req->at_least_version('1.2'), undef, 'not version 1.2';
is $req->url, '/foo/bar/baz.html?foo13#23', 'right URL';
is $req->query_params, 'foo13', 'right parameters';
is $req->headers->content_type,
'multipart/form-data; boundary=----------0xKhTmLbOuNdArY',
'right "Content-Type" value';
is $req->headers->content_length, 418, 'right "Content-Type" value';
isa_ok $req->content->parts->[0], 'Mojo::Content::Single', 'right part';
isa_ok $req->content->parts->[1], 'Mojo::Content::Single', 'right part';
isa_ok $req->content->parts->[2], 'Mojo::Content::Single', 'right part';
is $req->content->parts->[0]->asset->slurp, "hallo welt test123\n",
'right content';
is_deeply $req->body_params->to_hash->{text1}, "hallo welt test123\n",
'right value';
is_deeply $req->body_params->to_hash->{text2}, '', 'right value';
is $stream,
"#!/usr/bin/perl\n\n"
. "use strict;\n"
. "use warnings;\n\n"
. "print \"Hello World :)\\n\"\n",
'right content';

# Parse HTTP 1.1 multipart request (without upgrade)
$req = Mojo::Message::Request->new;
$req->content->auto_upgrade(0);
Expand Down

0 comments on commit 590e098

Please sign in to comment.