ASP4

 view release on metacpan or  search on metacpan

README.markdown  view on Meta::CPAN

# NAME

ASP4 - Fast, Simple and Scalable Web Development for Perl

# DESCRIPTION

ASP4 is a modern web development platform for Perl with a focus on speed, simplicity
and scalability.

# ASP OBJECTS

ASP4 brings our old friends `$Request`, `$Response`, `$Server` and `$Session`
back from the 1990's, but adds some new ever-present objects as well.  Together
the ASP objects provide a consistent interface to the incoming request, outgoing response,
server environment and configuration in-use by the application itself.

## $Form

This is a simple hash reference which contains the names and values of the incoming
request parameters for both GET and POST requests.

For example, the following request...

    /foo.asp?name=joe&color=red

...produces the following `$Form` object:

    $VAR1 = {
      name  => 'joe',
      color => 'red'
    };

Access form data just like any other hashref:

    Hello, <%= $Form->{name} %>, I see your favorite color is <%= $Form->{color} %>.

## $Server

The `$Server` object offers a few utility methods that don't really fit anywhere else.

### $Server->HTMLEncode( $string )

Given a string like `<br/>` returns a string like `&lt;br/&gt;`

### $Server->HTMLDecode( $string )

Given a string like `&lt;br/&gt;` returns a string like `<br/>`

### $Server->URLEncode( $string )

Given a string like `billg@microsoft.com` returns a string like `billg%40microsoft.com`

### $Server->URLDecode( $string )

Given a string like `billg%40microsoft.com` returns a string like `billg@microsoft.com`

### $Server->MapPath( $path )

Given a `$path` of `/foo.asp` would return something like `/var/www/example.com/htdocs/foo.asp`

### $Server->Mail( %args )

