fu: Close-up of Fu, bringing a scoop of water to her mouth (Default)
fu ([personal profile] fu) wrote in [site community profile] changelog2011-02-28 10:45 am

[dw-free] Need a way to cleanly call controllers from tests

[commit: http://hg.dwscoalition.org/dw-free/rev/37f7a2c8953c]

http://bugs.dwscoalition.org/show_bug.cgi?id=3547

Limit the methods that are supported by controllers to GET/POST/HEAD.
Controllers can override to allow other methods.

Patch by [personal profile] exor674.

Files modified:
  • cgi-bin/DW/Controller/Interface/S2.pm
  • cgi-bin/DW/Request/Standard.pm
  • cgi-bin/DW/Routing.pm
  • cgi-bin/DW/Routing/CallInfo.pm
  • t/routing.t
--------------------------------------------------------------------------------
diff -r b7d1369e7005 -r 37f7a2c8953c cgi-bin/DW/Controller/Interface/S2.pm
--- a/cgi-bin/DW/Controller/Interface/S2.pm	Mon Feb 28 16:33:50 2011 +0800
+++ b/cgi-bin/DW/Controller/Interface/S2.pm	Mon Feb 28 18:44:54 2011 +0800
@@ -21,7 +21,7 @@ use DW::Routing;
 use DW::Routing;
 
 # handle, even with no id, so that we can present an informative error message
-DW::Routing->register_regex( '^/interface/s2(?:/(\d+)?)?$', \&interface_handler, app => 1, format => 'plain' );
+DW::Routing->register_regex( '^/interface/s2(?:/(\d+)?)?$', \&interface_handler, app => 1, format => 'plain', methods => { GET => 1, PUT => 1 } );
 
 # handles menu nav pages
 sub interface_handler {
@@ -101,10 +101,6 @@ sub interface_handler {
 
             return $r->OK;
         }
-    } else {
-        # Return 'method not allowed' so that we can add methods in future
-        # and clients will get a sensible error from old servers.
-        return error( $r, $r->HTTP_METHOD_NOT_ALLOWED, 'Method Not Allowed', 'Only GET and PUT are supported for this resource' );
     }
 }
 
diff -r b7d1369e7005 -r 37f7a2c8953c cgi-bin/DW/Request/Standard.pm
--- a/cgi-bin/DW/Request/Standard.pm	Mon Feb 28 16:33:50 2011 +0800
+++ b/cgi-bin/DW/Request/Standard.pm	Mon Feb 28 18:44:54 2011 +0800
@@ -291,10 +291,14 @@ sub OK        { return 200; }
 sub OK        { return 200; }
 sub HTTP_CREATED { return 201; }
 sub REDIRECT  { return 302; }
+sub NOT_FOUND { return 404; }
+sub SERVER_ERROR { return 500; }
+sub HTTP_UNAUTHORIZED { return 401; }
 sub HTTP_BAD_REQUEST { return 400; }
-sub HTTP_UNAUTHORIZED { return 403; }
-sub NOT_FOUND { return 404; }
+sub HTTP_UNSUPPORTED_MEDIA_TYPE { return 415; }
 sub HTTP_SERVER_ERROR { return 500; }
