Skip to content

Commit

Permalink
renamed Mojo::IOLoop::EventEmitter to Mojo::EventEmitter and improved…
Browse files Browse the repository at this point in the history
… many modules to use events instead of callbacks
  • Loading branch information
kraih committed Oct 10, 2011
1 parent a0b3338 commit a5fb3ea
Show file tree
Hide file tree
Showing 30 changed files with 636 additions and 413 deletions.
4 changes: 3 additions & 1 deletion Changes
@@ -1,12 +1,14 @@
This file documents the revision history for Perl extension Mojolicious.

2.0 2011-10-10 00:00:00
2.0 2011-10-11 00:00:00
- Code name "Leaf Fluttering In Wind", this is a major release.
- Increased Perl version requirement to 5.10.1.
- Renamed Mojo::IOLoop::EventEmitter to Mojo::EventEmitter.
- Added EXPERIMENTAL on_body attribute to Mojo::Content.
- Added EXPERIMENTAL contains method to Mojo::Path.
- Added EXPERIMENTAL auto_upgrade attribute to Mojo::Content::Single.
- Added EXPERIMENTAL boundary method to Mojo::Content.
- Improved many modules to use events instead of callbacks.
- Improved message parser performance slightly.
- Improved Mojo::IOLoop to die if started twice.
- Improved setuidgid in Mojo::Server::Daemon.
Expand Down
42 changes: 19 additions & 23 deletions lib/Mojo.pm
Expand Up @@ -10,13 +10,7 @@ use Scalar::Util 'weaken';

