# 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 `
` returns a string like `<br/>`
### $Server->HTMLDecode( $string )
Given a string like `<br/>` returns a string like `
`
### $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")
This is an html email.
You can see that this text is bold.
HTML ); Please see [Mail::Sendmail](http://search.cpan.org/perldoc?Mail::Sendmail) for further details and examples. ### $Server->RegisterCleanup( sub { ... }, \@args ) After the final response has been sent to the client, the server will execute your subref and provide it the `\@args` passed in. This is useful for long-running or asynchronous processes that don't require the client to wait for a response. ## $Request An instance of [ASP4::Request](http://search.cpan.org/perldoc?ASP4::Request), the `$Request` object contains specialized methods for dealing with whatever the browser sent us. Examples: ### $Request->Cookies( $name ) my $cookie = $Request->Cookies("some-cookie-name"); ### $Request->FileUpload( $field_name ) if( my $file = $Request->FileUpload('avatar_pic') ) { # Handle the uploaded file: $file->SaveAs( "/var/media/$Session->{user_id}/avatar/" . $file->FileName ); } See also the [ASP4::FileUpload](http://search.cpan.org/perldoc?ASP4::FileUpload) documentation. ## $Response An instance of [ASP4::Response](http://search.cpan.org/perldoc?ASP4::Response), the `$Response` object gives shortcuts for dealing with the outgoing reply from the server back to the client. Examples: ### $Response->Write( $string ) The following example prints the string `Hello, World!` to the browser: $Response->Write("Hello, World!"); Or, within an ASP script, `<%= "Hello, World" %>` ### $Response->Redirect( $url ) $Response->Redirect( "/new/url/?foo=bar" ); ### $Response->SetCookie( %args ) Setting cookies works as follows: $Response->SetCookie( name => "cookie-name", value => "the-value", # The rest of these arguments are optional: # Expires: (If you don't specify the "expires" argument, the cookie will # be deleted when the browser is closed. expires => "3D", # 3 days expires => "3H", # or 3 hours expires => "3M", # or 3 minutes # Domain: (defaults to $ENV{HTTP_HOST}) domain => ".example.com", # works for *.example.com domain => "www.example.com", # will ONLY work for www.example.com # Path: path => "/some/folder/" # will ONLY work within /some/folder/ on your website ); ### $Response->Include( $path, %args ) ASP4's `$Response` object offers 3 different include methods. If you want to supply arguments to the included ASP script you can use `$Response->Include($path, \%args)` # Add the output of C 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: 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' => 'to_user_id' ); 1;# return true: Create your MasterPage like this: File: `htdocs/masters/global.asp` <%@ MasterPage %>