Sends an email via [Mail::Sendmail](http://search.cpan.org/perldoc?Mail::Sendmail).  In fact it simply calls the `sendmail(...)` function
provided by [Mail::Sendmail](http://search.cpan.org/perldoc?Mail::Sendmail).

Simple Example:

    $Server->Mail(
      from    => 'foo@bar.com',
      to      => 'bar@foo.com',
      subject => 'Hello, world!',
      message => 'this is a test message'
    );

To send an HTML email do the following:

    use MIME::Base64;
    $Server->Mail(
      from                        => 'foo@bar.com',
      to                          => 'bar@foo.com',
      subject                     => 'Hello, world!',
      'content-type'              => 'text/html',
      'content-transfer-encoding' => 'base64',
      message => encode_base64(<<"HTML")
    <html>
    <body>
      <p>This is an html email.</p>
      <p>You can see that <b>this text is bold</b>.</p>
    </body>
    </html>
    HTML
    );

README.markdown  view on Meta::CPAN

    <!-- Normal SSI-style Include -->
    <!-- #include virtual="/includes/page.asp" -->

If you want to supply arguments to the included ASP script you can use `$Response->Include($path, \%args)`

    # Add the output of C</includes/page.asp> to the current output buffer:
    my %args = ( foo => "bar" );
    $Response->Include( $Server->MapPath("/includes/page.asp"), \%args );

`\%args` is optional.

Within the included ASP script, `\%args` is accessible like this:

    <%
      my ($self, $context, $args) = @_;
    %>

### $Response->TrapInclude( $path, %args )

Or if you need to capture the result of executing an ASP script and use it within
a variable, use `$Response->TrapInclude($path, \%args)`

    # Capture the output of C</includes/page.asp>:
    my %args = ( foo => "bar" );
    my $html = $Response->TrapInclude( $Server->MapPath("/includes/page.asp"), \%args );

`\%args` is optional.

Within the included ASP script, `\%args` is accessible like this:

    <%
      my ($self, $context, $args) = @_;
    %>

## $Session

The `$Session` object is an instance of a subclass of [ASP4::SessionStateManager](http://search.cpan.org/perldoc?ASP4::SessionStateManager)
(depending on your website's configuration).

The `$Session` object is a simple blessed hashref and should be used like a hashref.

Examples:

### Set a session variable

    $Session->{foo} = "bar";

    $Session->{thing} = {
      banana  => "yellow",
      cherry  => "red",
      peach   => "pink,
    };

### Get a session variable

    my $foo = $Session->{foo};

### $Session->save()

Called automatically at the end of every successful request, causes any changes
to the `$Session` to be saved to the database.

### $Session->reset()

Call `$Session->reset()` to clear all the data out of the session and save 
it to the database.

## $Config

The ASP4 `$Config` object is stored in a simple JSON format on disk, and accessible
everywhere within your entire ASP4 application as the global `$Config` object.

If ever you find yourself in a place without a `$Config` object, you can get one
like this:

    use ASP4::ConfigLoader;
    my $Config = ASP4::ConfigLoader->load();

See [ASP4::Config](http://search.cpan.org/perldoc?ASP4::Config) for full details on the ASP4 `$Config` object and its usage.

## $Stash

The `$Stash` is a simple hashref that is guaranteed to be the exact same hashref
throughout the entire lifetime of a request.

Anything placed within the `$Stash` at the very beginning of processing a request -
such as in a RequestFilter - will still be there at the very end of the request -
as in a RegisterCleanup handler.

Use the `$Stash` as a great place to store a piece of data for the duration of
a single request.

# DATABASE

While ASP4 __does not require__ its users to choose any specific database (eg: MySQL or PostgreSQL)
or ORM (object-relational mapper) the __recommended__ ORM is [Class::DBI::Lite](http://search.cpan.org/perldoc?Class::DBI::Lite)
since it has been completely and thoroughly tested to be 100% compatible with ASP4.

For full documentation about [Class::DBI::Lite](http://search.cpan.org/perldoc?Class::DBI::Lite) please view its documentation.

__NOTE:__ [Class::DBI::Lite](http://search.cpan.org/perldoc?Class::DBI::Lite) must be installed in addition to ASP4 as it is a separate library.

# ASP4 QuickStart

Here is an example project to get things going.

In the `data_connections.main` section of `conf/asp4-config.json` you should have
something like this:

    ...
      "main": {
        "dsn":              "DBI:mysql:database_name:data.mywebsite.com",
        "username":         "db-username",
        "password":         "db-pAsswOrd"
      }
    ...

Suppose you had the following tables in your database:

    create table users (
      user_id     bigint unsigned not null primary key auto_increment,
      email       varchar(200) not null,
      password    char(32) not null,
      created_on  timestamp not null default current_timestamp,
      unique(email)
    ) engine=innodb charset=utf8;
    

    create table messages (
      message_id    bigint unsigned not null primary key auto_increment,
      from_user_id  bigint unsigned not null,
      to_user_id    bigint unsigned not null,
      subject       varchar(100) not null,
      body          text,
      created_on    timestamp not null default current_timestamp,
      foreign key fk_messages_to_senders (from_user_id) references users (user_id) on delete cascade,
      foreign key fk_messages_to_recipients (to_user_id) references users (user_id) on delete cascade
    ) engine=innodb charset=utf8;

__NOTE:__ It's best to assign every ASP4 application its own namespace.  For this
example the namespace is `App::db::`

Create the file `lib/App::db/model.pm` and add the following lines:

    package App::db::model;
    

    use strict;
    use warnings 'all';
    use base 'Class::DBI::Lite::mysql';
    use ASP4::ConfigLoader;
    

    # Get our configuration object:
    my $Config = ASP4::ConfigLoader->load();
    

    # Get our main database connection info:
    my $conn = $Config->data_connections->main;
    

    # Setup our database connection:
    __PACKAGE__->connection(
      $conn->dsn,
      $conn->username,
      $conn->password
    );
    

    1;# return true:

Add the following `Class::DBI::Lite` entity classes:

`lib/App/db/user.pm`

    package App::db::user;
    

    use strict;
    use warnings 'all';
    use base 'App::db::model';
    use Digest::MD5 'md5_hex';
    use ASP4::ConfigLoader;
    

    __PACKAGE__->set_up_table('users');
    

    __PACKAGE__->has_many(
      messages_in =>
        'App::db::message'  =>
          'to_user_id'
    );
    

    __PACKAGE__->has_many(
      messages_out  =>
        'App::db::message'  =>
          'from_user_id'
    );
    

    # Hash the password before storing it in the database:
    __PACKAGE__->add_trigger( before_create => sub {
      my ($self) = @_;
      

      # Sign the password instead of storing it as plaintext:
      unless( $self->{password} =~ m{^([a-f0-9]{32})$}i ) {
        $self->{password} = $self->hash_password( $self->password );
      }
    });
    

    # Hash the new password before storing it in the database:
    __PACKAGE__->add_trigger( before_update_password => sub {
      my ($self, $old, $new) = @_;
      

      unless( $new =~ m{^([a-f0-9]{32})$}i ) {
        $self->{password} = $self->hash_password( $new );
      }
    });
    

    # Verify an email/password combination and return the user if a match is found:
    sub check_credentials {
      my ($self, %args) = @_;
      

    my ($result) = $self->search(
      email     => $args{email},
      password  => $self->hash_password( $args{password} ),
    );
    

      $result ? return $result : return;
    }
    

    # Convert a password string into its hashed value:
    sub hash_password {
      my ($self, $str) = @_;
      

      my $key = ASP4::ConfigLoader->load->system->settings->signing_key;
      return md5_hex( $str . $key );
    }
    

    1;# return true:

`lib/App/db/message.pm`

    package App::db::message;
    

    use strict;
    use warnings 'all';
    use base 'App::db::model';
    

    __PACKAGE__->set_up_table('messages');
    

    __PACKAGE__->belongs_to(
      sender  =>
        'App::db::user' =>
          'from_user_id'
    );
    

    __PACKAGE__->belongs_to(
      recipient =>
        'App::db::user' =>



( run in 1.010 second using v1.01-cache-2.11-cpan-d7f47b0818f )