Skip to content

Commit

Permalink
added j function to ojo (closes #339)
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Jun 19, 2012
1 parent abf911b commit e3f2cbf
Show file tree
Hide file tree
Showing 19 changed files with 97 additions and 75 deletions.
2 changes: 1 addition & 1 deletion Changes
Expand Up @@ -7,7 +7,7 @@
- Updated IO::Socket::SSL requirement to 1.75 for IO::Socket::IP support.
- Switched back from IO::Socket::INET6 to IO::Socket::IP for IPv6 support.
- Switched from HMAC-MD5 to HMAC-SHA1 for signed cookies.
- Added r function to ojo. (sharifulin, sri)
- Added j and r functions to ojo. (sharifulin, sri)
- Added support for new HTTP status code.
- Improved message parser performance slightly.
- Improved documentation. (ichesnokov, sri)
Expand Down
8 changes: 4 additions & 4 deletions lib/Mojo/IOLoop/Client.pm
Expand Up @@ -58,12 +58,12 @@ sub _connect {
$options{LocalAddr} = $args->{local_address} if $args->{local_address};
$options{PeerAddr} =~ s/[\[\]]//g if $options{PeerAddr};
my $class = IPV6 ? 'IO::Socket::IP' : 'IO::Socket::INET';
return $self->emit_safe(error => "Couldn't connect.")
return $self->emit_safe(error => "Couldn't connect")
unless $handle = $class->new(%options);

# Timer
$self->{timer} = $reactor->timer($args->{timeout} || 10,
sub { $self->emit_safe(error => 'Connect timeout.') });
sub { $self->emit_safe(error => 'Connect timeout') });
}
$handle->blocking(0);

Expand All @@ -76,7 +76,7 @@ sub _connect {

# No TLS support
return $self->emit_safe(
error => 'IO::Socket::SSL 1.75 required for TLS support.')
error => 'IO::Socket::SSL 1.75 required for TLS support')
unless TLS;

# Upgrade
Expand All @@ -96,7 +96,7 @@ sub _connect {
SSL_verifycn_scheme => $args->{tls_ca} ? 'http' : undef
);
$self->{tls} = 1;
return $self->emit_safe(error => 'TLS upgrade failed.')
return $self->emit_safe(error => 'TLS upgrade failed')
unless $handle = IO::Socket::SSL->start_SSL($handle, %options);
}

Expand Down
10 changes: 5 additions & 5 deletions lib/Mojo/JSON.pm
Expand Up @@ -45,13 +45,13 @@ sub decode {
$self->error(undef);

# Missing input
$self->error('Missing or empty input.') and return unless $bytes;
$self->error('Missing or empty input') and return unless $bytes;

# Remove BOM
$bytes =~ s/^(?:\357\273\277|\377\376\0\0|\0\0\376\377|\376\377|\377\376)//g;

# Wide characters
$self->error('Wide character in input.') and return
$self->error('Wide character in input') and return
unless utf8::downgrade($bytes, 1);

# Detect and decode Unicode
Expand Down Expand Up @@ -314,7 +314,7 @@ sub _exception {
}

# Throw
die "$context.\n";
die "$context\n";
}