+sub HTTP_METHOD_NOT_ALLOWED { return 405; }
+sub FORBIDDEN { return 403; }
 
 # spawn a process for an external program
 sub spawn {
diff -r b7d1369e7005 -r 37f7a2c8953c cgi-bin/DW/Routing.pm
--- a/cgi-bin/DW/Routing.pm	Mon Feb 28 16:33:50 2011 +0800
+++ b/cgi-bin/DW/Routing.pm	Mon Feb 28 18:44:54 2011 +0800
@@ -157,6 +157,10 @@ sub _call_hash {
     my $opts = $r->pnote('routing_opts');
 
     $opts->prepare_for_call;
+
+    # check method
+    my $method = uc( $r->method );
+    return $r->HTTP_METHOD_NOT_ALLOWED unless $opts->method_valid( $method );
 
     my $format = $opts->format;
     # check for format validity
@@ -370,7 +374,7 @@ sub _apply_defaults {
 sub _apply_defaults {
     my ( $opts, $hash ) = @_;
 
-    $hash ||= 0;
+    $hash ||= {};
     $opts->{app} = 1 if ! defined $opts->{app} && !$opts->{user};
     $hash->{args} = $opts->{args};
     $hash->{ssl} = $opts->{ssl} || 0;
@@ -382,6 +386,7 @@ sub _apply_defaults {
     $formats = { map { ( $_, 1 ) } @$formats } if ( ref($formats) eq 'ARRAY' );
 
     $hash->{formats} = $formats;
+    $hash->{methods} = $opts->{methods} || { GET => 1, POST => 1, HEAD => 1 };
 
     return $hash;
 }
diff -r b7d1369e7005 -r 37f7a2c8953c cgi-bin/DW/Routing/CallInfo.pm
--- a/cgi-bin/DW/Routing/CallInfo.pm	Mon Feb 28 16:33:50 2011 +0800
+++ b/cgi-bin/DW/Routing/CallInfo.pm	Mon Feb 28 18:44:54 2011 +0800
@@ -114,6 +114,18 @@ sub format_valid {
     return $formats->{$_[0]->format} || 0;
 }
 
+=head2 C<< $self->method_valid( $method ) >>
+
+Returns if the method is valid for the callinfo
+
+=cut
+
+sub method_valid {
+    my $methods = $_[0]->{__hash}->{methods};
+    return 1 if $methods == 1;
+    return $methods->{$_[1]} || 0;
+}
+
 =head2 C<< $self->role >>
 
 Current mode: 'app' or 'user' or 'ssl'
diff -r b7d1369e7005 -r 37f7a2c8953c t/routing.t
--- a/t/routing.t	Mon Feb 28 16:33:50 2011 +0800
+++ b/t/routing.t	Mon Feb 28 18:44:54 2011 +0800
@@ -14,7 +14,7 @@
 # 'perldoc perlartistic' or 'perldoc perlgpl'.
 #
 use strict;
-use Test::More tests => 203;
+use Test::More tests => 238;
 use lib "$ENV{LJHOME}/cgi-bin";
 
 # don't let DW::Routing load DW::Controller subclasses
@@ -251,7 +251,6 @@ handle_redirect( '/xx3', '/xx3/' );
 handle_redirect( '/xx3', '/xx3/' );
 # 194
 
-
 # test dying
 DW::Routing->register_string( "/test/die/all_format", \&died_handler, app => 1, formats => 1 );
 
@@ -259,6 +258,32 @@ handle_server_error( "/test die .json fo
 handle_server_error( "/test die .json format (app)", "/test/die/all_format.json", "json" ); # 2 tests
 handle_server_error( "/test die .html format (app)", "/test/die/all_format.html", "html" ); # 2 tests
 handle_server_error( "/test die .blah format (app)", "/test/die/all_format.blah", "blah" ); # 2 tests
+# 203 ( I know this doesn't add up. )
+
+DW::Routing->register_string( "/test/method/normal", \&handler, app => 1 );
+
+handle_request( "Method GET  - okay", "/test/method/normal", 1, undef, method => 'GET' );  # 3 tests
+handle_request( "Method POST - okay", "/test/method/normal", 1, undef, method => 'POST' );
+handle_request( "Method HEAD - okay", "/test/method/normal", 1, undef, method => 'HEAD' );
+handle_request( "Method PUT  - !ok",  "/test/method/normal", 1, undef, method => 'PUT', expected_error => 405 ); # 1 test
+# 213
+
+DW::Routing->register_string( "/test/method/all", \&handler, app => 1, methods => 1 );
+
+handle_request( "Method GET  - okay", "/test/method/all", 1, undef, method => 'GET' );  # 3 tests
+handle_request( "Method POST - okay", "/test/method/all", 1, undef, method => 'POST' );
+handle_request( "Method HEAD - okay", "/test/method/all", 1, undef, method => 'HEAD' );
+handle_request( "Method PUT  - okay", "/test/method/all", 1, undef, method => 'PUT' );
+handle_request( "Method FOO  - okay", "/test/method/all", 1, undef, method => 'FOO' );
+# 228
+
+DW::Routing->register_string( "/test/method/no_post", \&handler, app => 1, methods => { GET => 1, HEAD => 1, PUT => 1 } );
+
+handle_request( "Method GET  - okay", "/test/method/no_post", 1, undef, method => 'GET' );  # 3 tests
+handle_request( "Method POST - !ok",  "/test/method/no_post", 1, undef, method => 'POST', expected_error => 405 ); # 1 test
+handle_request( "Method HEAD - okay", "/test/method/no_post", 1, undef, method => 'HEAD' ); # 3 tests
+handle_request( "Method PUT  - okay", "/test/method/no_post", 1, undef, method => 'PUT' ); # 3 test
+# 238
 
 
 sub handle_redirect {
@@ -286,7 +311,9 @@ sub handle_request {
     $DW::Request::determined = 0;
     $DW::Request::cur_req = undef;
 
-    my $req = HTTP::Request->new(GET=>"$uri");
+    my $method = $opts{method} || 'GET';
+
+    my $req = HTTP::Request->new($method=>"$uri");
     my $r = DW::Request::Standard->new($req);
 
     $result = undef;
--------------------------------------------------------------------------------