basic authorization support for run_test_request and CLI
Matt S Trout [Sun, 15 Jul 2012 18:44:12 +0000 (18:44 +0000)]
Changes
lib/Web/Simple/Application.pm
t/test-request-basic-auth.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index 6587207..50db948 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,3 +1,5 @@
+  - Support for basic authentication in test requests
+
 0.017 - 2012-07-05
   - Don't falsely recognize mod_cgid as FCGI
 
index 24d3463..febd830 100644 (file)
@@ -100,7 +100,7 @@ sub run {
 
   my @args = @ARGV;
 
-  unshift(@args, 'GET') if $args[0] =~ m{^/};
+  unshift(@args, 'GET') if $args[0] =~ m{^/} or $args[0] =~ m{\@};
 
   $self->_run_cli_test_request(@args);
 }
@@ -111,6 +111,14 @@ sub _test_request_spec_to_http_request {
   # if it's a reference, assume a request object
   return $method if ref($method);
 
+  if ($path =~ s/^(.*?)\@//) {
+    my $basic = $1;
+    require MIME::Base64;
+    unshift @rest, 'Authorization:', 'Basic '.MIME::Base64::encode($basic);
+  }
+
+  require HTTP::Request;
+
   my $request = HTTP::Request->new($method => $path);
 
   my @params;
@@ -145,7 +153,6 @@ sub _test_request_spec_to_http_request {
 sub run_test_request {
   my ($self, @req) = @_;
 
-  require HTTP::Request;
   require Plack::Test;
 
   my $request = $self->_test_request_spec_to_http_request(@req);
@@ -299,6 +306,10 @@ The body of the response is sent to STDOUT and the headers to STDERR, so
 
 will generally do the right thing.
 
+To send basic authentication credentials, use user:pass@ syntax -
+
+  $ ./myapp GET bob:secret@/protected/path
+
 Additionally, you can treat the file as though it were a standard PSGI
 application file (*.psgi).  For example you can start up up with C<plackup>
 
@@ -370,6 +381,13 @@ this to create a form style message body. If you need to test an upload, then
 create an L<HTTP::Request> object by hand or use the C<POST> subroutine
 provided by L<HTTP::Request::Common>.
 
+If you prefix the URL with 'user:pass@' this will be converted into
+an Authorization header for HTTP basic auth:
+
+  my $res = $app->run_test_request(
+              GET => 'bob:secret@/protected/resource'
+            );
+
 If pairs are passed where the key ends in :, it is instead treated as a
 headers, so:
 
diff --git a/t/test-request-basic-auth.t b/t/test-request-basic-auth.t
new file mode 100644 (file)
index 0000000..9800554
--- /dev/null
@@ -0,0 +1,54 @@
+use strictures 1;
+use Test::More;
+
+my $auth_result;
+my @auth_args;
+
+{
+  package TestApp;
+
+  use Web::Simple;
+  use Plack::Middleware::Auth::Basic;
+
+  sub dispatch_request {
+    sub () {
+      Plack::Middleware::Auth::Basic->new(
+        authenticator => sub { 
+          @auth_args = @_; return $auth_result
+        }
+      )
+    },
+    sub () {
+      [ 200, [ 'Content-type' => 'text/plain' ], [ 'Woo' ] ]
+    }
+  }
+}
+
+my $ta = TestApp->new;
+
+my $res = $ta->run_test_request(GET => '/');
+
+is($res->code, '401', 'Auth failed with no user/pass');
+ok(!@auth_args, 'Auth callback never called with no user/pass');
+
+$res = $ta->run_test_request(GET => 'bob:secret@/');
+
+is($res->code, '401', 'Auth failed with bad user/pass');
+is($auth_args[0], 'bob', 'Username passed ok');
+is($auth_args[1], 'secret', 'Password passed ok');
+
+$auth_result = 1;
+@auth_args = ();
+
+$res = $ta->run_test_request(GET => '/');
+
+is($res->code, '401', 'Auth failed with no user/pass');
+ok(!@auth_args, 'Auth callback never called with no user/pass');
+
+$res = $ta->run_test_request(GET => 'bob:secret@/');
+
+is($res->code, '200', 'Auth succeeded with good user/pass');
+is($auth_args[0], 'bob', 'Username passed ok');
+is($auth_args[1], 'secret', 'Password passed ok');
+
+done_testing;