# Emulate boolean type
Expand Down Expand Up @@ -366,7 +366,7 @@ L<Mojo::JSON> implements the following attributes.
=head2 C<error>
my $err = $json->error;
$json = $json->error('Oops!');
$json = $json->error('Parser error');
Parser errors.
Expand All @@ -386,7 +386,7 @@ Decode JSON.
my $bytes = $json->encode({foo => 'bar'});
Encode Perl structure.
Encode Perl data structure.
=head2 C<false>
Expand Down
10 changes: 5 additions & 5 deletions lib/Mojo/Message.pm
Expand Up @@ -331,7 +331,7 @@ sub _parse {
$self->{buffer} .= $chunk;

# Check message size
return $self->error('Maximum message size exceeded.', 413)
return $self->error('Maximum message size exceeded', 413)
if $self->{raw_size} > $self->max_message_size;

# Start line
Expand All @@ -340,7 +340,7 @@ sub _parse {
# Check line size
my $len = index $self->{buffer}, "\x0a";
$len = length $self->{buffer} if $len < 0;
return $self->error('Maximum line size exceeded.', 431)
return $self->error('Maximum line size exceeded', 431)
if $len > $self->max_line_size;

# Parse
Expand Down Expand Up @@ -370,7 +370,7 @@ sub _parse {
}

# Check line size
return $self->error('Maximum line size exceeded.', 431)
return $self->error('Maximum line size exceeded', 431)
if $self->headers->is_limit_exceeded;

# Finished
Expand Down Expand Up @@ -642,8 +642,8 @@ to perform a C<find> on it right away, which returns a collection.
my $message = $message->error;
my ($message, $code) = $message->error;
$message = $message->error('Parser error.');
$message = $message->error('Parser error.', 500);
$message = $message->error('Parser error');
$message = $message->error('Parser error', 500);
Parser errors and codes.
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/Message/Request.pm
Expand Up @@ -284,7 +284,7 @@ sub _parse_start_line {
return unless defined $line;

# We have a (hopefully) full request line
return $self->error('Bad request start line.', 400)
return $self->error('Bad request start line', 400)
unless $line =~ $START_LINE_RE;
$self->method($1);
my $url = $self->url;
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/Message/Response.pm
Expand Up @@ -135,7 +135,7 @@ sub _parse_start_line {

# We have a full HTTP 1.0+ response line
return unless defined(my $line = get_line \$self->{buffer});
return $self->error('Bad response start line.')
return $self->error('Bad response start line')
unless $line =~ m!^\s*HTTP/(\d\.\d)\s+(\d\d\d)\s*(.+)?$!;
$self->version($1)->code($2)->message($3);
$self->content->auto_relax(1);
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/Transaction.pm
Expand Up @@ -271,7 +271,7 @@ message in C<error>, 400 and 500 responses also a code.
if (my $res = $tx->success) { say $res->body }
else {
my ($message, $code) = $tx->error;
say $code ? "$code $message response." : "Connection error: $message";
say $code ? "$code $message response" : "Connection error: $message";
}
Error messages can be accessed with the C<error> method of the transaction
Expand Down
12 changes: 6 additions & 6 deletions lib/Mojo/UserAgent.pm
Expand Up @@ -198,8 +198,8 @@ sub _connect {
return $self->_error($id, $err) if $err;

# Connection established
$stream->on(
timeout => sub { $self->_error($id => 'Inactivity timeout.') });
$stream->on(timeout => sub { $self->_error($id => 'Inactivity timeout') }
);
$stream->on(close => sub { $self->_handle($id => 1) });
$stream->on(error => sub { $self->_error($id, pop, 1) });
$stream->on(read => sub { $self->_read($id => pop) });
Expand All @@ -219,7 +219,7 @@ sub _connect_proxy {

# CONNECT failed
unless (($tx->res->code || '') eq '200') {
$old->req->error('Proxy connection failed.');
$old->req->error('Proxy connection failed');
return $self->_finish($old, $cb);
}

Expand Down Expand Up @@ -306,7 +306,7 @@ sub _finish {
unless ($res->error) {

# Premature connection close
if ($close && !$res->code) { $res->error('Premature connection close.') }
if ($close && !$res->code) { $res->error('Premature connection close') }

# 400/500
elsif ($res->is_status_class(400) || $res->is_status_class(500)) {
Expand Down Expand Up @@ -467,7 +467,7 @@ sub _start {
if (my $t = $self->request_timeout) {
weaken $self;
$self->{connections}{$id}{timeout} = $self->_loop->timer(
$t => sub { $self->_error($id => 'Request timeout.') });
$t => sub { $self->_error($id => 'Request timeout') });
}

return $id;
Expand Down Expand Up @@ -536,7 +536,7 @@ Mojo::UserAgent - Non-blocking I/O HTTP 1.1 and WebSocket user agent
if (my $res = $tx->success) { say $res->body }
else {
my ($message, $code) = $tx->error;
say $code ? "$code $message response." : "Connection error: $message";
say $code ? "$code $message response" : "Connection error: $message";
}
# Quick JSON API request with Basic authentication
Expand Down
14 changes: 7 additions & 7 deletions lib/Mojolicious/Guides/FAQ.pod
Expand Up @@ -37,7 +37,7 @@ to provide advanced functionality if they are installed.

Because we can make them rounder. Components specifically designed for
user-friendliness and development speed are not easy to come by. We are strong
believers of the Perl mantra "There is more than one way to do it.", and our
believers of the Perl mantra "There is more than one way to do it", and our
quest is to develop the best possible solutions for these two criteria.

=head2 What about backwards compatibility?
Expand Down Expand Up @@ -69,23 +69,23 @@ that it might not pass the vote. To increase the chances you can also discuss
and refine ideas on the
L<mailing-list|http://groups.google.com/group/mojolicious>.

=head2 What does the error "Maximum message size exceeded." mean?
=head2 What does the error "Maximum message size exceeded" mean?

To protect your applications from excessively large requests and responses,
our HTTP parser has a cap after which it will automatically stop accepting new
data, and in most cases force the connection to be closed. This limit is
around C<5MB> by default, you can use the C<MOJO_MAX_MESSAGE_SIZE> environment
variable to change this value.

=head2 What does the error "Maximum line size exceeded." mean?
=head2 What does the error "Maximum line size exceeded" mean?

This is a very similar protection mechanism to the one described in the
previous answer, but a little more specific. It limits the maximum length of
any C<\r\n> terminated part of a HTTP message, such as request line, status
line and headers. This limit is around C<10KB> by default, you can use the
C<MOJO_MAX_LINE_SIZE> environment variable to change this value.

=head2 What does "Your secret passphrase needs to be changed!!!" mean?
=head2 What does "Your secret passphrase needs to be changed" mean?

L<Mojolicious> uses a secret passphrase for security features such as signed
cookies. It defaults to the name of your application, which is not very
Expand All @@ -94,7 +94,7 @@ passphrase with the attribute L<Mojolicious/"secret">.

app->secret('My very secret passphrase.');

=head2 What does "Inactivity timeout." mean.
=head2 What does "Inactivity timeout" mean.

To protect your applications from denial-of-service attacks, all connections
have an inactivity timeout which limits how long a connection may be inactive
Expand All @@ -103,13 +103,13 @@ agent and C<15> seconds for all built-in web servers, and is commonly referred
to as C<inactivity_timeout>. This timeout always applies, so you might have to
tweak it for applications that take a long time to process a request.

=head2 What does "Premature connection close." mean?
=head2 What does "Premature connection close" mean?

This error message is often related to the one above, and means that the web
server closed the connection before the user agent could receive the whole
response.

=head2 What does "Worker 31842 has no heartbeat, restarting." mean?
=head2 What does "Worker 31842 has no heartbeat, restarting" mean?

Hypnotoad worker processes send heartbeat messages to the manager process in
regular intervals to signal that they are still responsive. A blocking
Expand Down
4 changes: 2 additions & 2 deletions lib/Mojolicious/Guides/Rendering.pod
Expand Up @@ -208,8 +208,8 @@ performed.

=head2 Rendering JSON

The C<json> stash value allows you to pass Perl structures to the renderer
which get directly encoded to JSON.
The C<json> stash value allows you to pass Perl data structures to the
renderer which get directly encoded to JSON.

$self->render(json => {foo => [1, 'test', 3]});

Expand Down
22 changes: 19 additions & 3 deletions lib/ojo.pm
Expand Up @@ -6,6 +6,7 @@ use Mojo::Base -strict;
use Mojo::ByteStream 'b';
use Mojo::Collection 'c';
use Mojo::DOM;
use Mojo::JSON;
use Mojo::UserAgent;

# Silent oneliners
Expand Down Expand Up @@ -43,11 +44,16 @@ sub import {
*{"${caller}::f"} = sub { _request($UA->build_form_tx(@_)) };
*{"${caller}::g"} = sub { _request($UA->build_tx(GET => @_)) };
*{"${caller}::h"} = sub { _request($UA->build_tx(HEAD => @_)) };
*{"${caller}::j"} = sub {
my $d = shift;
my $j = Mojo::JSON->new;
return ref $d ~~ [qw(ARRAY HASH)] ? $j->encode($d) : $j->decode($d);

This comment has been minimized.

Copy link
@memowe

memowe Jun 19, 2012

Contributor

cool! \oF

};
*{"${caller}::o"} = sub { _request($UA->build_tx(OPTIONS => @_)) };
*{"${caller}::p"} = sub { _request($UA->build_tx(POST => @_)) };
*{"${caller}::p"} = sub { _request($UA->build_tx(POST => @_)) };
*{"${caller}::r"} = sub { $UA->app->dumper(@_) };
*{"${caller}::t"} = sub { _request($UA->build_tx(PATCH => @_)) };
*{"${caller}::u"} = sub { _request($UA->build_tx(PUT => @_)) };
*{"${caller}::t"} = sub { _request($UA->build_tx(PATCH => @_)) };
*{"${caller}::u"} = sub { _request($UA->build_tx(PUT => @_)) };
*{"${caller}::x"} = sub { Mojo::DOM->new(@_) };
}

Expand Down Expand Up @@ -143,6 +149,16 @@ L<Mojo::Message::Response> object.
Perform C<HEAD> request with L<Mojo::UserAgent/"head"> and return resulting
L<Mojo::Message::Response> object.
=head2 C<j>
my $bytes = j({foo => 'bar'});
my $array = j($bytes);
my $hash = j($bytes);
Encode Perl data structure or decode JSON with L<Mojo::JSON>.
$ perl -Mojo -E 'say j({hello => "world!"})'
=head2 C<o>
my $res = o('mojolicio.us');
Expand Down
28 changes: 14 additions & 14 deletions t/mojo/json.t
Expand Up @@ -269,49 +269,49 @@ is_deeply $json->decode($string), {just => 'works'}, 'right roundtrip';

# Errors
is $json->decode('["♥"]'), undef, 'wide character in input';
is $json->error, 'Wide character in input.', 'right error';
is $json->error, 'Wide character in input', 'right error';
is $json->decode(b("\x{feff}[\"\\ud800\"]")->encode('UTF-16LE')), undef,
'missing high surrogate';
is $json->error, 'Malformed JSON: Missing low-surrogate at line 1, offset 8.',
is $json->error, 'Malformed JSON: Missing low-surrogate at line 1, offset 8',
'right error';
is $json->decode(b("\x{feff}[\"\\udf46\"]")->encode('UTF-16LE')), undef,
'missing low surrogate';
is $json->error, 'Malformed JSON: Missing high-surrogate at line 1, offset 8.',
is $json->error, 'Malformed JSON: Missing high-surrogate at line 1, offset 8',
'right error';
is $json->decode('[[]'), undef, 'missing right square bracket';
is $json->error, 'Malformed JSON: Expected comma or right square bracket while'
. ' parsing array at line 1, offset 3.', 'right error';
. ' parsing array at line 1, offset 3', 'right error';
is $json->decode('{{}'), undef, 'missing right curly bracket';
is $json->error, 'Malformed JSON: Expected string while'
. ' parsing object at line 1, offset 1.', 'right error';
. ' parsing object at line 1, offset 1', 'right error';
is $json->decode('[[]...'), undef, 'syntax error';
is $json->error, 'Malformed JSON: Expected comma or right square bracket while'
. ' parsing array at line 1, offset 3.', 'right error';
. ' parsing array at line 1, offset 3', 'right error';
is $json->decode('{{}...'), undef, 'syntax error';
is $json->error, 'Malformed JSON: Expected string while'
. ' parsing object at line 1, offset 1.', 'right error';
. ' parsing object at line 1, offset 1', 'right error';
is $json->decode('[nan]'), undef, 'syntax error';
is $json->error, 'Malformed JSON: Expected string, array, object, number,'
. ' boolean or null at line 1, offset 1.', 'right error';
. ' boolean or null at line 1, offset 1', 'right error';
is $json->decode('["foo]'), undef, 'syntax error';
is $json->error, 'Malformed JSON: Unterminated string at line 1, offset 6.',
is $json->error, 'Malformed JSON: Unterminated string at line 1, offset 6',
'right error';
is $json->decode('["foo"]lala'), undef, 'syntax error';
is $json->error,
'Malformed JSON: Unexpected data after array at line 1, offset 7.',
'Malformed JSON: Unexpected data after array at line 1, offset 7',
'right error';
is $json->decode('false'), undef, 'no object or array';
is $json->error,
'Malformed JSON: Expected array or object at line 0, offset 0.',
'Malformed JSON: Expected array or object at line 0, offset 0',
'right error';
is $json->decode(''), undef, 'no object or array';
is $json->error, 'Missing or empty input.', 'right error';
is $json->error, 'Missing or empty input', 'right error';
is $json->decode("[\"foo\",\n\"bar\"]lala"), undef, 'syntax error';
is $json->error,
'Malformed JSON: Unexpected data after array at line 2, offset 6.',
'Malformed JSON: Unexpected data after array at line 2, offset 6',
'right error';
is $json->decode("[\"foo\",\n\"bar\",\n\"bazra\"]lalala"), undef,
'syntax error';
is $json->error,
'Malformed JSON: Unexpected data after array at line 3, offset 8.',
'Malformed JSON: Unexpected data after array at line 3, offset 8',
'right error';

0 comments on commit e3f2cbf

Please sign in to comment.