Apache2-ASP

 view release on metacpan or  search on metacpan

lib/Apache2/ASP/Manual/BestPractices.pod  view on Meta::CPAN

  <%
    if( my $msg = delete($Session->{msg}) ) {
  %>
  <div class="message"><%= $Server->HTMLEncode( $msg ) %></div>
  <%
    }# end if()
  %>
  
  <%
    if( $errors->{general} ) {
  %>
  <div class="general_error"><%= $Server->HTMLEncode( $errors->{general} ) %></div>
  <%
    }# end if()
  %>
  
  <form action="/handlers/site1.user.login" method="post">
    <input type="text" name="username" value="<%= $Server->HTMLEncode( $Form->{username} ) %>" />
    <% $errLabel->( 'username' ); %>
    <br />
    <input type="password" name="password" />
    <% $errLabel->( 'password' ); %>
    <br />
    <input type="submit" value="Submit" />
  </form>

The form submits to the URI C</handlers/site1.user.login> which maps to the package
C<site1::user::login>.

It is recommended that inside your C</etc> folder you have a YAML file, C</etc/properties.yaml>:

B<The YAML File>: (C</etc/properties.yaml>)

  ---
  user_login:
    username:
      is_missing: Required
      is_invalid: Invalid username
    password:
      is_missing: Required
      is_invalid: Invalid password
    general:
      success: Successfully Logged In
      fail: Invalid username and/or password.  Please try again.

B<The Handler>: (C</handlers/site1/user/login.pm>)

  package site1::user::login;
  
  use strict;
  use warnings 'all';
  use base 'Apache2::ASP::FormHandler';
  use vars __PACKAGE__->VARS;
  use Data::Properties::YAML;
  
  #============================================================================
  sub run
  {
    my ($s, $context) = @_;
    
    if( my $errors = $s->validate( $context ) )
    {
      # We found some kind of validation error:
      $Session->{__lastArgs} = $Form;
      $Session->{validation_errors} = $errors;
      return $Response->Redirect( $ENV{HTTP_REFERER} );
    }# end if()
    
    # Success! - no validation errors:
    my ($user) = find_user( ... );
    $Session->{user} = $user;
    
    # Find our success message:
    my $props = Data::Properties::YAML->new(
      properties_file => $Config->web->application_root . '/etc/properties.yaml'
    )->user_login;
    $Session->{msg} = $props->general->success;
    
    # Redirect the user to the logged-in page:
    return $Response->Redirect("/logged-in.asp");
  }# end run()
  
  #============================================================================
  sub validate
  {
    my ($s, $context) = @_;
    
    # Remove leading and trailing whitespace:
    map {
      $Form->{$_} =~ s/^\s+//;
      $Form->{$_} =~ s/\s+$//;
    } keys(%$Form);
    
    my $props = Data::Properties::YAML->new(
      properties_file => $Config->web->application_root . '/etc/properties.yaml'
    )->user_login;
    
    my $errors = { };
    
    no warnings 'uninitialized';
    
    # username:
    if( length($Form->{username}) )
    {
      # Username cannot contain whitespace:
      if( $Form->{username} =~ m/\s/ )
      {
        $errors->{username} = $props->username->is_invalid;
      }# end if()
    }
    else
    {
      $errors->{username} = $props->username->is_missing;
    }# end if()
    
    # password:
    if( length($Form->{password}) )
    {
      # Password cannot contain whitespace:
      if( $Form->{password} =~ m/\s/ )
      {
        $errors->{password} = $props->password->is_invalid;
      }# end if()
    }
    else
    {
      $errors->{password} = $props->password->is_missing;
    }# end if()
    
    # Only check to see if the user exists if we haven't encountered other errors:
    unless( keys(%$errors) )
    {
      if( ! find_user( ... ) )
      {
        $errors->{general} = $props->general->fail;
      }# end if()
    }# end unless()
    
    return unless keys(%$errors);
    return $errors;
  }# end validate()
  
  1;# return true:

=head1 UNIT TESTING

Unit testing was the number one reason behind the development of Apache2::ASP.

Apache2::ASP offers a unit testing environment that is not dependent on Apache
or any other server.

Unit tests are made possible via instances of L<Apache2::ASP::Test::Base> and 
use L<Apache2::ASP::Test::UserAgent> to make "requests" to ASP scripts and handlers
in your Apache2::ASP web application.

=head2 Example

Supposing your website is at C</var/www/www.example.com>, create a folder C</t>
at C</var/www/www.example.com/t>.

Inside C</t> create C</t/00-basic.t> which contains:

  #!/usr/bin/env perl -w
  
  use strict;
  use warnings 'all';
  use Test::More 'no_plan';
  use base 'Apache2::ASP::Test::Base';
  
  # Create our base test object:
  my $s = __PACKAGE__->SUPER::new();
  
  # Make a request:
  my $res = $s->ua->get("/index.asp");
  
  # $res is a normal HTTP::Response object:
  ok( $res->is_success => "Got /index.asp" );
  like $res->content, qr/Hello, World/, "Contents look right";
  is( $res->header('content-type') => 'text/html' );

Run your tests with:

  prove t

All of your tests will be run.

=head1 CODE COVERAGE

Along with unit testing, code coverage is another great reason to use Apache2::ASP.

Just by using the L<Devel::Cover> utility C<cover> you can get code coverage
for not only your website's libraries, but also its handlers and ASP scripts.

=head1 PROFILING

Profiling an Apache2::ASP web application fits right in with your unit tests and
code coverage.

L<Devel::NYTProf> is an excellent profiler tool for Perl and works very well with
Apache2::ASP web applications.



( run in 0.479 second using v1.01-cache-2.11-cpan-140bd7fdf52 )