Skip to content

Commit

Permalink
added experimental PATCH support
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Feb 26, 2012
1 parent bc3648c commit 72b2d02
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 40 deletions.
5 changes: 5 additions & 0 deletions Changes
@@ -1,6 +1,11 @@
This file documents the revision history for Perl extension Mojolicious.

2.54 2012-02-26 00:00:00
- Added EXPERIMENTAL patch function to Mojolicious::Lite.
- Added EXPERIMENTAL patch method to Mojolicious::Routes.
- Added EXPERIMENTAL patch method to Mojo::UserAgent.
- Added EXPERIMENTAL patch_ok method to Test::Mojo.
- Added EXPERIMENTAL t function to ojo.
- Added support for MOJO_CONNECT_TIMEOUT, MOJO_INACTIVITY_TIMEOUT,
MOJO_REQUEST_TIMEOUT and MOJO_WEBSOCKET_TIMEOUT environment
variables.
Expand Down
19 changes: 18 additions & 1 deletion lib/Mojo/UserAgent.pm
Expand Up @@ -31,7 +31,7 @@ has websocket_timeout => sub { $ENV{MOJO_WEBSOCKET_TIMEOUT} // 300 };
# Common HTTP methods
{
no strict 'refs';
for my $name (qw/DELETE GET HEAD POST PUT/) {
for my $name (qw/DELETE GET HEAD PATCH POST PUT/) {
*{__PACKAGE__ . '::' . lc($name)} = sub {
my $self = shift;
$self->start($self->build_tx($name, @_));
Expand Down Expand Up @@ -933,6 +933,23 @@ append a callback to perform requests non-blocking.
Check if request for domain would use a proxy server.
=head2 C<patch>
my $tx = $ua->patch('http://kraih.com');
Perform blocking HTTP C<PATCH> request and return resulting
L<Mojo::Transaction::HTTP> object, takes the exact same arguments as
L<Mojo::UserAgent::Transactor/"tx"> (except for the method). You can also
append a callback to perform requests non-blocking. Note that this method is
EXPERIMENTAL and might change without warning!
$ua->patch('http://kraih.com' => sub {
my ($ua, $tx) = @_;
say $tx->res->body;
Mojo::IOLoop->stop;
});
Mojo::IOLoop->start;
=head2 C<post>
my $tx = $ua->post('http://kraih.com');
Expand Down
9 changes: 9 additions & 0 deletions lib/Mojolicious/Lite.pm
Expand Up @@ -49,6 +49,7 @@ sub import {
*{"${caller}::hook"} = sub { $app->hook(@_) };
*{"${caller}::under"} = *{"${caller}::ladder"} =
sub { $routes = $root->under(@_) };
*{"${caller}::patch"} = sub { $routes->patch(@_) };
*{"${caller}::plugin"} = sub { $app->plugin(@_) };
*{"${caller}::post"} = sub { $routes->post(@_) };
*{"${caller}::put"} = sub { $routes->put(@_) };
Expand Down Expand Up @@ -882,6 +883,14 @@ Alias for L<Mojolicious/"helper">.
Alias for L<Mojolicious/"hook">.
=head2 C<patch>
my $route = patch '/:foo' => sub {...};
Generate route matching only C<PATCH> requests. See also the tutorial above
for more argument variations. Note that this function is EXPERIMENTAL and
might change without warning!
=head2 C<plugin>
plugin 'SomeThing';
Expand Down
36 changes: 22 additions & 14 deletions lib/Mojolicious/Routes.pm
Expand Up @@ -85,7 +85,7 @@ sub auto_render {

sub bridge { shift->route(@_)->inline(1) }

sub delete { shift->_generate_route('delete', @_) }
sub delete { shift->_generate_route(delete => @_) }

sub detour {
my $self = shift;
Expand Down Expand Up @@ -144,7 +144,7 @@ sub dispatch {
$self->auto_render($c);
}

sub get { shift->_generate_route('get', @_) }
sub get { shift->_generate_route(get => @_) }

sub has_conditions {
my $self = shift;
Expand Down Expand Up @@ -217,9 +217,9 @@ sub parse {
return $self;
}

sub post { shift->_generate_route('post', @_) }

sub put { shift->_generate_route('put', @_) }
sub patch { shift->_generate_route(patch => @_) }
sub post { shift->_generate_route(post => @_) }
sub put { shift->_generate_route(put => @_) }

sub render {
my ($self, $path, $values) = @_;
Expand Down Expand Up @@ -312,7 +312,7 @@ sub to_string {
return $pattern;
}

sub under { shift->_generate_route('under', @_) }
sub under { shift->_generate_route(under => @_) }

sub via {
my $self = shift;
Expand Down Expand Up @@ -751,8 +751,8 @@ Add a new shortcut for this route.
=head2 C<any>
my $any = $route->any('/:foo' => sub {...});
my $any = $route->any([qw/get post/] => '/:foo' => sub {...});
my $route = $route->any('/:foo' => sub {...});
my $route = $route->any([qw/get post/] => '/:foo' => sub {...});
Generate route matching any of the listed HTTP request methods or all. See
also the L<Mojolicious::Lite> tutorial for more argument variations.
Expand All @@ -772,7 +772,7 @@ Add a new bridge to this route as a nested child.
=head2 C<delete>
my $del = $route->delete('/:foo' => sub {...});
my $route = $route->delete('/:foo' => sub {...});
Generate route matching only C<DELETE> requests. See also the
L<Mojolicious::Lite> tutorial for more argument variations.
Expand Down Expand Up @@ -802,7 +802,7 @@ Match routes and dispatch.
=head2 C<get>
my $get = $route->get('/:foo' => sub {...});
my $route = $route->get('/:foo' => sub {...});
Generate route matching only C<GET> requests. See also the
L<Mojolicious::Lite> tutorial for more argument variations.
Expand Down Expand Up @@ -868,16 +868,24 @@ Apply condition parameters to this route and disable routing cache.
Parse a pattern.
=head2 C<patch>
my $route = $route->patch('/:foo' => sub {...});
Generate route matching only C<PATCH> requests. See also the
L<Mojolicious::Lite> tutorial for more argument variations. Note that this
method is EXPERIMENTAL and might change without warning!
=head2 C<post>
my $post = $route->post('/:foo' => sub {...});
my $route = $route->post('/:foo' => sub {...});
Generate route matching only C<POST> requests. See also the
L<Mojolicious::Lite> tutorial for more argument variations.
=head2 C<put>
my $put = $route->put('/:foo' => sub {...});
my $route = $route->put('/:foo' => sub {...});
Generate route matching only C<PUT> requests. See also the
L<Mojolicious::Lite> tutorial for more argument variations.
Expand Down Expand Up @@ -920,8 +928,8 @@ Stringifies the whole route.
=head2 C<under>
my $under = $r->under(sub {...});
my $under = $r->under('/:foo');
my $route = $r->under(sub {...});
my $route = $r->under('/:foo');
Generate bridges. See also the L<Mojolicious::Lite> tutorial for more
argument variations.
Expand Down
19 changes: 14 additions & 5 deletions lib/Test/Mojo.pm
Expand Up @@ -99,7 +99,7 @@ sub content_type_unlike {
# "A job's a job. I mean, take me.
# If my plant pollutes the water and poisons the town,
# by your logic, that would make me a criminal."
sub delete_ok { shift->_request_ok('delete', @_) }
sub delete_ok { shift->_request_ok(delete => @_) }

sub element_exists {
my ($self, $selector, $desc) = @_;
Expand Down Expand Up @@ -128,8 +128,8 @@ sub finish_ok {
return $self;
}

sub get_ok { shift->_request_ok('get', @_) }
sub head_ok { shift->_request_ok('head', @_) }
sub get_ok { shift->_request_ok(get => @_) }
sub head_ok { shift->_request_ok(head => @_) }

sub header_is {
my ($self, $name, $value) = @_;
Expand Down Expand Up @@ -238,7 +238,8 @@ sub message_unlike {
}

# "God bless those pagans."
sub post_ok { shift->_request_ok('post', @_) }
sub patch_ok { shift->_request_ok(patch => @_) }
sub post_ok { shift->_request_ok(post => @_) }

sub post_form_ok {
my ($self, $url) = (shift, shift);
Expand All @@ -251,7 +252,7 @@ sub post_form_ok {
}

# "WHO IS FONZY!?! Don't they teach you anything at school?"
sub put_ok { shift->_request_ok('put', @_) }
sub put_ok { shift->_request_ok(put => @_) }

sub reset_session {
my $self = shift;
Expand Down Expand Up @@ -652,6 +653,14 @@ EXPERIMENTAL and might change without warning!
Opposite of C<message_like>. Note that this method is EXPERIMENTAL and might
change without warning!
=head2 C<patch_ok>
$t = $t->patch_ok('/foo');
Perform a C<PATCH> request and check for transport errors, takes the exact
same arguments as L<Mojo::UserAgent/"patch">. Note that this method is
EXPERIMENTAL and might change without warning!
=head2 C<post_ok>
$t = $t->post_ok('/foo');
Expand Down
25 changes: 16 additions & 9 deletions lib/ojo.pm
Expand Up @@ -41,12 +41,13 @@ sub import {
*{"${caller}::oO"} = sub { _request(@_) };
*{"${caller}::a"} =
sub { *{"${caller}::any"}->(@_) and return *{"${caller}::app"}->() };
*{"${caller}::d"} = sub { _request('DELETE', @_) };
*{"${caller}::f"} = sub { _request('FORM', @_) };
*{"${caller}::g"} = sub { _request('GET', @_) };
*{"${caller}::h"} = sub { _request('HEAD', @_) };
*{"${caller}::p"} = sub { _request('POST', @_) };
*{"${caller}::u"} = sub { _request('PUT', @_) };
*{"${caller}::d"} = sub { _request(DELETE => @_) };
*{"${caller}::f"} = sub { _request(FORM => @_) };
*{"${caller}::g"} = sub { _request(GET => @_) };
*{"${caller}::h"} = sub { _request(HEAD => @_) };
*{"${caller}::p"} = sub { _request(POST => @_) };
*{"${caller}::t"} = sub { _request(PATCH => @_) };
*{"${caller}::u"} = sub { _request(PUT => @_) };
*{"${caller}::x"} = sub { Mojo::DOM->new(@_) };
}

Expand All @@ -58,9 +59,7 @@ sub _request {

# Transaction
my $tx =
$method eq 'FORM'
? $UA->build_form_tx(@_)
: $UA->build_tx($method => @_);
$method eq 'FORM' ? $UA->build_form_tx(@_) : $UA->build_tx($method => @_);

# Process
$tx = $UA->start($tx);
Expand Down Expand Up @@ -153,6 +152,14 @@ L<Mojo::Message::Response> object.
Perform C<POST> request with L<Mojo::UserAgent/"post"> and return resulting
L<Mojo::Message::Response> object.
=head2 C<t>
my $res = t('http://mojolicio.us');
Perform C<PATCH> request with L<Mojo::UserAgent/"patch"> and return resulting
L<Mojo::Message::Response> object. Note that this function is EXPERIMENTAL
and might change without warning!
=head2 C<u>
my $res = u('http://mojolicio.us');
Expand Down
12 changes: 6 additions & 6 deletions t/mojolicious/lite_app.t
Expand Up @@ -363,8 +363,8 @@ post '/bar/:test' => {test => 'default'} => sub {
$self->render_text($self->stash('test'));
};

# GET /firefox/*
get '/firefox/:stuff' => (agent => qr/Firefox/) => sub {
# PATCH /firefox/*
patch '/firefox/:stuff' => (agent => qr/Firefox/) => sub {
my $self = shift;
$self->render_text($self->url_for('foxy', stuff => 'foo'));
} => 'foxy';
Expand Down Expand Up @@ -1130,14 +1130,14 @@ $t->get_ok('/layout')->status_is(200)
->header_is('X-Powered-By' => 'Mojolicious (Perl)')
->content_is("LayoutYea baby! with layout\n");

# GET /firefox
$t->get_ok('/firefox/bar', {'User-Agent' => 'Firefox'})->status_is(200)
# PATCH /firefox
$t->patch_ok('/firefox/bar', {'User-Agent' => 'Firefox'})->status_is(200)
->header_is(Server => 'Mojolicious (Perl)')
->header_is('X-Powered-By' => 'Mojolicious (Perl)')
->content_is('/firefox/foo');

# GET /firefox
$t->get_ok('/firefox/bar', {'User-Agent' => 'Explorer'})->status_is(404)
# PATCH /firefox
$t->patch_ok('/firefox/bar', {'User-Agent' => 'Explorer'})->status_is(404)
->header_is(Server => 'Mojolicious (Perl)')
->header_is('X-Powered-By' => 'Mojolicious (Perl)')
->content_like(qr/Oops!/);
Expand Down
5 changes: 4 additions & 1 deletion t/mojolicious/ojo.t
Expand Up @@ -9,7 +9,7 @@ BEGIN {
$ENV{MOJO_MODE} = 'development';
}

use Test::More tests => 10;
use Test::More tests => 11;

# "What do you mean 'we', flesh-tube?"
use_ok 'ojo';
Expand All @@ -27,6 +27,9 @@ is g('/')->body, 'GET', 'right content';
# HEAD /
is h('/')->body, '', 'no content';

# PATCH /
is t('/')->body, 'PATCH', 'right content';

# POST /
is p('/')->body, 'POST', 'right content';

Expand Down
8 changes: 4 additions & 4 deletions t/mojolicious/tag_helper_lite_app.t
Expand Up @@ -44,8 +44,8 @@ get 'form/:test' => 'form';
# PUT /selection
put 'selection';

# GET /☃
get '/☃' => 'snowman';
# PATCH /☃
patch '/☃' => 'snowman';

my $t = Test::Mojo->new;

Expand Down Expand Up @@ -324,8 +324,8 @@ $t->put_ok('/selection?preselect=1')->status_is(200)
. '</form>'
. "\n");

# GET /☃
$t->get_ok('/☃')->status_is(200)->content_is(<<'EOF');
# PATCH /☃
$t->patch_ok('/☃')->status_is(200)->content_is(<<'EOF');
<form action="/%E2%98%83">
<input type="submit" value="☃" />
</form>
Expand Down

0 comments on commit 72b2d02

Please sign in to comment.