has home => sub { Mojo::Home->new };
has log => sub { Mojo::Log->new };
has on_transaction => sub {
sub { Mojo::Transaction::HTTP->new }
};
has on_websocket => sub {
sub { Mojo::Transaction::WebSocket->new(handshake => pop) }
};
has ua => sub {
has ua => sub {
my $self = shift;

# Fresh user agent
Expand Down Expand Up @@ -44,6 +38,10 @@ sub new {
# "D’oh."
sub handler { croak 'Method "handler" not implemented in subclass' }

sub transaction { Mojo::Transaction::HTTP->new }

sub upgrade { Mojo::Transaction::WebSocket->new(handshake => pop) }

1;
__END__
Expand Down Expand Up @@ -105,22 +103,6 @@ The logging layer of your application, defaults to a L<Mojo::Log> object.
$app->log->debug('It works!');
=head2 C<on_transaction>
my $cb = $app->on_transaction;
$app = $app->on_transaction(sub {...});
Callback to be invoked when a new transaction is needed, defaults to building
a L<Mojo::Transaction::HTTP> object.
=head2 C<on_websocket>
my $cb = $app->on_websocket;
$app = $app->on_websocket(sub {...});
Callback to be invoked for WebSocket handshakes, defaults to building a
L<Mojo::Transaction::WebSocket> object.
=head2 C<ua>
my $ua = $app->ua;
Expand Down Expand Up @@ -154,6 +136,20 @@ L<Mojo::Transaction::HTTP> or L<Mojo::Transaction::WebSocket> object.
my ($self, $tx) = @_;
}
=head2 C<transaction>
my $tx = $app->transaction;
Transaction builder, defaults to building a L<Mojo::Transaction::HTTP>
object.
=head2 C<upgrade>
my $ws = $app->upgrade(tx);
Upgrade transaction, defaults to building a L<Mojo::Transaction::WebSocket>
object.
=head1 SEE ALSO
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
Expand Down
87 changes: 53 additions & 34 deletions lib/Mojo/Content.pm
@@ -1,5 +1,5 @@
package Mojo::Content;
use Mojo::Base -base;
use Mojo::Base 'Mojo::EventEmitter';

use Carp 'croak';
use Mojo::Headers;
Expand All @@ -8,7 +8,6 @@ use constant CHUNK_SIZE => $ENV{MOJO_CHUNK_SIZE} || 131072;

has [qw/auto_relax relaxed/] => 0;
has headers => sub { Mojo::Headers->new };
has [qw/on_body on_read/];

sub body_contains {
croak 'Method "body_contains" not implemented by subclass';
Expand Down Expand Up @@ -81,7 +80,7 @@ sub clone {
sub generate_body_chunk {
my ($self, $offset) = @_;

# Callback
# Drain
if (!delete $self->{delay} && !length $self->{body_buffer}) {
my $cb = delete $self->{drain};
$self->$cb($offset) if $cb;
Expand Down Expand Up @@ -134,7 +133,7 @@ sub is_done {

sub is_dynamic {
my $self = shift;
return 1 if $self->on_read && !defined $self->headers->content_length;
return 1 if $self->{dynamic} && !defined $self->headers->content_length;
return;
}

Expand All @@ -156,6 +155,9 @@ sub leftovers {
return $self->{buffer};
}

sub on_body { shift->on(body => shift) }
sub on_read { shift->on(read => shift) }

sub parse {
my $self = shift;

Expand Down Expand Up @@ -188,12 +190,12 @@ sub parse {
$self->{buffer} .= delete $self->{pre_buffer};
}

# Custom body parser callback
if (my $cb = $self->on_read) {
# Custom body parser
if ($self->has_subscribers('read')) {

# Chunked or relaxed content
if ($self->is_chunked || $self->relaxed) {
$self->$cb($self->{buffer} //= '');
$self->emit(read => $self->{buffer} //= '');
$self->{buffer} = '';
}

Expand All @@ -209,7 +211,7 @@ sub parse {
if ($need > 0) {
my $chunk = substr $self->{buffer}, 0, $need, '';
$self->{size} = $self->{size} + length $chunk;
$self->$cb($chunk);
$self->emit(read => $chunk);
}

# Done
Expand Down Expand Up @@ -274,7 +276,7 @@ sub write {
my ($self, $chunk, $cb) = @_;

# Dynamic content
$self->on_read(sub { });
$self->{dynamic} = 1;

# Add chunk
if (defined $chunk) {
Expand All @@ -285,7 +287,7 @@ sub write {
# Delay
else { $self->{delay} = 1 }

# Drain callback
# Drain
$self->{drain} = $cb if $cb;

# Finish
Expand Down Expand Up @@ -404,7 +406,7 @@ sub _parse_headers {
$self->{header_size} = $self->{raw_size} - length $leftovers;
$self->{pre_buffer} = $leftovers;
$self->{state} = 'body';
if (my $cb = $self->on_body) { $self->$cb }
$self->emit('body');
}
}

Expand All @@ -424,6 +426,26 @@ Mojo::Content - HTTP 1.1 content base class
L<Mojo::Content> is an abstract base class for HTTP 1.1 content as described
in RFC 2616.
=head1 EVENTS
L<Mojo::Content> can emit the following events.
=head2 C<body>
$content->on(body => sub {
my $content = shift;
});
Emitted once all headers have been parsed and the content starts.
=head2 C<read>
$content->on(read => sub {
my ($content, $chunk) = @_;
});
Emitted when new content arrives.
=head1 ATTRIBUTES
L<Mojo::Content> implements the following attributes.
Expand All @@ -442,27 +464,6 @@ Try to detect broken web servers and turn on relaxed parsing automatically.
Content headers, defaults to a L<Mojo::Headers> object.
=head2 C<on_body>
my $cb = $content->on_body;
$content = $content->on_body(sub {...});
Callback to be invoked once all headers have been parsed and the content
starts.
Note that this attribute is EXPERIMENTAL and might change without warning!
=head2 C<on_read>
my $cb = $content->on_read;
$content = $content->on_read(sub {...});
Callback to be invoked when new content arrives.
$content = $content->on_read(sub {
my ($self, $chunk) = @_;
say $chunk;
});
=head2 C<relaxed>
my $relaxed = $content->relaxed;
Expand All @@ -472,8 +473,8 @@ Activate relaxed parsing for HTTP 0.9 and broken web servers.
=head1 METHODS
L<Mojo::Content> inherits all methods from L<Mojo::Base> and implements the
following new ones.
L<Mojo::Content> inherits all methods from L<Mojo::EventEmitter> and
implements the following new ones.
=head2 C<body_contains>
Expand Down Expand Up @@ -580,6 +581,24 @@ Check if body parsing started yet.
Remove leftover data from content parser.
=head2 C<on_body>
$content->on_body(sub {...});
Register C<body> event.
Note that this method is EXPERIMENTAL and might change without warning!
=head2 C<on_read>
$content->on_read(sub {...});
Register C<read> event.
$content->on_read(sub {
my ($self, $chunk) = @_;
say $chunk;
});
=head2 C<parse>
$content = $content->parse("Content-Length: 12\r\n\r\nHello World!");
Expand Down
8 changes: 6 additions & 2 deletions lib/Mojo/Content/MultiPart.pm
Expand Up @@ -89,7 +89,7 @@ sub get_body_chunk {
my ($self, $offset) = @_;

# Body generator
return $self->generate_body_chunk($offset) if $self->on_read;
return $self->generate_body_chunk($offset) if $self->{dynamic};

# First boundary
my $boundary = $self->build_boundary;
Expand Down Expand Up @@ -137,7 +137,7 @@ sub parse {
$self->SUPER::parse(@_);

# Custom body parser
return $self if $self->on_read;
return $self if $self->has_subscribers('read');

# Parse multipart content
$self->_parse_multipart;
Expand Down Expand Up @@ -254,6 +254,10 @@ Mojo::Content::MultiPart - HTTP 1.1 multipart content container
L<Mojo::Content::MultiPart> is a container for HTTP 1.1 multipart content as
described in RFC 2616.
=head1 EVENTS
L<Mojo::Content::Multipart> inherits all events from L<Mojo::Content>.
=head1 ATTRIBUTES
L<Mojo::Content::MultiPart> inherits all attributes from L<Mojo::Content>
Expand Down
12 changes: 9 additions & 3 deletions lib/Mojo/Content/Single.pm
Expand Up @@ -16,7 +16,7 @@ sub body_contains {

sub body_size {
my $self = shift;
return ($self->headers->content_length || 0) if $self->on_read;
return ($self->headers->content_length || 0) if $self->{dynamic};
return $self->asset->size;
}

Expand All @@ -31,7 +31,7 @@ sub get_body_chunk {
my ($self, $offset) = @_;

# Body generator
return $self->generate_body_chunk($offset) if $self->on_read;
return $self->generate_body_chunk($offset) if $self->{dynamic};

# Normal content
return $self->asset->get_chunk($offset);
Expand All @@ -44,7 +44,8 @@ sub parse {
$self->SUPER::parse(@_);

# Still parsing headers or using a custom body parser
return $self if ($self->{state} || '') eq 'headers' || $self->on_read;
return $self
if ($self->{state} || '') eq 'headers' || $self->has_subscribers('read');

# Content needs to be upgraded to multipart
if ($self->auto_upgrade && defined($self->boundary)) {
Expand Down Expand Up @@ -96,6 +97,11 @@ Mojo::Content::Single - HTTP 1.1 content container
L<Mojo::Content::Single> is a container for HTTP 1.1 content as described in
RFC 2616.
=head1 EVENTS
L<Mojo::Content::Single> inherits all events from L<Mojo::Content> and can
emit the following new ones.
=head1 ATTRIBUTES
L<Mojo::Content::Single> inherits all attributes from L<Mojo::Content> and
Expand Down

0 comments on commit a5fb3ea

Please sign in to comment.