Apache-ASP
view release on metacpan or search on metacpan
sub Script_OnParse {
my $code = $Server->{ScriptRef}
$$code .= " ADDED SOMETHING ";
}
=head2 Application_OnStart
This event marks the beginning of an ASP application, and
is run just before the Session_OnStart of the first Session
of an application. This event is useful to load up
$Application with data that will be used in all user sessions.
=head2 Application_OnEnd
The end of the application is marked by this event, which
is run after the last user session has timed out for a
given ASP application.
=head2 Server_OnStart ( pseudo-event )
Some might want something like a Server_OnStart event, where
some code gets runs when the web server starts. In mod_perl,
this is easy to achieve outside of the scope of an ASP
application, by putting some initialization code into
a <Perl> section in the httpd.conf file. Initializations
that you would like to be shared with the child httpds are
particularly useful, one such being the Apache::ASP->Loader()
routine which you can read more about in the TUNING section -
Precompile Scripts subsection. It is could be called like:
# httpd.conf
<Perl>
Apache::ASP->Loader($path, $pattern, %config)
</Perl>
So a <Perl> section is your Server_OnStart routine!
=head2 mod_perl handlers
If one wants to extend one's environment with mod_perl
handlers, Apache::ASP does not stop this. Basic
use of Apache::ASP in fact only involves the content
handler phase of mod_perl's PerlHandler, like
SetHandler perl-script
PerlModule Apache::ASP
PerlHandler Apache::ASP
But mod_perl allows for direct access to many more
Apache event stages, for full list try "perldoc mod_perl"
or buy the mod_perl Eagle book. Some commonly used ones are:
PerlInitHandler
PerlTransHandler
PerlFixupHandler
PerlHandler
PerlLogHandler
PerlCleanupHandler
For straight Apache::ASP programming, there are some
equivalents, say Script_OnStart event instead of Init/Fixup
stages, or $Server->RegisterCleanup() for Log/Cleanup stages,
but you can do things in the mod_perl handlers that you
cannot do in Apache::ASP, especially if you want to handle
all files globally, and not just ASP scripts.
For many Apache::* modules for use with mod_perl, of which
Apache::ASP is just one, check out
http://perl.apache.org/src/apache-modlist.html
To gain access to the ASP objects like $Session outside
in a non-PerlHandler mod_perl handler, you may use this API:
my $ASP = Apache::ASP->new($r); # $r is Apache->request object
as in this possible Authen handler:
<Perl>
use Apache::ASP;
sub My::Auth::handler {
my $r = shift;
my $ASP = Apache::ASP->new($r)
my $Session = $ASP->Session;
}
</Perl>
Here are some examples of do-it-yourself mod_perl
handler programming...
=== Forbid Bad HSlide User Agent ===
# httpd.conf
PerlAccessHandler My::Access
<Perl>
sub My::Access::handler {
my $r = shift;
if($r->headers_in->{'USER_AGENT'} =~ /HSlide/) {
403;
} else {
200;
}
}
</Perl>
=== Runtime Path Parsing ===
This example shows how one might take an arbitrary
URL path /$path/$file.asp, and turn that into a runtime
config for your site, so your scripts get executed
always in your sites DocumentRoot.
INPUT URL /SomeCategory/
OUTPUT
Script: index.asp
$Server->Config('PATH') eq '/SomeCategory'
INPUT URL /SomeCategory/index.asp
OUTPUT
Script: index.asp
$Server->Config('PATH') eq '/SomeCategory'
my $buffer = '&' x 100000;
$buffer = $Server->HTMLEncode($buffer);
print $buffer;
- or -
my $buffer = '&' x 100000;
$Server->HTMLEncode(\$buffer);
print $buffer;
Using the reference passing method in benchmarks on 100K of
data was 5% more efficient, but maybe useful for some.
It saves on copying the 100K buffer twice.
=item $Server->MapInclude($include)
API extension. Given the include $include, as an absolute or relative file name to the current
executing script, this method returns the file path that the include would
be found from the include search path. The include search path is the
current script directory, Global, and IncludesDir directories.
If the include is not found in the includes search path, then undef, or bool false,
is returned. So one may do something like this:
if($Server->MapInclude('include.inc')) {
$Response->Include('include.inc');
}
This code demonstrates how one might only try to execute an include if
it exists, which is useful since a script will error if it tries to execute an include
that does not exist.
=item $Server->MapPath($url);
Given the url $url, absolute, or relative to the current executing script,
this method returns the equivalent filename that the server would
translate the request to, regardless or whether the request would be valid.
Only a $url that is relative to the host is valid. Urls like "." and
"/" are fine arguments to MapPath, but http://localhost would not be.
To see this method call in action, check out the sample ./site/eg/server.htm
script.
=item $Server->Mail(\%mail, %smtp_args);
With the Net::SMTP and Net::Config modules installed, which are part of the
perl libnet package, you may use this API extension to send email. The
\%mail hash reference that you pass in must have values for at least
the To, From, and Subject headers, and the Body of the mail message.
The return value of this routine is 1 for success, 0 for failure. If the MailHost
SMTP server is not available, this will have a return value of 0.
You could send an email like so:
$Server->Mail({
To => 'somebody@yourdomain.com.foobar',
From => 'youremail@yourdomain.com.foobar',
Subject => 'Subject of Email',
Body =>
'Body of message. '.
'You might have a lot to say here!',
Organization => 'Your Organization',
CC => 'youremailcc@yourdomain.com.foobar',
BCC => 'youremailbcc@yourdomain.com.foobar',
Debug => 0 || 1,
});
Any extra fields specified for the email will be interpreted
as headers for the email, so to send an HTML email, you
could set 'Content-Type' => 'text/html' in the above example.
If you have MailFrom configured, this will be the default
for the From header in your email. For more configuration
options like the MailHost setting, check out the CONFIG section.
The return value of this method call will be boolean for
success of the mail being sent.
If you would like to specially configure the Net::SMTP
object used internally, you may set %smtp_args and they
will be passed on when that object is initialized.
"perldoc Net::SMTP" for more into on this topic.
If you would like to include the output of an ASP page as the
body of the mail message, you might do something like:
my $mail_body = $Response->TrapInclude('mail_body.inc');
$Server->Mail({ %mail, Body => $$mail_body });
=item $Server->RegisterCleanup($sub)
non-portable extension
Sets a subroutine reference to be executed after the script ends,
whether normally or abnormally, the latter occurring
possibly by the user hitting the STOP button, or the web server
being killed. This subroutine must be a code reference
created like:
$Server->RegisterCleanup(sub { $main::Session->{served}++; });
or
sub served { $main::Session->{served}++; }
$Server->RegisterCleanup(\&served);
The reference to the subroutine passed in will be executed.
Though the subroutine will be executed in anonymous context,
instead of the script, all objects will still be defined
in main::*, that you would reference normally in your script.
Output written to $main::Response will have no affect at
this stage, as the request to the www client has already completed.
Check out the ./site/eg/register_cleanup.asp script for an example
of this routine in action.
=item $Server->Transfer($file, @args)
New method from ASP 3.0. Transfers control to another script.
The Response buffer will not be cleared automatically, so if you
want this to serve as a faster $Response->Redirect(), you will need to
call $Response->Clear() before calling this method.
directives which enable Apache::ASP to the parse the session id
into document URLs on the fly. Because this is resource
inefficient, there is also the SessionQuery* directives
that may be used with the $Server->URL($url,\%params) method to
generate custom URLs with the session id in its query string.
To see an example of these cookieless sessions in action,
check out the ./site/eg/session_query_parse.asp example.
*** WARNING ***
If you do use these methods, then be VERY CAREFUL
of linking offsite from a page that was accessed with a
session id in a query string. This is because this session
id will show up in the HTTP_REFERER logs of the linked to
site, and a malicious hacker could use this information to
compromise the security of your site's $Sessions, even if
these are run under a secure web server.
In order to shake a session id off an HTTP_REFERER for a link
taking a user offsite, you must point that link to a redirect
page that will redirect a user, like so:
<%
# "cross site scripting bug" prevention
my $sanitized_url =
$Server->HTMLEncode($Response->QueryString('OffSiteUrl'));
%>
<html>
<head>
<meta http-equiv=refresh content='0;URL=<%=$sanitized_url%>'>
</head>
<body>
Redirecting you offsite to
<a href=<%=$sanitized_url%> >here</a>...
</body>
</html>
Because the web browser visits a real page before being redirected
with the <meta> tag, the HTTP_REFERER will be set to this page.
Just be sure to not link to this page with a session id in its
query string.
Unfortunately a simple $Response->Redirect() will not work here,
because the web browser will keep the HTTP_REFERER of the
original web page if only a normal redirect is used.
=head1 XML/XSLT
=head2 Custom Tags with XMLSubsMatch
Before XML, there was the need to make HTML markup smarter.
Apache::ASP gives you the ability to have a perl
subroutine handle the execution of any predefined tag,
taking the tag descriptors, and the text contained between,
as arguments of the subroutine. This custom tag
technology can be used to extend a web developer's abilities
to add dynamic pieces without having to visibly use
<% %> style code entries.
So, lets say that you have a table that
you want to insert for an employee with contact
info and the like, you could set up a tag like:
<my:new-employee name="Jane" last="Doe" phone="555-2222">
Jane Doe has been here since 1998.
</my:new-employee>
To render it with a custom tag, you would tell
the Apache::ASP parser to render the tag with a
subroutine:
PerlSetVar XMLSubsMatch my:new-employee
Any colons, ':', in the XML custom tag will turn
into '::', a perl package separator, so the my:employee
tag would translate to the my::employee subroutine, or the
employee subroutine in the my package. Any dash "-" will
also be translated to an underscore "_", as dash is not valid
in the names of perl subroutines.
Then you would create the my::employee subroutine in the my
perl package or whereever like so:
package my;
sub new_employee {
my($attributes, $body) = @_;
$main::Response->Include('new_employee.inc', $attributes, $body);
}
1;
<!-- # new_employee.inc file somewhere else, maybe in Global directory -->
<% my($attributes, $body) = @_; %>
<table>
<% for('name', 'last', 'phone') { %>
<tr>
<td><b><%=ucfirst $_ %></b>:</td>
<td><%= $attributes->{$_} %></td>
</tr>
<% } %>
<tr><td colspan=2><%= $body %></td></tr>
</table>
<!-- # end new_employee.inc file -->
The $main::Response->Include() would then delegate the rendering
of the new-employee to the new_employee.inc ASP script include.
Though XML purists would not like this custom tag technology
to be related to XML, the reality is that a careful
site engineer could render full XML documents with this
technology, applying all the correct styles that one might
otherwise do with XSLT.
Custom tags defined in this way can be used as XML tags
are defined with both a body and without as it
<my:new-employee>...</my:new-employee>
and just
<my:new-employee />
One of perl's blessings is also its bane, variables do not need to be
declared, and are by default globally scoped. The problem with this in
mod_perl is that global variables persist from one request to another
even if a different web browser is viewing a page.
To avoid this problem, perl programmers have often been advised to
add to the top of their perl scripts:
use strict;
In Apache::ASP, you can do this better by setting:
PerlSetVar UseStrict 1
which will cover both script & global.asa compilation and will catch
"use strict" errors correctly. For perl modules, please continue to
add "use strict" to the top of them.
Because its so essential in catching hard to find errors, this
configuration will likely become the default in some future release.
For now, keep setting it.
=head2 Do not define subroutines in scripts.
DO NOT add subroutine declarations in scripts. Apache::ASP is optimized
by compiling a script into a subroutine for faster future invocation.
Adding a subroutine definition to a script then looks like this to
the compiler:
sub page_script_sub {
...
... some HTML ...
...
sub your_sub {
...
}
...
}
The biggest problem with subroutines defined in subroutines is the
side effect of creating closures, which will not behave as usually
desired in a mod_perl environment. To understand more about closures,
please read up on them & "Nested Subroutines" at:
http://perl.apache.org/docs/general/perl_reference/perl_reference.html
Instead of defining subroutines in scripts, you may add them to your sites
global.asa, or you may create a perl package or module to share
with your scripts. For more on perl objects & modules, please see:
http://perldoc.perl.org/perlobj.html
=head2 Use global.asa's Script_On* Events
Chances are that you will find yourself doing the same thing repeatedly
in each of your web application's scripts. You can use Script_OnStart
and Script_OnEnd to automate these routine tasks. These events are
called before and after each script request.
For example, let's say you have a header & footer you would like to
include in the output of every page, then you might:
# global.asa
sub Script_OnStart {
$Response->Include('header.inc');
}
sub Script_OnEnd {
$Response->Include('footer.inc');
}
Or let's say you want to initialize a global database connection
for use in your scripts:
# global.asa
use Apache::DBI; # automatic persistent database connections
use DBI;
use vars qw($dbh); # declare global $dbh
sub Script_OnStart {
# initialize $dbh
$dbh = DBI->connect(...);
# force you to explicitly commit when you want to save data
$Server->RegisterCleanup(sub { $dbh->rollback; });
}
sub Script_OnEnd {
# not really necessary when using persistent connections, but
# will free this one object reference at least
$dbh = undef;
}
=head1 FAQ
The following are some frequently asked questions
about Apache::ASP.
=head2 Installation
=item Examples don't work, I see the ASP script in the browser?
This is most likely that Apache is not configured to execute
the Apache::ASP scripts properly. Check the INSTALL QuickStart
section for more info on how to quickly set up Apache to
execute your ASP scripts.
=item Apache Expat vs. XML perl parsing causing segfaults, what do I do?
Make sure to compile apache with expat disabled. The
./make_httpd/build_httpds.sh in the distribution will do
this for you, with the --disable-rule=EXPAT in particular:
cd ../$APACHE
echo "Building apache =============================="
./configure \
--prefix=/usr/local/apache \
--activate-module=src/modules/perl/libperl.a \
--enable-module=ssl \
--enable-module=proxy \
--enable-module=so \
--disable-rule=EXPAT
^^^^^
keywords: segmentation fault, segfault seg fault
=item Why do variables retain their values between requests?
Unless scoped by my() or local(), perl variables in mod_perl
are treated as globals, and values set may persist from one
=begin html
<a href=http://www.redhat.com><img src=redhat_logo.gif border=0></a>
=end html
We're using Apache::ASP on www.redhat.com. We find Apache::ASP very
easy to use, and it's quick for new developers to get up to speed with
it, given that many people have already been exposed to the ASP object
model that Apache::ASP is based on.
The documentation is comprehensive and easy to understand, and the
community and maintainer have been very helpful whenever we've had
questions.
-- Tom Lancaster, Red Hat
=item Anime Wallpaper at Anime Cubed
Your suite has got our old CGI implementation beat, hands down. Our site is divided into two main areas, each run by a separate developer, and the Apache::ASP section runs head and shoulders above the other side. Anyone who is still using anything bu...
-- Al from 'Anime Wallpaper at Anime Cubed', http://www.animecubed.com/wallpapers/
=item gutscheinwurst.de
I am the web master of http://www.gutscheinwurst.de , a German voucher community.
We use Apache::Asp to run our backend & administration servers for the system. We started using Apache::ASP to see whether it is a valid alternative to IIS legacy systems. So far all expectations in regard of performance, ease of development and inte...
Thank's for such a great product :)
-- Johnannes Leimbach
=item D. L. Fox
I had programmed in Perl for some time ... but,
since I also knew VB, I had switched to VB in IIS-ASP for
web stuff because of its ease of use in embedding code
with HTML ... When I discovered
Apache-ASP, it was like a dream come true. I would much rather code in Perl
than any other language. Thanks for such a fine product!
=item HOSTING 321, LLC.
After discontinuing Windows-based hosting due to the high cost of software,
our clients are thrilled with Apache::ASP and they swear ASP it's faster
than before. Installation was a snap on our 25-server web farm with a small
shell script and everything is running perfectly! The documentation is
very comprehensive and everyone has been very helpful during this migration.
Thank you!
-- Richard Ward, HOSTING 321, LLC.
=item Concept Online Ltd.
=begin html
<a href=http://www.conceptonline.com><img src=concept_online.gif border=0></a>
=end html
I would like to say that your ASP module rocks :-) We have practically stopped developing in anything else about half a year ago, and are now using Apache::ASP extensively. I just love Perl, and whereever we are not "forced" to use JSP, we chose ASP....
-- Csongor Fagyal, Concept Online Ltd.
=item WebTime
=begin html
<a href="http://webtime-project.net"><img border=0 src="webtimelogo.jpg"></a>
=end html
As we have seen with WebTime, Apache::ASP is not only good for the
development of website, but also for the development of webtools. Since
I first discoverd it, I made it a must-have in my society by taking
traditional PHP users to the world of perl afficionados.
Having the possibility to use Apache::ASP with mod_perl or mod_cgi make
it constraintless to use because of CGI's universality and perl's
portability.
-- Grégoire Lejeune
=item David Kulp
First, I just want to say that I am very very impressed with Apache::ASP. I
just want to gush with praise after looking at many other implementations of
perl embedded code and being very underwhelmed. This is so damn slick and
clean. Kudos! ...
... I'm very pleased how quickly I've been able to mock
up the application. I've been writing Perl CGI off and on since 1993(!)
and I can tell you that Apache::ASP is a pleasure. (Last year I tried
Zope and just about threw my computer out the window.)
-- David Kulp
=item MFM Commmunication Software, Inc.
=begin html
<table border=0><tr><td>
<a href="http://www.mfm.com"><img src="communication_software.gif" border=0></a>
<p>
<a href=http://www.huff.com/>HUFF Realty</a>
<br>
<a href=http://www.starone.com/>Star One Realtors</a>
<br>
<a href=http://www.comey.com/>Comey & Shepherd Realtors</a>
<br>
<a href=http://www.unlimitedrealestate.net/>RE/MAX Unlimited Realtors</a>
<br>
<a href=http://www.cincinnatibuilders.com/>Cincinnati Builders</a>
<br>
<a href=http://www.airportdays.com/>Blue Ash Airport Days Airshow</a>
</td></tr></table>
=end html
Working in a team environment where you have HTML coders and perl
coders, Apache::ASP makes it easy for the HTML folks to change the look
of the page without knowing perl. Using Apache::ASP (instead of another
embedded perl solution) allows the HTML jockeys to use a variety of HTML
tools that understand ASP, which reduces the amount of code they break
when editing the HTML. Using Apache::ASP instead of M$ ASP allows us to
use perl (far superior to VBScript) and Apache (far superior to IIS).
We've been very pleased with Apache::ASP and its support.
=item Planet of Music
Apache::ASP has been a great tool. Just a little
background.... the whole site had been in cgi flat files when I started
here. I was looking for a technology that would allow me to write the
objects and NEVER invoke CGI.pm... I found it and hopefuly I will be able to
implement this every site I go to.
When I got here there was a huge argument about needing a game engine
and I belive this has been the key... Games are approx. 10 time faster than
before. The games don't break anylonger. All in all a great tool for
advancement.
-- JC Fant IV
=item Cine.gr
( run in 0.725 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )