which is not always wanted or expected. Set XMLSubsStrict to 1 if this
is the case.
XSLT
default not defined, if set to a file, ASP scripts will be regarded as
XML output and transformed with the given XSL file with XML::XSLT. This
XSL file will also be executed as an ASP script first, and its output
will be the XSL data used for the transformation. This XSL file will be
executed as a dynamic include, so may be located in the current
directory, Global, or IncludesDir.
Please see the XML/XSLT section for an explanation of its use.
PerlSetVar XSLT template.xsl
XSLTMatch
default .*, if XSLT is set by default all ASP scripts will be XSL
transformed by the specified XSL template. This regexp setting will tell
XSLT which file names to match with doing XSL transformations, so that
regular HTML ASP scripts and XML ASP scripts can be configured with the
same configuration block. Please see ./site/eg/.htaccess for an example
of its use.
PerlSetVar XSLTMatch \.xml$
XSLTParser
default XML::XSLT, determines which perl module to use for XSLT parsing.
This is a new config as of 2.11. Also supported is XML::Sablotron which
does not handle XSLT with the exact same output, but is about 10 times
faster than XML::XSLT. XML::LibXSLT may also be used as of version 2.29,
and seems to be about twice again as fast as XML::Sablotron, and a very
complete XSLT implementation.
PerlSetVar XSLTParser XML::XSLT
PerlSetVar XSLTParser XML::Sablotron
PerlSetVar XSLTParser XML::LibXSLT
XSLTCache
Activate XSLT file based caching through CacheDB, CacheDir, and
CacheSize settings. This gives cached XSLT performance near AxKit and
greater than Cocoon. XSLT caches transformations keyed uniquely by XML &
XSLT inputs.
PerlSetVar XSLTCache 1
XSLTCacheSize
as of version 2.11, this config is no longer supported.
Caching
The output caching layer is a file dbm based output cache that runs on
top of the MLDBM::Sync so inherits its performance characteristics. With
CacheDB set to MLDBM::Sync::SDBM_File, the cache layer is very fast at
caching entries up to 20K in size, but for greater cached items, you
should set CacheDB to another dbm like DB_File or GDBM_File.
In order for the cache layer to function properly, whether for
$Response->Include() output caching, see OBJECTS, or XSLT caching, see
XML/XSLT, then Apache::ASP must be loaded in the parent httpd like so:
# httpd.conf
PerlModule Apache::ASP
-- or --
use Apache::ASP;
The cache layer automatically expires entries upon server restart, but
for this to work, a $ServerID must be computed when the Apache::ASP
module gets loaded to store in each cached item. Without the above done,
each child httpd process will get its own $ServerID, so caching will not
work at all.
This said, output caching will not work in raw CGI mode, just running
under mod_perl.
CacheDB
Like StateDB, sets dbm format for caching. Since SDBM_File only support
key/values pairs of around 1K max in length, the default for this is
MLDBM::Sync::SDBM_File, which is very fast for < 20K output sizes. For
caching larger data than 20K, DB_File or GDBM_File are probably better
to use.
PerlSetVar CacheDB MLDBM::Sync::SDBM_File
For your own benchmarks to test the relative speeds of the various DBMs
under MLDBM::Sync, which is used by CacheDB, you may run the
./bench/bench_sync.pl script from the MLDBM::Sync distribution on your
system.
CacheDir
By default, the cache directory is at StateDir/cache, but CacheDir can
be used to set the StateDir value for caching purposes. One may want the
CacheDir separate from StateDir for example StateDir might be a
centrally network mounted file system, while CacheDir might be a local
file cache.
PerlSetVar CacheDir /tmp/asp_demo
On a system like Solaris where there is a RAM disk mounted on the system
like /tmp, I could put the CacheDir there. On a system like Linux where
files are cached pretty well by default, this is less important.
CacheSize
By default, this is 10M of data per cache. When any cache, like the
XSLTCache, reaches this limit, the cache will be purged by deleting the
cached dbm files entirely. This is better for long term running of dbms
than deleting individual records, because dbm formats will often degrade
in performance with lots of insert & deletes.
Units of M, K, and B are supported for megabytes, kilobytes, and bytes,
with the default unit being B, so the following configs all mean the
same thing;
PerlSetVar CacheSize 10M
PerlSetVar CacheSize 10240K
PerlSetVar CacheSize 10485760B
PerlSetVar CacheSize 10485760
There are 2 caches currently, the XSLTCache, and the Response cache, the
latter which is currently invoked for caching output from includes with
special syntax. See $Response->Include() for more info on the Response
cache.
Miscellaneous
AuthServerVariables
default 0. If you are using basic auth and would like
$Request->ServerVariables set like AUTH_TYPE, AUTH_USER, AUTH_NAME,
REMOTE_USER, & AUTH_PASSWD, then set this and Apache::ASP will
initialize these values from Apache->*auth* commands. Use of these
environment variables keeps applications cross platform compatible as
other servers set these too when performing basic 401 auth.
PerlSetVar AuthServerVariables 0
BufferingOn
default 1, if true, buffers output through the response object.
$Response object will only send results to client browser if a
$Response->Flush() is called, or if the asp script ends. Lots of output
will need to be flushed incrementally.
If false, 0, the output is immediately written to the client, CGI style.
There will be a performance hit server side if output is flushed
automatically to the client, but is probably small.
I would leave this on, since error handling is poor, if your asp script
errors after sending only some of the output.
PerlSetVar BufferingOn 1
InodeNames
Default 0. Set to 1 to uses a stat() call on scripts and includes to
derive subroutine namespace based on device and inode numbers. In case
of multiple symbolic links pointing to the same script this will result
in the script being compiled only once. Use only on unix flavours which
support the stat() call that know about device and inode numbers.
PerlSetVar InodeNames 1
RequestParams
Default 0, if set creates $Request->Params object with combined contents
of $Request->QueryString and $Request->Form. This is for developer
convenience simlar to CGI.pm's param() method.
PerlSetVar RequestParams 1
StatINC
default 0, if true, reloads perl libraries that have changed on disk
automatically for ASP scripts. If false, the www server must be
restarted for library changes to take effect.
A known bug is that any functions that are exported, e.g. confess Carp
qw(confess), will not be refreshed by StatINC. To refresh these, you
must restart the www server.
This setting should be used in development only because it is so slow.
For a production version of StatINC, see StatINCMatch.
PerlSetVar StatINC 1
StatINCMatch
default undef, if defined, it will be used as a regular expression to
reload modules that match as in StatINC. This is useful because StatINC
has a very high performance penalty in production, so if you can narrow
the modules that are checked for reloading each script execution to a
handful, you will only suffer a mild performance penalty.
The StatINCMatch setting should be a regular expression like: Struct|LWP
which would match on reloading Class/Struct.pm, and all the LWP/.*
libraries.
If you define StatINCMatch, you do not need to define StatINC.
PerlSetVar StatINCMatch .*
StatScripts
default 1, if set to 0, changed scripts, global.asa, and includes will
not be reloaded. Coupled with Apache mod_perl startup and restart
handlers executing Apache::ASP->Loader() for your application this
allows your application to be frozen, and only reloaded on the next
server restart or stop/start.
There are a few advantages for not reloading scripts and modules in
production. First there is a slight performance improvement by not
having to stat() the script, its includes and the global.asa every
request.
From an application deployment standpoint, you also gain the ability to
deploy your application as a snapshot taken when the server starts and
restarts. This provides you with the reassurance that during a
production server update from development sources, you do not have to
worry with sources being used for the wrong libraries and such, while
they are all being copied over.
Finally, though you really should not do this, you can work on a live
production application, with a test server reloading changes, but your
production server does see the changes until you restart or stop/start
it. This saves your public from syntax errors while you are just doing a
quick bug fix.
PerlSetVar StatScripts 1
SoftRedirect
default 0, if true, a $Response->Redirect() does not end the script.
Normally, when a Redirect() is called, the script is ended
automatically. SoftRedirect 1, is a standard way of doing redirects,
allowing for html output after the redirect is specified.
PerlSetVar SoftRedirect 0
Filter
On/Off, default Off. With filtering enabled, you can take advantage of
full server side includes (SSI), implemented through Apache::SSI. SSI is
implemented through this mechanism by using Apache::Filter. A sample
configuration for full SSI with filtering is in the ./site/eg/.htaccess
file, with a relevant example script ./site/eg/ssi_filter.ssi.
You may only use this option with modperl v1.16 or greater installed and
PERL_STACKED_HANDLERS enabled. Filtering may be used in conjunction with
other handlers that are also "filter aware". If in doubt, try building
your mod_perl with
perl Makefile.PL EVERYTHING=1
With filtering through Apache::SSI, you should expect near a a 20%
performance decrease.
PerlSetVar Filter Off
CgiHeaders
default 0. When true, script output that looks like HTTP / CGI headers,
will be added to the HTTP headers of the request. So you could add:
Set-Cookie: test=message
...
to the top of your script, and all the headers preceding a newline
will be added as if with a call to $Response->AddHeader(). This
functionality is here for compatibility with raw cgi scripts,
and those used to this kind of coding.
When set to 0, CgiHeaders style headers will not be parsed from the
script response.
PerlSetVar CgiHeaders 0
Clean
default 0, may be set between 1 and 9. This setting determine how much
text/html output should be compressed. A setting of 1 strips mostly
white space saving usually 10% in output size, at a performance cost of
less than 5%. A setting of 9 goes much further saving anywhere 25% to
50% typically, but with a performance hit of 50%.
This config option is implemented via HTML::Clean. Per script
configuration of this setting is available via the $Response->{Clean}
property, which may also be set between 0 and 9.
PerlSetVar Clean 0
CompressGzip
default 0, if true will gzip compress HTML output on the fly if
Compress::Zlib is installed, and the client browser supports it.
Depending on the HTML being compressed, the client may see a 50% to 90%
reduction in HTML output. I have seen 40K of HTML squeezed down to just
under 6K. This will come at a 5%-20% hit to CPU usage per request
compressed.
Note there are some cases when a browser says it will accept gzip
encoding, but then not render it correctly. This behavior has been seen
with IE5 when set to use a proxy but not using a proxy, and the URL does
not end with a .html or .htm. No work around has yet been found for this
case so use at your own risk.
PerlSetVar CompressGzip 1
FormFill
default 0, if true will auto fill HTML forms with values from
$Request->Form(). This functionality is provided by use of
HTML::FillInForm. For more information please see "perldoc
HTML::FillInForm", and the example ./site/eg/formfill.asp.
This feature can be enabled on a per form basis at runtime with
$Response->{FormFill} = 1
PerlSetVar FormFill 1
TimeHiRes
default 0, if set and Time::HiRes is installed, will do sub second
timing of the time it takes Apache::ASP to process a request. This will
not include the time spent in the session manager, nor modperl or
Apache, and is only a rough approximation at best.
If Debug is set also, you will get a comment in your HTML output that
indicates the time it took to process that script.
If system debugging is set with Debug -1 or -2, you will also get this
time in the Apache error log with the other system messages.
Mail Administration
Apache::ASP has some powerful administrative email extensions that let
you sleep at night, knowing full well that if an error occurs at the web
site, you will know about it immediately. With these features already
enabled, it was also easy to provide the $Server->Mail(\%mail) API
extension which you can read up about in the OBJECTS section.
MailHost
The mail host is the smtp server that the below Mail* config directives
will use when sending their emails. By default Net::SMTP uses smtp mail
hosts configured in Net::Config, which is set up at install time, but
this setting can be used to override this config.
The mail hosts specified in the Net::Config file will be used as backup
smtp servers to the MailHost specified here, should this primary server
not be working.
PerlSetVar MailHost smtp.yourdomain.com.foobar
MailFrom
Default NONE, set this to specify the default mail address placed in the
From: mail header for the $Server->Mail() API extension, as well as
MailErrorsTo and MailAlertTo.
PerlSetVar MailFrom youremail@yourdomain.com.foobar
MailErrorsTo
No default, if set, ASP server errors, error code 500, that result while
compiling or running scripts under Apache::ASP will automatically be
emailed to the email address set for this config. This allows an
administrator to have a rapid response to user generated server errors
resulting from bugs in production ASP scripts. Other errors, such as 404
not found will be handled by Apache directly.
An easy way to see this config in action is to have an ASP script which
calls a die(), which generates an internal ASP 500 server error.
The Debug config of value 2 and this setting are mutually exclusive, as
Debug 2 is a development setting where errors are displayed in the
browser, and MailErrorsTo is a production setting so that errors are
silently logged and sent via email to the web admin.
PerlSetVar MailErrorsTo youremail@yourdomain.com
MailAlertTo
The address configured will have an email sent on any ASP server error
500, and the message will be short enough to fit on a text based pager.
This config setting would be used to give an administrator a heads up
that a www server error occurred, as opposed to MailErrorsTo would be
used for debugging that server error.
This config does not work when Debug 2 is set, as it is a setting for
use in production only, where Debug 2 is for development use.
PerlSetVar MailAlertTo youremail@yourdomain.com
MailAlertPeriod
Default 20 minutes, this config specifies the time in minutes over which
there may be only one alert email generated by MailAlertTo. The purpose
of MailAlertTo is to give the admin a heads up that there is an error at
the www server. MailErrorsTo is for to aid in speedy debugging of the
incident.
PerlSetVar MailAlertPeriod 20
File Uploads
FileUploadMax
default 0, if set will limit file uploads to this size in bytes. This is
currently implemented by setting $CGI::POST_MAX before handling the file
upload. Prior to this, a developer would have to hardcode a value for
$CGI::POST_MAX to get this to work.
PerlSetVar 100000
FileUploadTemp
default 0, if set will leave a temp file on disk during the request,
which may be helpful for processing by other programs, but is also a
security risk in that other users on the operating system could
potentially read this file while the script is running.
The path to the temp file will be available at
$Request->{FileUpload}{$form_field}{TempFile}. The regular use of file
uploads remains the same with the <$filehandle> to the upload at
$Request->{Form}{$form_field}. Please see the CGI section for more
information on file uploads, and the $Request section in OBJECTS.
PerlSetVar FileUploadTemp 0
SYNTAX
General
ASP embedding syntax allows one to embed code in html in 2 simple ways.
The first is the <% xxx %> tag in which xxx is any valid perl code. The
second is <%= xxx %> where xxx is some scalar value that will be
inserted into the html directly. An easy print.
A simple asp page would look like:
For loop incrementing font size:
<% for(1..5) { %>
Size = <%=$_%>
<% } %>
Notice that your perl code blocks can span any html. The for loop above
iterates over the html without any special syntax.
XMLSubs
XMLSubs allows a developer to define custom handlers for HTML & XML
tags, which can extend the natural syntax of the ASP environment.
Configured like:
PerlSetVar XMLSubsMatch site:\w+
A simple tag like:
can be constructed that could translate into:
sub site::header {
my $args = shift;
print "
$args->{title}\n";
print "\n";
}
Better yet, one can use this functionality to trap and post process
embedded HTML & XML like:
... some HTML here ...
and then:
sub site::page {
my($args, $html) = @_;
&site::header($args);
$main::Response->Write($html);
$main::Response->Write("");
}
Though this could be used to fully render XML documents, it was not
built for this purpose, but to add powerful tag extensions to HTML
development environments. For full XML rendering, you ought to try an
XSLT approach, also supported by Apache::ASP.
Editors
As Apache::ASP supports a mixing of perl and HTML, any editor which
supports development of one or the other would work well. The following
editors are known to work well for developing Apache::ASP web sites:
* Emacs, in perl or HTML modes. For a mmm-mode config
that mixes HTML & perl modes in a single buffer, check
out the editors/mmm-asp-perl.el file in distribution.
* Microsoft Frontpage
* Vim, special syntax support with editors/aasp.vim file in distribution.
* UltraEdit32 ( http://www.ultraedit.com/ ) has syntax highlighting,
good macros and a configurable wordlist (so one can have syntax
highlighting both for Perl and HTML).
Please feel free to suggest your favorite development environment for
this list.
EVENTS
Overview
The ASP platform allows developers to create Web Applications. In
fulfillment of real software requirements, ASP allows event-triggered
actions to be taken, which are defined in a global.asa file. The
global.asa file resides in the Global directory, defined as a config
option, and may define the following actions:
Action Event
------ ------
Script_OnStart * Beginning of Script execution
Script_OnEnd * End of Script execution
Script_OnFlush * Before $Response being flushed to client.
Application_OnStart Beginning of Application
Application_OnEnd End of Application
Session_OnStart Beginning of user Session.
Session_OnEnd End of user Session.
* These are API extensions that are not portable, but were
added because they are incredibly useful
These actions must be defined in the $Global/global.asa file as
subroutines, for example:
sub Session_OnStart {
$Application->{$Session->SessionID()} = started;
}
Sessions are easy to understand. When visiting a page in a web
application, each user has one unique $Session. This session expires,
after which the user will have a new $Session upon revisiting.
A web application starts when the user visits a page in that
application, and has a new $Session created. Right before the first
$Session is created, the $Application is created. When the last user
$Session expires, that $Application expires also. For some web
applications that are always busy, the Application_OnEnd event may never
occur.
Script_OnStart & Script_OnEnd
The script events are used to run any code for all scripts in an
application defined by a global.asa. Often, you would like to run the
same code for every script, which you would otherwise have to add by
hand, or add with a file include, but with these events, just add your
code to the global.asa, and it will be run.
There is one caveat. Code in Script_OnEnd is not guaranteed to be run
when $Response->End() is called, since the program execution ends
immediately at this event. To always run critical code, use the API
extension:
$Server->RegisterCleanup()
Session_OnStart
Triggered by the beginning of a user's session, Session_OnStart gets run
before the user's executing script, and if the same session recently
timed out, after the session's triggered Session_OnEnd.
The Session_OnStart is particularly useful for caching database data,
and avoids having the caching handled by clumsy code inserted into each
script being executed.
Session_OnEnd
Triggered by a user session ending, Session_OnEnd can be useful for
cleaning up and analyzing user data accumulated during a session.
Sessions end when the session timeout expires, and the StateManager
performs session cleanup. The timing of the Session_OnEnd does not occur
immediately after the session times out, but when the first script runs
after the session expires, and the StateManager allows for that session
to be cleaned up.
So on a busy site with default SessionTimeout (20 minutes) and
StateManager (10 times) settings, the Session_OnEnd for a particular
session should be run near 22 minutes past the last activity that
Session saw. A site infrequently visited will only have the
Session_OnEnd run when a subsequent visit occurs, and theoretically the
last session of an application ever run will never have its
Session_OnEnd run.
Thus I would not put anything mission-critical in the Session_OnEnd,
just stuff that would be nice to run whenever it gets run.
Script_OnFlush
API extension. This event will be called prior to flushing the $Response
buffer to the web client. At this time, the $Response->{BinaryRef}
buffer reference may be used to modify the buffered output at runtime to
apply global changes to scripts output without having to modify all the
scripts.
sub Script_OnFlush {
my $ref = $Response->{BinaryRef};
$$ref =~ s/\s+/ /sg; # to strip extra white space
}
Check out the ./site/eg/global.asa for an example of its use.
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.
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.
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 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
Apache::ASP->Loader($path, $pattern, %config)
So a section is your Server_OnStart routine!
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:
use Apache::ASP;
sub My::Auth::handler {
my $r = shift;
my $ASP = Apache::ASP->new($r)
my $Session = $ASP->Session;
}
Here are some examples of do-it-yourself mod_perl handler programming...
=== Forbid Bad HSlide User Agent ===
# httpd.conf
PerlAccessHandler My::Access
sub My::Access::handler {
my $r = shift;
if($r->header_in('USER_AGENT') =~ /HSlide/) {
403;
} else {
200;
}
}
=== 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'
INPUT URI /index.asp
OUTPUT
Script: index.asp
$Server->Config('PATH') eq ''
# httpd.conf
PerlTransHandler My::Init
use lib qw( $custom_perllib );
# $custom_perllib/My/Init.pm
package My::Init;
use strict;
use Apache::Constants qw(:common);
sub handler {
my $r = shift;
my $uri = $r->uri || '/';
unless($uri =~ m|^(.*)(/([^/.]+\.[\w]+)?)$|i) {
warn("can't parse uri $uri");
return DECLINED;
}
$uri = $2;
my $PATH = $1 || '';
$r->dir_config('PATH', $PATH);
if($uri eq '/') {
$uri = '/index.asp';
}
$r->uri($uri);
$r->filename($r->document_root.$uri);
DECLINED;
}
1;
OBJECTS
The beauty of the ASP Object Model is that it takes the burden of CGI
and Session Management off the developer, and puts them in objects
accessible from any ASP script & include. For the perl programmer, treat
these objects as globals accessible from anywhere in your ASP
application.
The Apache::ASP object model supports the following:
Object Function
------ --------
$Session - user session state
$Response - output to browser
$Request - input from browser
$Application - application state
$Server - general methods
These objects, and their methods are further defined in the following
sections.
If you would like to define your own global objects for use in your
scripts and includes, you can initialize them in the global.asa
Script_OnStart like:
use vars qw( $Form $Site ); # declare globals
sub Script_OnStart {
$Site = My::Site->new; # init $Site object
$Form = $Request->Form; # alias form data
$Server->RegisterCleanup(sub { # garbage collection
$Site->DESTROY;
$Site = $Form = undef;
});
}
In this way you can create site wide application objects and simple
aliases for common functions.
$Session Object
The $Session object keeps track of user and web client state, in a
persistent manner, making it relatively easy to develop web
applications. The $Session state is stored across HTTP connections, in
database files in the Global or StateDir directories, and will persist
across web server restarts.
The user session is referenced by a 128 bit / 32 byte MD5 hex hashed
cookie, and can be considered secure from session id guessing, or
session hijacking. When a hacker fails to guess a session, the system
times out for a second, and with 2**128 (3.4e38) keys to guess, a hacker
will not be guessing an id any time soon.
If an incoming cookie matches a timed out or non-existent session, a new
session is created with the incoming id. If the id matches a currently
active session, the session is tied to it and returned. This is also
similar to the Microsoft ASP implementation.
The $Session reference is a hash ref, and can be used as such to store
data as in:
$Session->{count}++; # increment count by one
%{$Session} = (); # clear $Session data
The $Session object state is implemented through MLDBM, and a user
should be aware of the limitations of MLDBM. Basically, you can read
complex structures, but not write them, directly:
$data = $Session->{complex}{data}; # Read ok.
$Session->{complex}{data} = $data; # Write NOT ok.
$Session->{complex} = {data => $data}; # Write ok, all at once.
Please see MLDBM for more information on this topic. $Session can also
be used for the following methods and properties:
$Session->{CodePage}
Not implemented. May never be until someone needs it.
$Session->{LCID}
Not implemented. May never be until someone needs it.
$Session->{SessionID}
SessionID property, returns the id for the current session, which is
exchanged between the client and the server as a cookie.
$Session->{Timeout} [= $minutes]
Timeout property, if minutes is being assigned, sets this default
timeout for the user session, else returns the current session
timeout.
If a user session is inactive for the full timeout, the session is
destroyed by the system. No one can access the session after it
times out, and the system garbage collects it eventually.
$Session->Abandon()
The abandon method times out the session immediately. All Session
data is cleared in the process, just as when any session times out.
$Session->Lock()
API extension. If you are about to use $Session for many consecutive
reads or writes, you can improve performance by explicitly locking
$Session, and then unlocking, like:
$Session->Lock();
$Session->{count}++;
$Session->{count}++;
$Session->{count}++;
$Session->UnLock();
This sequence causes $Session to be locked and unlocked only 1 time,
instead of the 6 times that it would be locked otherwise, 2 for each
increment with one to read and one to write.
Because of flushing issues with SDBM_File and DB_File databases,
each lock actually ties fresh to the database, so the performance
savings here can be considerable.
Note that if you have SessionSerialize set, $Session is already
locked for each script invocation automatically, as if you had
called $Session->Lock() in Script_OnStart. Thus you do not need to
worry about $Session locking for performance. Please read the
section on SessionSerialize for more info.
$Session->UnLock()
API Extension. Unlocks the $Session explicitly. If you do not call
this, $Session will be unlocked automatically at the end of the
script.
$Response Object
This object manages the output from the ASP Application and the client
web browser. It does not store state information like the $Session
object but does have a wide array of methods to call.
$Response->{BinaryRef}
API extension. This is a perl reference to the buffered output of
the $Response object, and can be used in the Script_OnFlush
global.asa event to modify the buffered output at runtime to apply
global changes to scripts output without having to modify all the
scripts. These changes take place before content is flushed to the
client web browser.
sub Script_OnFlush {
my $ref = $Response->{BinaryRef};
$$ref =~ s/\s+/ /sg; # to strip extra white space
}
Check out the ./site/eg/global.asa for an example of its use.
$Response->{Buffer}
Default 1, when TRUE sends output from script to client only at the
end of processing the script. When 0, response is not buffered, and
client is sent output as output is generated by the script.
$Response->{CacheControl}
Default "private", when set to public allows proxy servers to cache
the content. This setting controls the value set in the HTTP header
Cache-Control
$Response->{Charset}
This member when set appends itself to the value of the Content-Type
HTTP header. If $Response->{Charset} = 'ISO-LATIN-1' is set, the
corresponding header would look like:
Content-Type: text/html; charset=ISO-LATIN-1
$Response->{Clean} = 0-9;
API extension. Set the Clean level, default 0, on a per script
basis. Clean of 1-9 compresses text/html output. Please see the
Clean config option for more information. This setting may also be
useful even if using compression to obfuscate HTML.
$Response->{ContentType} = "text/html"
Sets the MIME type for the current response being sent to the
client. Sent as an HTTP header.
$Response->{Debug} = 1|0
API extension. Default set to value of Debug config. May be used to
temporarily activate or inactivate $Response->Debug() behavior.
Something like:
{
local $Response->{Debug} = 1;
$Response->Debug($values);
}
maybe be used to always log something. The Debug() method can be
better than AppendToLog() because it will log data in data
structures one level deep, whereas AppendToLog prints just raw
string/scalar values.
$Response->{Expires} = $time
Sends a response header to the client indicating the $time in
SECONDS in which the document should expire. A time of 0 means
immediate expiration. The header generated is a standard HTTP date
like: "Wed, 09 Feb 1994 22:23:32 GMT".
$Response->{ExpiresAbsolute} = $date
Sends a response header to the client with $date being an absolute
time to expire. Formats accepted are all those accepted by
HTTP::Date::str2time(), e.g.
"Wed, 09 Feb 1994 22:23:32 GMT" -- HTTP format
"Tuesday, 08-Feb-94 14:15:29 GMT" -- old rfc850 HTTP format
"08-Feb-94" -- old rfc850 HTTP format
"09 Feb 1994" -- proposed new HTTP format
"Feb 3 1994" -- Unix 'ls -l' format
"Feb 3 17:03" -- Unix 'ls -l' format
$Response->{FormFill} = 0|1
If true, HTML forms generated by the script output will be auto
filled with data from $Request->Form. This feature requires
HTML::FillInForm to be installed. Please see the FormFill CONFIG for
more information.
This setting overrides the FormFill config at runtime for the script
execution only.
$Response->{IsClientConnected}
1 if web client is connected, 0 if not. This value starts set to 1,
and will be updated whenever a $Response->Flush() is called. If
BufferingOn is set, by default $Response->Flush() will only be
called at the end of the HTML output.
As of version 2.23 this value is updated correctly before global.asa
Script_OnStart is called, so global script termination may be
correctly handled during that event, which one might want to do with
excessive user STOP/RELOADS when the web server is very busy.
An API extension $Response->IsClientConnected may be called for
refreshed connection status without calling first a $Response->Flush
$Response->{PICS}
If this property has been set, a PICS-Label HTTP header will be sent
with its value. For those that do not know, PICS is a header that is
useful in rating the internet. It stands for Platform for Internet
Content Selection, and you can find more info about it at:
http://www.w3.org
$Response->{Status} = $status
Sets the status code returned by the server. Can be used to set
messages like 500, internal server error
$Response->AddHeader($name, $value)
Adds a custom header to a web page. Headers are sent only before any
text from the main page is sent, so if you want to set a header
after some text on a page, you must turn BufferingOn.
$Response->AppendToLog($message)
Adds $message to the server log. Useful for debugging.
$Response->BinaryWrite($data)
Writes binary data to the client. The only difference from
$Response->Write() is that $Response->Flush() is called internally
first, so the data cannot be parsed as an html header. Flushing
flushes the header if has not already been written.
If you have set the $Response->{ContentType} to something other than
text/html, cgi header parsing (see CGI notes), will be automatically
be turned off, so you will not necessarily need to use BinaryWrite
for writing binary data.
For an example of BinaryWrite, see the binary_write.htm example in
./site/eg/binary_write.htm
Please note that if you are on Win32, you will need to call binmode
on a file handle before reading, if its data is binary.
$Response->Clear()
Erases buffered ASP output.
$Response->Cookies($name, [$key,] $value)
Sets the key or attribute of cookie with name $name to the value
$value. If $key is not defined, the Value of the cookie is set. ASP
CookiePath is assumed to be / in these examples.
$Response->Cookies('name', 'value');
--> Set-Cookie: name=value; path=/
$Response->Cookies("Test", "data1", "test value");
$Response->Cookies("Test", "data2", "more test");
$Response->Cookies(
"Test", "Expires",
&HTTP::Date::time2str(time+86400)
);
$Response->Cookies("Test", "Secure", 1);
$Response->Cookies("Test", "Path", "/");
$Response->Cookies("Test", "Domain", "host.com");
--> Set-Cookie:Test=data1=test%20value&data2=more%20test; \
expires=Fri, 23 Apr 1999 07:19:52 GMT; \
path=/; domain=host.com; secure
The latter use of $key in the cookies not only sets cookie
attributes such as Expires, but also treats the cookie as a hash of
key value pairs which can later be accesses by
$Request->Cookies('Test', 'data1');
$Request->Cookies('Test', 'data2');
Because this is perl, you can (NOT PORTABLE) reference the cookies
directly through hash notation. The same 5 commands above could be
compressed to:
$Response->{Cookies}{Test} =
{
Secure => 1,
Value =>
{
data1 => 'test value',
data2 => 'more test'
},
Expires => 86400, # not portable, see above
Domain => 'host.com',
Path => '/'
};
and the first command would be:
# you don't need to use hash notation when you are only setting
# a simple value
$Response->{Cookies}{'Test Name'} = 'Test Value';
I prefer the hash notation for cookies, as this looks nice, and is
quite perlish. It is here to stay. The Cookie() routine is very
complex and does its best to allow access to the underlying hash
structure of the data. This is the best emulation I could write
trying to match the Collections functionality of cookies in IIS ASP.
For more information on Cookies, please go to the source at
http://home.netscape.com/newsref/std/cookie_spec.html
$Response->Debug(@args)
API Extension. If the Debug config option is set greater than 0,
this routine will write @args out to server error log. refs in @args
will be expanded one level deep, so data in simple data structures
like one-level hash refs and array refs will be displayed. CODE refs
like
$Response->Debug(sub { "some value" });
will be executed and their output added to the debug output. This
extension allows the user to tie directly into the debugging
capabilities of this module.
While developing an app on a production server, it is often useful
to have a separate error log for the application to catch debugging
output separately. One way of implementing this is to use the Apache
ErrorLog configuration directive to create a separate error log for
a virtual host.
If you want further debugging support, like stack traces in your
code, consider doing things like:
$Response->Debug( sub { Carp::longmess('debug trace') };
$SIG{__WARN__} = \&Carp::cluck; # then warn() will stack trace
The only way at present to see exactly where in your script an error
occurred is to set the Debug config directive to 2, and match the
error line number to perl script generated from your ASP script.
However, as of version 0.10, the perl script generated from the asp
script should match almost exactly line by line, except in cases of
inlined includes, which add to the text of the original script, pod
comments which are entirely yanked out, and <% # comment %> style
comments which have a \n added to them so they still work.
If you would like to see the HTML preceding an error while
developing, consider setting the BufferingOn config directive to 0.
$Response->End()
Sends result to client, and immediately exits script. Automatically
called at end of script, if not already called.
$Response->ErrorDocument($code, $uri)
API extension that allows for the modification the Apache
ErrorDocument at runtime. $uri may be a on site document, off site
URL, or string containing the error message.
This extension is useful if you want to have scripts set error codes
with $Response->{Status} like 401 for authentication failure, and to
then control from the script what the error message looks like.
For more information on the Apache ErrorDocument mechanism, please
see ErrorDocument in the CORE Apache settings, and the
Apache->custom_response() API, for which this method is a wrapper.
$Response->Flush()
Sends buffered output to client and clears buffer.
$Response->Include($filename, @args)
This API extension calls the routine compiled from asp script in
$filename with the args @args. This is a direct translation of the
SSI tag
Please see the SSI section for more on SSI in general.
This API extension was created to allow greater modularization of
code by allowing includes to be called with runtime arguments. Files
included are compiled once, and the anonymous code ref from that
compilation is cached, thus including a file in this manner is just
like calling a perl subroutine. The @args can be found in @_ in the
includes like:
# include.inc
<% my @args = @_; %>
As of 2.23, multiple return values can be returned from an include
like:
my @rv = $Response->Include($filename, @args);
$Response->Include(\%cache_args, @sub_args) *CACHE API*
As of version 2.23, output from an include may be cached with this
API and the CONFIG settings CacheDir & CacheDB. This can be used to
execute expensive includes only rarely where applicable, drastically
increasing performance in some cases.
This API extension applies to the entire include family:
my @rv = $Response->Include(\%cache_args, @include_args)
my $html_ref = $Response->TrapInclude(\%cache_args, @include_args)
$Server->Execute(\%cache_args, @include_args)
For this output cache to work, you must load Apache::ASP in the
Apache parent httpd like so:
# httpd.conf
PerlModule Apache::ASP
The cache arguments are shown here
$Response->Include({
File => 'file.inc',
Cache => 1, # to activate cache layer
Expires => 3600, # to expire in one hour
LastModified => time() - 600, # to expire if cached before 10 minutes ago
Key => $Request->Form, # to cache based on checksum of serialized form data,
Clear => 1, # always executes include & cache output
}, @include_args);
File - include file to execute, can be file name or \$script
script data passed in as a string reference.
Cache - activate caching, will run like normal include without this
Expires - only cache for this long in seconds
LastModified - if cached before this time(), expire
Key - The cache item identity. Can be $data, \$data, \%data, \@data,
this data is serialized and combined with the filename & @include_args
to create a MD5 checksum to fetch from the cache with. If you wanted
to cache the results of a search page from form data POSTed,
then this key could be
{ Key => $Request->Form }
Clear - If set to 1, or boolean true, will always execute the include
and update the cache entry for it.
Motivation: If an include takes 1 second to execute because of
complex SQL to a database, and you can cache the output of this
include because it is not realtime data, and the cache layer runs at
.01 seconds, then you have a 100 fold savings on that part of the
script. Site scalability can be dramatically increased in this way
by intelligently caching bottlenecks in the web application.
Use Sparingly: If you have a fast include, then it may execute
faster than the cache layer runs, in which case you may actually
slow your site down by using this feature. Therefore try to use this
sparingly, and only when sure you really need it. Apache::ASP
scripts generally execute very quickly, so most developers will not
need to use this feature at all.
$Response->Include(\$script_text, @args)
Added in Apache::ASP 2.11, this method allows for executing ASP
scripts that are generated dynamically by passing in a reference to
the script data instead of the file name. This works just like the
normal $Response->Include() API, except a string reference is passed
in instead of a filename. For example:
<%
my $script = "<\% print 'TEST'; %\>";
$Response->Include(\$script);
%>
This include would output TEST. Note that tokens like <% and %> must
be escaped so Apache::ASP does not try to compile those code blocks
directly when compiling the original script. If the $script data
were fetched directly from some external resource like a database,
then these tokens would not need to be escaped at all as in:
<%
my $script = $dbh->selectrow_array(
"select script_text from scripts where script_id = ?",
undef, $script_id
);
$Response->Include(\$script);
%>
This method could also be used to render other types of dynamic
scripts, like XML docs using XMLSubs for example, though for complex
runtime XML rendering, one should use something better suited like
XSLT. See the $Server->XSLT API for more on this topic.
$Response->IsClientConnected()
API Extension. 1 for web client still connected, 0 if disconnected
which might happen if the user hits the stop button. The original
API for this $Response->{IsClientConnected} is only updated after a
$Response->Flush is called, so this method may be called for a
refreshed status.
Note $Response->Flush calls $Response->IsClientConnected to update
$Response->{IsClientConnected} so to use this you are going straight
to the source! But if you are doing a loop like:
while(@data) {
$Response->End if ! $Response->{IsClientConnected};
my $row = shift @data;
%> <%= $row %> <%
$Response->Flush;
}
Then its more efficient to use the member instead of the method
since $Response->Flush() has already updated that value for you.
$Response->Redirect($url)
Sends the client a command to go to a different url $url. Script
immediately ends.
$Response->TrapInclude($file, @args)
Calls $Response->Include() with same arguments as passed to it, but
instead traps the include output buffer and returns it as as a perl
string reference. This allows one to postprocess the output buffer
before sending to the client.
my $string_ref = $Response->TrapInclude('file.inc');
$$string_ref =~ s/\s+/ /sg; # squash whitespace like Clean 1
print $$string_ref;
The data is returned as a referenece to save on what might be a
large string copy. You may dereference the data with the
$$string_ref notation.
$Response->Write($data)
Write output to the HTML page. <%=$data%> syntax is shorthand for a
$Response->Write($data). All final output to the client must at some
point go through this method.
$Request Object
The request object manages the input from the client browser, like
posts, query strings, cookies, etc. Normal return results are values if
an index is specified, or a collection / perl hash ref if no index is
specified. WARNING, the latter property is not supported in ActiveState
PerlScript, so if you use the hashes returned by such a technique, it
will not be portable.
A normal use of this feature would be to iterate through the form
variables in the form hash...
$form = $Request->Form();
for(keys %{$form}) {
$Response->Write("$_: $form->{$_}
\n");
}
Please see the ./site/eg/server_variables.htm asp file for this method
in action.
Note that if a form POST or query string contains duplicate values for a
key, those values will be returned through normal use of the $Request
object:
@values = $Request->Form('key');
but you can also access the internal storage, which is an array
reference like so:
$array_ref = $Request->{Form}{'key'};
@values = @{$array_ref};
Please read the PERLSCRIPT section for more information on how things
like $Request->QueryString() & $Request->Form() behave as collections.
$Request->{Method}
API extension. Returns the client HTTP request method, as in GET or
POST. Added in version 2.31.
$Request->{TotalBytes}
The amount of data sent by the client in the body of the request,
usually the length of the form data. This is the same value as
$Request->ServerVariables('CONTENT_LENGTH')
$Request->BinaryRead($length)
Returns a string whose contents are the first $length bytes of the
form data, or body, sent by the client request. This data is the raw
data sent by the client, without any parsing done on it by
Apache::ASP.
Note that BinaryRead will not return any data for file uploads.
Please see the $Request->FileUpload() interface for access to this
data. $Request->Form() data will also be available as normal.
$Request->ClientCertificate()
Not implemented.
$Request->Cookies($name [,$key])
Returns the value of the Cookie with name $name. If a $key is
specified, then a lookup will be done on the cookie as if it were a
query string. So, a cookie set by:
Set-Cookie: test=data1=1&data2=2
would have a value of 2 returned by
$Request->Cookies('test','data2').
If no name is specified, a hash will be returned of cookie names as
keys and cookie values as values. If the cookie value is a query
string, it will automatically be parsed, and the value will be a
hash reference to these values.
When in doubt, try it out. Remember that unless you set the Expires
attribute of a cookie with $Response->Cookies('cookie', 'Expires',
$xyz), the cookies that you set will only last until you close your
browser, so you may find your self opening & closing your browser a
lot when debugging cookies.
For more information on cookies in ASP, please read
$Response->Cookies()
$Request->FileUpload($form_field, $key)
API extension. The FileUpload interface to file upload data is
stabilized. The internal representation of the file uploads is a
hash of hashes, one hash per file upload found in the
$Request->Form() collection. This collection of collections may be
queried through the normal interface like so:
$Request->FileUpload('upload_file', 'ContentType');
$Request->FileUpload('upload_file', 'FileHandle');
$Request->FileUpload('upload_file', 'BrowserFile');
$Request->FileUpload('upload_file', 'Mime-Header');
$Request->FileUpload('upload_file', 'TempFile');
* note that TempFile must be use with the UploadTempFile
configuration setting.
The above represents the old slow collection interface, but like all
collections in Apache::ASP, you can reference the internal hash
representation more easily.
my $fileup = $Request->{FileUpload}{upload_file};
$fileup->{ContentType};
$fileup->{BrowserFile};
$fileup->{FileHandle};
$fileup->{Mime-Header};
$fileup->{TempFile};
$Request->Form($name)
Returns the value of the input of name $name used in a form with
POST method. If $name is not specified, returns a ref to a hash of
all the form data. One can use this hash to create a nice alias to
the form data like:
# in global.asa
use vars qw( $Form );
sub Script_OnStart {
$Form = $Request->Form;
}
# then in ASP scripts
<%= $Form->{var} %>
File upload data will be loaded into $Request->Form('file_field'),
where the value is the actual file name of the file uploaded, and
the contents of the file can be found by reading from the file name
as a file handle as in:
while(read($Request->Form('file_field_name'), $data, 1024)) {};
For more information, please see the CGI / File Upload section, as
file uploads are implemented via the CGI.pm module. An example can
be found in the installation samples ./site/eg/file_upload.asp
$Request->Params($name)
API extension. If RequestParams CONFIG is set, the $Request->Params
object is created with combined contents of $Request->QueryString
and $Request->Form. This is for developer convenience simlar to
CGI.pm's param() method. Just like for $Response->Form, one could
create a nice alias like:
# in global.asa
use vars qw( $Params );
sub Script_OnStart {
$Params = $Request->Params;
}
$Request->QueryString($name)
Returns the value of the input of name $name used in a form with GET
method, or passed by appending a query string to the end of a url as
in http://localhost/?data=value. If $name is not specified, returns
a ref to a hash of all the query string data.
$Request->ServerVariables($name)
Returns the value of the server variable / environment variable with
name $name. If $name is not specified, returns a ref to a hash of
all the server / environment variables data. The following would be
a common use of this method:
$env = $Request->ServerVariables();
# %{$env} here would be equivalent to the cgi %ENV in perl.
$Application Object
Like the $Session object, you may use the $Application object to store
data across the entire life of the application. Every page in the ASP
application always has access to this object. So if you wanted to keep
track of how many visitors there where to the application during its
lifetime, you might have a line like this:
$Application->{num_users}++
The Lock and Unlock methods are used to prevent simultaneous access to
the $Application object.
$Application->Lock()
Locks the Application object for the life of the script, or until
UnLock() unlocks it, whichever comes first. When $Application is
locked, this guarantees that data being read and written to it will
not suddenly change on you between the reads and the writes.
This and the $Session object both lock automatically upon every read
and every write to ensure data integrity. This lock is useful for
concurrent access control purposes.
Be careful to not be too liberal with this, as you can quickly
create application bottlenecks with its improper use.
$Application->UnLock()
Unlocks the $Application object. If already unlocked, does nothing.
$Application->GetSession($sess_id)
This NON-PORTABLE API extension returns a user $Session given a
session id. This allows one to easily write a session manager if
session ids are stored in $Application during Session_OnStart, with
full access to these sessions for administrative purposes.
Be careful not to expose full session ids over the net, as they
could be used by a hacker to impersonate another user. So when
creating a session manager, for example, you could create some other
id to reference the SessionID internally, which would allow you to
control the sessions. This kind of application would best be served
under a secure web server.
The ./site/eg/global_asa_demo.asp script makes use of this routine
to display all the data in current user sessions.
$Application->SessionCount()
This NON-PORTABLE method returns the current number of active
sessions, in the application. This method is not implemented as part
of the ASP object model, but is implemented here because it is
useful. In particular, when accessing databases with license
requirements, one can monitor usage effectively through accessing
this value.
This is a new feature as of v.06, and if run on a site with previous
versions of Apache::ASP, the count may take a while to synch up. To
ensure a correct count, you must delete all the current state files
associated with an application, usually in the $Global/.state
directory.
$Server Object
The server object is that object that handles everything the other
objects do not. The best part of the server object for Win32 users is
the CreateObject method which allows developers to create instances of
ActiveX components, like the ADO component.
$Server->{ScriptTimeout} = $seconds
Not implemented. May never be. Please see the Apache Timeout
configuration option, normally in httpd.conf.
$Server->Config($setting)
API extension. Allows a developer to read the CONFIG settings, like
Global, GlobalPackage, StateDir, etc. Currently implemented as a
wrapper around
Apache->dir_config($setting)
May also be invoked as $Server->Config(), which will return a hash
ref of all the PerlSetVar settings.
$Server->CreateObject($program_id)
Allows use of ActiveX objects on Win32. This routine returns a
reference to an Win32::OLE object upon success, and nothing upon
failure. It is through this mechanism that a developer can utilize
ADO. The equivalent syntax in VBScript is
Set object = Server.CreateObject(program_id)
For further information, try 'perldoc Win32::OLE' from your favorite
command line.
$Server->Execute($file, @args)
New method from ASP 3.0, this does the same thing as
$Response->Include($file, @args)
and internally is just a wrapper for such. Seems like we had this
important functionality before the IIS/ASP camp!
$Server->File()
Returns the absolute file path to current executing script. Same as
Apache->request->filename when running under mod_perl.
ASP API extension.
$Server->GetLastError()
Not implemented, will likely not ever be because this is dependent
on how IIS handles errors and is not relevant in Apache.
$Server->HTMLEncode( $string || \$string )
Returns an HTML escapes version of $string. &, ", >, <, are each
escapes with their HTML equivalents. Strings encoded in this nature
should be raw text displayed to an end user, as HTML tags become
escaped with this method.
As of version 2.23, $Server->HTMLEncode() may take a string
reference for an optmization when encoding a large buffer as an API
extension. Here is how one might use one over the other:
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.
$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.
$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.
$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 });
$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.
$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.
This new script will take over current execution and the current
script will not continue to be executed afterwards. It differs from
Execute() because the original script will not pick up where it left
off.
As of Apache::ASP 2.31, this method now accepts optional arguments
like $Response->Include & $Server->Execute. $Server->Transfer is now
just a wrapper for:
$Response->Include($file, @args);
$Response->End;
$Server->URLEncode($string)
Returns the URL-escaped version of the string $string. +'s are
substituted in for spaces and special characters are escaped to the
ascii equivalents. Strings encoded in this manner are safe to put in
urls... they are especially useful for encoding data used in a query
string as in:
$data = $Server->URLEncode("test data");
$url = "http://localhost?data=$data";
$url evaluates to http://localhost?data=test+data, and is a
valid URL for use in anchor tags and redirects, etc.
$Server->URL($url, \%params)
Will return a URL with %params serialized into a query string like:
$url = $Server->URL('test.asp', { test => value });
which would give you a URL of test.asp?test=value
Used in conjunction with the SessionQuery* settings, the returned
URL will also have the session id inserted into the query string,
making this a critical part of that method of implementing
cookieless sessions. For more information on that topic please read
on the setting in the CONFIG section, and the SESSIONS section too.
$Server->XSLT(\$xsl_data, \$xml_data)
* NON-PORTABLE API EXTENSION *
This method takes string references for XSL and XML data and returns
the XSLT output as a string reference like:
my $xslt_data_ref = $Server->XSLT(\$xsl_data, \$xml_data)
print $$xslt_data_ref;
The XSLT parser defaults to XML::XSLT, and is configured with the
XSLTParser setting, which can also use XML::Sablotron ( support
added in 2.11 ), and XML::LibXSLT ( support added in 2.29 ). Please
see the CONFIG section for more information on the XSLT* settings
that drive this API. The XSLT setting itself uses this API
internally to do its rendering.
This API was created to allow developers easy XSLT component
rendering without having to render the entire ASP scripts via XSLT.
This will make an easy plugin architecture for those looking to
integrate XML into their existing ASP application frameworks.
At some point, the API will likely take files as arguments, but not
as of the 2.11 release.
SSI
SSI is great! One of the main features of SSI is to include other files
in the script being requested. In Apache::ASP, this is implemented in a
couple ways, the most crucial of which is implemented in the file
include. Formatted as
,the .inc being merely a convention, text from the included file will be
inserted directly into the script being executed and the script will be
compiled as a whole. Whenever the script or any of its includes change,
the script will be recompiled.
Includes go a great length to promote good decomposition and code
sharing in ASP scripts, but they are still fairly static. As of version
.09, includes may have dynamic runtime execution, as subroutines
compiled into the global.asa namespace. The first way to invoke includes
dynamically is
If @args is specified, Apache::ASP knows to execute the include at
runtime instead of inlining it directly into the compiled code of the
script. It does this by compiling the script at runtime as a subroutine,
and caching it for future invocations. Then the compiled subroutine is
executed and has @args passed into its as arguments.
This is still might be too static for some, as @args is still hardcoded
into the ASP script, so finally, one may execute an include at runtime
by utilizing this API extension
$Response->Include("filename.inc", @args);
which is a direct translation of the dynamic include above.
Although inline includes should be a little faster, runtime dynamic
includes represent great potential savings in httpd memory, as includes
are shared between scripts keeping the size of each script to a minimum.
This can often be significant saving if much of the formatting occurs in
an included header of a www page.
By default, all includes will be inlined unless called with an args
parameter. However, if you want all your includes to be compiled as subs
and dynamically executed at runtime, turn the DynamicIncludes config
option on as documented above.
That is not all! SSI is full featured. One of the things missing above
is the
tag. This and many other SSI code extensions are available by filtering
Apache::ASP output through Apache::SSI via the Apache::Filter and the
Filter config options. For more information on how to wire Apache::ASP
and Apache::SSI together, please see the Filter config option documented
above. Also please see Apache::SSI for further information on the
capabilities it offers.
EXAMPLES
Use with Apache. Copy the ./site/eg directory from the ASP installation
to your Apache document tree and try it out! You have to put
"AllowOverride All" in your config section to let the
.htaccess file in the ./site/eg installation directory do its work.
IMPORTANT (FAQ): Make sure that the web server has write access to that
directory. Usually a
chmod -R 0777 eg
will do the trick :)
SESSIONS
Cookies are used by default for user $Session support ( see OBJECTS ).
In order to track a web user and associate server side data with that
client, the web server sets, and the web client returns a 32 byte
session id identifier cookie. This implementation is very secure and may
be used in secure HTTPS transactions, and made stronger with
SecureSession and ParanoidSession settings (see CONFIG ).
However good cookies are for this kind of persistent state management
between HTTP requests, they have long been under fire for security risks
associated with JavaScript security exploits and privacy abuse by large
data tracking companies.
Because of these reasons, web users will sometimes turn off their
cookies, rendering normal ASP session implementations powerless,
resulting in a new $Session generated every request. This is not good
for ASP style sessions.
Cookieless Sessions
*** See WARNING Below ***
So we now have more ways to track sessions with the SessionQuery* CONFIG
settings, that allow a web developer to embed the session id in URL
query strings when use of cookies is denied. The implementations work
such that if a user has cookies turned on, then cookies will be used,
but for those users with cookies turned off, the session ids will be
parsed into document URLs.
The first and easiest method that a web developer may use to implement
cookieless sessions are with SessionQueryParse* 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'));
%>
Redirecting you offsite to
>here...
Because the web browser visits a real page before being redirected with
the 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.
XML/XSLT
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:
Jane Doe has been here since 1998.
To render it with a custom tag, you would tell the Apache::ASP parser to
render the tag with a subroutine:
PerlSetVar XMLSubsMatch my: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.
Then you would create the my::employee subroutine in the my perl package
or whereever like so
sub my::employee {
my($attributes, $body) = @_;
$main::Response->Include('employee.inc', $attributes, $body);
}
<% my($attributes, $body) = @_; %>
<% for('name', 'last', 'phone') { %>
| <%=ucfirst $_ %>: |
<%= $attributes->{$_} %> |
<% } %>
| <%= $body %> |
The $main::Response->Include() would then delegate the rendering of the
employee to the 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
...
and just
These tags are very powerful in that they can also enclose normal ASP
logic, like:
<% my $birthday = &HTTP::Date::time2str(time - 25 * 86400 * 365); %>
This employee has been online for <%= int(rand()*600)+1 %>
seconds, and was born near <%= $birthday %>.
For an example of this custom XML tagging in action, please check out
the ./site/eg/xml_subs.asp script. Note the one limitation that
currently exists is that tags of the same name may not be used in each
other, but otherwise customs tags may be used in other custom tags.
XSLT Tranformations
XML is good stuff, but what can you use it for? The principle is that by
having data and style separated in XML and XSL files, you can reformat
your data more easily in the future, and you can render your data in
multiple formats, just as easily as for your web site, so you might
render your site to a PDA, or a cell phone just as easily as to a
browser, and all you have to do is set up the right XSL stylesheets to
do the transformation (XSLT).
With native XML/XSLT support, Apache::ASP scripts may be the source of
XML data that the XSL file transforms, and the XSL file itself will be
first executed as an ASP script also. The XSLT transformation is handled
by XML::XSLT or XML::Sablotron and you can see an example of it in
action at the ./site/eg/xslt.xml XML script.
To specify a XSL stylesheet, use the setting:
PerlSetVar XSLT template.xsl
where template.xsl could be any file. By default this will XSLT
transform all ASP scripts so configured, but you can separate xml
scripts from the rest with the setting:
PerlSetVar XSLTMatch xml$
where all files with the ending xml would undergo a XSLT transformation.
Note that XSLT depends on the installation of XML::XSLT, which in turn
depends on XML::DOM, and XML::Parser. As of version 2.11, XML::Sablotron
may also be used by setting:
PerlSetVar XSLTParser XML::Sablotron
and XML::LibXSLT may be used, as of 2.29, by setting
PerlSetVar XSLTParser XML::LibXSLT
If you would like to install XML::Sablotron or XML::LibXSLT, you will
first have to install the libraries that these perl modules use, which
you can get at:
libxslt - The XSLT C Library for Gnome
http://xmlsoft.org/XSLT/
Sablotron - Ginger Alliance
http://www.gingerall.com
For more on XML::XSLT, the default XSLT engine that Apache::ASP will
use, please see:
XML::XSLT
http://xmlxslt.sourceforge.net/
XML:XSLT was the first supported XSLT engine as has the benefit of being
written in pure perl so that though while it is slower than the other
solutions, it is easier to port.
If you would like to cache XSLT tranformations, which is highly
recommended, just set:
PerlSetVar XSLTCache 1
Please see the Cache settings in the CONFIG section for more about how
to configure the XSLTCache.
References
For more information about XSLT, please see the standard at:
http://www.w3.org/TR/xslt
For their huge ground breaking XML efforts, these other XML OSS projects
need mention:
Cocoon - XML-based web publishing, in Java
http://xml.apache.org/cocoon/
AxKit - XML web publishing with Apache & mod_perl
http://www.axkit.org/
CGI
CGI has been the standard way of deploying web applications long before
ASP came along. In the CGI gateway world, CGI.pm has been a widely used
module in building CGI applications, and Apache::ASP is compatible with
scripts written with CGI.pm. Also, as of version 2.19, Apache::ASP can
run in standalone CGI mode for the Apache web server without mod_perl
being available. See "Standalone CGI Mode" section below.
Following are some special notes with respect to compatibility with CGI
and CGI.pm. Use of CGI.pm in any of these ways was made possible through
a great amount of work, and is not guaranteed to be portable with other
perl ASP implementations, as other ASP implementations will likely be
more limited.
Standalone CGI Mode, without mod_perl
As of version 2.19, Apache::ASP scripts may be run as standalone CGI
scripts without mod_perl being loaded into Apache. Work to date has
only been done with mod_cgi scripts under Apache on a Unix platform,
and it is unlikely to work under other web servers or Win32
operating systems without further development.
To run the ./site/eg scripts as CGI scripts, you copy the ./site
directory to some location accessible by your web server, in this
example its /usr/local/apache/htdocs/aspcgi, then in your httpd.conf
activate Apache::ASP cgi scripts like so:
Alias /aspcgi/ /usr/local/apache/htdocs/aspcgi/
AddType application/x-httpd-cgi .htm
AddType application/x-httpd-cgi .html
AddType application/x-httpd-cgi .asp
AddType application/x-httpd-cgi .xml
AddType application/x-httpd-cgi .ssi
AllowOverride None
Options +ExecCGI +Indexes
Then install the asp-perl script from the distribution into
/usr/bin, or some other directory. This is so the CGI execution line
at the top of those scripts will invoke the asp-perl wrapper like
so:
#!/usr/bin/perl /usr/bin/asp-perl
The asp-perl script is a cgi wrapper that sets up the Apache::ASP
environment in lieu of the normal mod_perl handler request. Because
there is no Apache->dir_config() data available under mod_cgi, the
asp-perl script will load a asp.conf file that may define a hash
%Config of data for populating the dir_config() data. An example of
a complex asp.conf file is at ./site/eg/asp.conf
So, a trivial asp.conf file might look like:
# asp.conf
%Config = (
'Global' => '.',
'StateDir' => '/tmp/aspstate',
'NoState' => 0,
'Debug' => 3,
);
The default for NoState is 1 in CGI mode, so one must set NoState to
0 for objects like $Session & $Application to be defined.
CGI.pm
CGI.pm is a very useful module that aids developers in the building
of these applications, and Apache::ASP has been made to be
compatible with function calls in CGI.pm. Please see cgi.htm in the
./site/eg directory for a sample ASP script written almost entirely
in CGI.
As of version 0.09, use of CGI.pm for both input and output is
seamless when working under Apache::ASP. Thus if you would like to
port existing cgi scripts over to Apache::ASP, all you need to do is
wrap <% %> around the script to get going. This functionality has
been implemented so that developers may have the best of both worlds
when building their web applications.
Query Object Initialization
You may create a CGI.pm $query object like so:
use CGI;
my $query = new CGI;
As of Apache::ASP version 0.09, form input may be read in by CGI.pm
upon initialization. Before, Apache::ASP would consume the form
input when reading into $Request->Form(), but now form input is
cached, and may be used by CGI.pm input routines.
CGI headers
Not only can you use the CGI.pm $query->header() method to put out
headers, but with the CgiHeaders config option set to true, you can
also print "Header: value\n", and add similar lines to the top of
your script, like:
Some-Header: Value
Some-Other: OtherValue
Script body starts here.
Once there are no longer any cgi style headers, or the there is a
newline, the body of the script begins. So if you just had an asp
script like:
print join(":", %{$Request->QueryString});
You would likely end up with no output, as that line is interpreted
as a header because of the semicolon. When doing basic debugging, as
long as you start the page with you will avoid this problem.
print()ing CGI
CGI is notorious for its print() statements, and the functions in
CGI.pm usually return strings to print(). You can do this under
Apache::ASP, since print just aliases to $Response->Write(). Note
that $| has no affect.
print $query->header();
print $query->start_form();
File Upload
CGI.pm is used for implementing reading the input from file upload.
You may create the file upload form however you wish, and then the
data may be recovered from the file upload by using
$Request->Form(). Data from a file upload gets written to a file
handle, that may in turn be read from. The original file name that
was uploaded is the name of the file handle.
my $filehandle = $Request->Form('file_upload_field_name');
print $filehandle; # will get you the file name
my $data;
while(read($filehandle, $data, 1024)) {
# data from the uploaded file read into $data
};
Please see the docs on CGI.pm (try perldoc CGI) for more information
on this topic, and ./site/eg/file_upload.asp for an example of its
use.
There is a $Request->FileUpload() API extension that you can use to
get more data about a file upload, so that the following properties
are available for querying:
my $file_upload = $Request->{FileUpload}{upload_field};
$file_upload->{BrowserFile}
$file_upload->{FileHandle}
$file_upload->{ContentType}
# only if FileUploadTemp is set
$file_upload->{TempFile}
# whatever mime headers are sent with the file upload
# just "keys %$file_upload" to find out
$file_upload->{?Mime-Header?}
Please see the $Request section in OBJECTS for more information.
PERLSCRIPT
Much work has been done to bring compatibility with ASP applications
written in PerlScript under IIS. Most of that work revolved around
bringing a Win32::OLE Collection interface to many of the objects in
Apache::ASP, which are natively written as perl hashes.
New as of version 2.05 is new functionality enabled with the
CollectionItem setting, to giver better support to more recent
PerlScript syntax. This seems helpful when porting from an
IIS/PerlScript code base. Please see the CONFIG section for more info.
The following objects in Apache::ASP respond as Collections:
$Application
$Session
$Request->FileUpload *
$Request->FileUpload('upload_file') *
$Request->Form
$Request->QueryString
$Request->Cookies
$Response->Cookies
$Response->Cookies('some_cookie')
* FileUpload API Extensions
And as such may be used with the following syntax, as compared with the
Apache::ASP native calls. Please note the native Apache::ASP interface
is compatible with the deprecated PerlScript interface.
C = PerlScript Compatibility N = Native Apache::ASP
## Collection->Contents($name)
[C] $Application->Contents('XYZ')
[N] $Application->{XYZ}
## Collection->SetProperty($property, $name, $value)
[C] $Application->Contents->SetProperty('Item', 'XYZ', "Fred");
[N] $Application->{XYZ} = "Fred"
## Collection->GetProperty($property, $name)
[C] $Application->Contents->GetProperty('Item', 'XYZ')
[N] $Application->{XYZ}
## Collection->Item($name)
[C] print $Request->QueryString->Item('message'), "
\n\n";
[N] print $Request->{QueryString}{'message'}, "
\n\n";
## Working with Cookies
[C] $Response->SetProperty('Cookies', 'Testing', 'Extra');
[C] $Response->SetProperty('Cookies', 'Testing', {'Path' => '/'});
[C] print $Request->Cookies(Testing) . "
\n";
[N] $Response->{Cookies}{Testing} = {Value => Extra, Path => '/'};
[N] print $Request->{Cookies}{Testing} . "
\n";
Several incompatibilities exist between PerlScript and Apache::ASP:
> Collection->{Count} property has not been implemented.
> VBScript dates may not be used for Expires property of cookies.
> Win32::OLE::in may not be used. Use keys() to iterate over.
> The ->{Item} property does not work, use the ->Item() method.
FAQ
The following are some frequently asked questions about Apache::ASP.
Installation
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.
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
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 request to another. This
can be seen in as simple a script as this:
$counter++;
$Response->Write("
Counter: $counter");
The value for $counter++ will remain between requests. Generally use of
globals in this way is a BAD IDEA, and you can spare yourself many
headaches if do "use strict" perl programming which forces you to
explicity declare globals like:
use vars qw($counter);
You can make all your Apache::ASP scripts strict by default by setting:
PerlSetVar UseStrict 1
Apache errors on the PerlHandler directive ?
You do not have mod_perl correctly installed for Apache. The PerlHandler
directive in Apache *.conf files is an extension enabled by mod_perl and
will not work if mod_perl is not correctly installed.
Common user errors are not doing a 'make install' for mod_perl, which
installs the perl side of mod_perl, and not starting the right httpd
after building it. The latter often occurs when you have an old apache
server without mod_perl, and you have built a new one without copying
over to its proper location.
To get mod_perl, go to http://perl.apache.org
Error: no request object (Apache=SCALAR(0x???????):)
Your Apache + mod_perl build is not working properly, and is likely a
RedHat Linux RPM DSO build. Make sure you statically build your Apache +
mod_perl httpd, recompiled fresh from the sources.
I am getting a tie or MLDBM / state error message, what do I do?
Make sure the web server or you have write access to the eg directory,
or to the directory specified as Global in the config you are using.
Default for Global is the directory the script is in (e.g. '.'), but
should be set to some directory not under the www server document root,
for security reasons, on a production site.
Usually a
chmod -R -0777 eg
will take care of the write access issue for initial testing purposes.
Failing write access being the problem, try upgrading your version of
Data::Dumper and MLDBM, which are the modules used to write the state
files.
Sessions
How can I use $Session to store complex data structures.
Very carefully. Please read the $Session documentation in the OBJECTS
section. You can store very complex objects in $Session, but you have to
understand the limits, and the syntax that must be used to make this
happen.
In particular, stay away from statements that that have more than one
level of indirection on the left side of an assignment like:
$Session->{complex}{object} = $data;
How can I keep search engine spiders from killing the session manager?
If you want to dissallow session creation for certain non web browser
user agents, like search engine spiders, you can use an init handler
like:
PerlInitHandler "sub { $_[0]->dir_config('NoState', 1) }"
This will configure your environment before Apache::ASP executes and
sees the configuration settings. You can use the mod_perl API in this
way to configure Apache::ASP at runtime.
Insecure dependency in eval while running with - T switch ?
If you are running your mod_perl with "PerlTaintCheck On", which is
recommended if you are highly concerned about security issues, you may
get errors like "Insecure dependency ... with - T switch".
Apache::ASP automatically untaints data internally so that you may run
scripts with PerlTaintCheck On, but if you are using state objects like
$Session or $Application, you must also notify MLDBM, which Apache::ASP
uses internally, to also untaint data read from disk, with this setting:
$MLDBM::RemoveTaint = 1;
You could put the above line in your global.asa, which is just like a
perl module, outside any event handlers you define there.
How can I use $Session to store a $dbh database handle ?
You cannot use $Session to store a $dbh handle. This can be awkward for
those coming from the IIS/NT world, where you could store just about
anything in $Session, but this boils down to a difference between
threads vs. processes.
Database handles often have per process file handles open, which cannot
be shared between requests, so though you have stored the $dbh data in
$Session, all the other initializations are not relevant in another
httpd process.
All is not lost! Apache::DBI can be used to cache database connections
on a per process basis, and will work for most cases.
Development
How is database connectivity handled?
Database connectivity is handled through perl's DBI & DBD interfaces. In
the UNIX world, it seems most databases have cross platform support in
perl. You can find the book on DBI programming at
http://www.oreilly.com/catalog/perldbi/
DBD::ODBC is often your ticket on Win32. On UNIX, commercial vendors
like OpenLink Software (http://www.openlinksw.com/) provide the nuts and
bolts for ODBC.
Database connections can be cached per process with Apache::DBI.
What is the best way to debug an ASP application ?
There are lots of perl-ish tricks to make your life developing and
debugging an ASP application easier. For starters, you will find some
helpful hints by reading the $Response->Debug() API extension, and the
Debug configuration directive.
How are file uploads handled?
Please see the CGI section. File uploads are implemented through CGI.pm
which is loaded at runtime only for this purpose. This is the only time
that CGI.pm will be loaded by Apache::ASP, which implements all other
cgi-ish functionality natively. The rationale for not implementing file
uploads natively is that the extra 100K in memory for CGI.pm shouldn't
be a big deal if you are working with bulky file uploads.
How do I access the ASP Objects in general?
All the ASP objects can be referenced through the main package with the
following notation:
$main::Response->Write("html output");
This notation can be used from anywhere in perl, including routines
registered with $Server->RegisterCleanup().
You use the normal notation in your scripts, includes, and global.asa:
$Response->Write("html output");
Can I print() in ASP?
Yes. You can print() from anywhere in an ASP script as it aliases to the
$Respon