By Aaron Weiss, WDVL
“Back in the halcyon days of the
Perl You Need to Know Part 4, we looked at inserting the output
from Perl-based CGI scripts into
pre-fabricated template pages. Ah, good times, good times. Now,
some 11 Perls You Need to Know later, we’re more sophisticated and
urbane, thirsting for shaken martinis and intrigued by the promises
of embedded scripting languages, made popular by Microsoft’s Active Server
Pages (ASP) and the open-source PHP. Why
embedded? Embedded scripting lets you intermingle powerful
programming within HTML documents,
streamlining the process of creating dynamic, template-based pages.
Perl fiends need not be left out in the cold — there are several
options for embedding Perl into HTML, and we’ll look at several
today, ultimately focusing on the Apache::ASP module.”
Why is the raging hot popularity of embedded scripting sweeping
the nation? In the next 30 minutes, we’ll help you understand the
fundamental principles and
how-to know-how that the successfull
scripters already know, and are already using to make
millions of dollars a day! Okay, so
embedded scripting may not be big enough for a late night
informercial yet, but many web developers have been attracted to
the simplicity of the embedded model. The embedding that we’re
talking about is server-side processed, which is different
from embedded scripts such as JavaScript and
VBScript. The latter two are processed client-side, by the
web browser itself. These are convenient but often of limited
power.
Server-side embedded scripts are parsed and processed by the web
server before the page is delivered to the browser. Ultimately, the
browser simply receives an HTML page, without any script inside, as
the script has been replaced by the output of said scripts.
Think of HTML on steroids:
fictional_embedded_document.html
<div class=headline>News of the World, <% insert_date() %><br><p> <% get_headline(1) %> </p></div> etc...
The beauty of the embedded approach is that you can essentially
insert any amount of processing or programming at any given point
in a web page. The result is a visual mental model for building a
web template around the necessary programming components. The
possibilities are endless, such as creating tables within which the
row contents are generated from a script that queries a database, or content
features which are drawn from a database of available articles. Of
course, we could always do this before purely in Perl, but
outputting large amounts of HTML from Perl code can be both a
syntactical hassle and visually messy.
Embedded scripting eases the process of building web templates
around script. But …
The Embedded Disadvantage
We’re not in utopia. Although it is much easier to work with the
HTML in an embedded document, it can be more difficult to work with
the script code. A single HTML document may contain numerous
fragments of embedded script, and these fragments may interact with
each other. While sometimes powerful, this can make for a more
cluttered working environment, especially for debugging, and some
developers dislike scattering their program throughout the
landscape of an HTML document.
Second, many visual HTML editors will trip or choke on documents
which contain embedded scripts. Even advanced editors such as
Dreamweaver 3 require tag and commenting trickery to prevent the
editor from mangling the scripts, which reduces some of the benefit
of being able to work on the HTML template separate from the script
code itself.
Perl is not the first embedded scripting language that often
comes to mind for web developers. Microsoft popularized server-side
embedded scripting with their Active Server Pages, or ASP. Many
developers who prefer not to fall in line with Microsoft have
migrated towards the open-source PHP language, which is a powerful
and very web-oriented language with similarities to Perl, and is
well supported by the dominant Apache web browser. But the fact is
that many developers are also experienced with Perl, and there’s no
reason to learn yet another language when embedded Perl would do
the trick just as well.
Towards that end, there are no less than three embedded Perl
projects that are mature and available:
- Mason is perhaps the most sophisticated and mature embedded
Perl system. Mason’s main strength is the ability to construct
“components” of HTML/Perl which can be reused, as if subroutines or
modules, in many pages. Mason is especially popular for sites whose
entire structure relies on embedded Perl and HTML templates. - Embperl is similar in nature to Mason, with strengths leaning
towards the integration of HTML and Perl, such as output of tables
from database queries and processing of form fields. - Apache::ASP is a “port” of Active Server Pages for Apache and
mod_perl, and uses Perl as the scripting language rather than
Microsoft’s homebrewed scripting language. One of Apache::ASP’s
nice features is its CGI compatibility, which is especially useful
for scripts that have already been developed using the CGI module,
that you wish to use in an embedded environment.
In introducing embedded Perl, we’ll be focusing first on
Apache::ASP. It’s backwards-compatibility with the CGI.pm module
provides a natural stepping stone from the CGI programming we’ve
seen and used in this series.
What attracted me first to Apache::ASP was its ability to use
scripts which were already written with the CGI.pm module. I had a
number of scripts which interacted with forms via CGI, and there
was no good reason to re-write these scripts for a new model of
form interaction. Yet, I wanted to move these scripts into both a
mod_perl environment and, ideally, an embedded environment where an
HTML template could be “wrapped around” the output of the
scripts.
A nice benefit of this embedded model was that we could create a
variety of “results page templates”, each with a different page
design, yet each containing an embedded call to the same processing
script. Apache::ASP seemed to be the only embedded Perl solution
that would let us migrate these scripts into an embedded
environment without modification. How sweet it was.
To begin using Apache::ASP, you must download and install the
module. Doing this does first require that you have already
installed the Apache web server with mod_perl support. The
most recent version of the Apache::ASP module can always be found
at
The module archive contains the very simple installation
instructions. Installation is refreshingly easy.
Apache::ASP is configured via the .htaccess file, which
must reside at the top of the web tree you wish to be ASP-enabled.
For instance, if your Apache document root folder is
/www/htdocs/, then you’ll need to configure Apache::ASP in
/www/htdocs/.htaccess. The module includes a sample
.htaccess configuration file in the site/eg
directory of the installation archive.
The Apache web server, however, will ignore the
.htaccess file unless you enable its use, via the Apache
configuration script at /your/apache/conf/httpd.conf
(depending on where your Apache is installed). Somewhere in
httpd.conf there will be a config section for the web tree
in question, and here you must enable “AllowOverride All”. for
example:
<Directory "/www/htdocs"> Options FollowSymLinks ExecCGI Includes AllowOverride All
Order allow,deny Allow from all
</Directory>
Now, when Apache follows a document in the named directory, it
will heed any configuration directive in the .htaccess
file in that directory.
While developing your scripts, it is a good idea to enable the
StatINC and Debug variables for Apache::ASP,
which means adding the following lines to .htaccess:
PerlSetVar StatINC 1
PerlSetVar Debug 1
The StatINC variable will tell Apache::ASP to reload
any changed pages and scripts on each invocation, rather than rely
on a cached, pre-compiled copy. As you can imagine, this will
reduce performance, but will ease development as you code pages and
scripts, without having to restart the Apache server for every
modification. The Debug variable will output error
messages to the Apache server log. Once the pages are ready to go
live and into production, remember to disable StatINC (set
it to 0), consider disabling debugging to prevent the log from
inflating grossly, and restart the Apache server to affect changes
to .htaccess.
As we crowed about earlier, one of the luxuries of Apache::ASP
is that we can quickly and easily integrate existing CGI-based Perl
scripts into new (or old) HTML templates. How easily? Imagine we
have a Perl script, newnews.cgi, that retrieves the newest
news article from a database of articles. We won’t worry about the
details of this Perl script, except to say that it output only the
article text without surrounding decoration. Now, with Apache::ASP
installed, we want to integrate the newest news article into an
elaborate HTML page, so that the article appears within a specific
portion of the page.
newspage.asp
<HTML>
<HEAD><TITLE>The Newest News of the Day</TITLE></HEAD>
<BODY>
<!-- blah blah blah ... -->
<TABLE WIDTH='80%'>
<TR>
<TD WIDTH='20%'>
<!-- lefthand column of table code -->
</TD>
<TD WIDTH='80%'>
<!-- righthand column of table,
where Perl-generated news article will appear -->
<% do "/www/htdocs/cgi-bin/newnews.cgi" %>
</TD>
</TR>
</TABLE></BODY></HTML>
How easy was that? The opening tag <% denotes the
start of an ASP section. In this ASP section, all we do is call an
external script, whose results will appear in this spot in the web
page. The ASP section is closed with the %> tag. The
ASP module, which handles this page, knows to pass any CGI
parameters into the environment. So, if we wanted to send some
parameters to newnews.cgi, we can simply send those
parameters to newspage.asp, via either the GET or POST
methods. For example, a “GET” form submission that yielded:
newspage.asp?date=071100
Would pass the date parameter into the CGI environment,
and any included scripts, such as newnews.cgi, will
transparently access this CGI parameter through the CGI.pm module.
This is why no changes need be made to the original CGI
script.
HTML and Perl … why can’t they just get along? They can! In
fact, they can get along quite well, and leveraging Apache::ASP to
code Perl directly into your HTML is an exercise in powerful web
design. A segment of Perl code can be wedged anywhere in your HTML
document. Want to simply output the date, in red sans-serif
font?
<DIV STYLE="font-family: arial, helvetica, sans-serif; color: red;"> <% print scalar localtime(time); %> </DIV>
We can even use Perl to modify the construction of HTML tags
themselves. Let’s take a silly but illustrative example: on
Thursdays, we want the background color of the page set to a
steel-grey.
<HTML> <BODY BGCOLOR="<% if ((localtime)[6]==4) { print "#CCCCDD" } else { print "#FFFFFF" }; %>"> etc... </BODY> </HTML>
In setting the BGCOLOR attribute for the
<BODY> tag, we use ASP to embed Perl code. The Perl
seen above simply determines whether the current day is Thursday
(the fourth day of the week), and if so, outputs a steel-grey color
code, otherwise pure white. The upshot is that the output from this
fragment of Perl code will replace the Perl code itself, so that,
on a Thursday, the web browser will ultimately receive the HTML
tag
<BODY BGCOLOR="#CCCCDD">
While we’re keeping the embedded Perl examples short, any amount
of Perl code can appear within the ASP tag, and we can even call
external Perl scripts, as we saw earlier with the do
statement. What’s more impressive, each ASP tag is not an island —
Perl code can span multiple segments of HTML. Scenario: we want to
query a database, and output a table wherein each row contains a
record retrieved from the database.
<HTML> <BODY> <TABLE width='100%' border=2> <TR> <TD><B>FIELD 1</B></TD> <TD><B>FIELD 2</B></TD> </TR> <% use DBI; my $dbh=DBI->connect("dbi:mysql:dbname","dbuser","dbpass"); my $sql="select FIELD1,FIELD2 from BIGTABLE where FIELD2 like 'z%'"; my $sth=$dbh->prepare($sql); $sth->execute || die "Could not execute SQL query: ".$dbh->errstr; while (my @row=$sth->fetchrow_array) { %> <TR> <TD><% = $row[0] %></TD> <TD><% = $row[1] %></TD> </TR> <% } %> </TABLE> </BODY> </HTML>
We’ve liberally sprinkled embedded Perl throughout this page,
with great success. After we build the first row of the table,
containing field labels, we begin an ASP segment. The embedded Perl
opens a connection to a database, and sends an SQL query to this
database, requesting FIELD1 and FIELD2 from all
records where FIELD2 begins with the letter “z”. In the
last code line of this ASP segment, we begin a while loop
which will iterate through each returned record. Notice how we
close the ASP segment right after opening the loop.
With the ASP segment closed, we can insert plain HTML. So, we
begin a table row with the <TR> tag. We then create
the first table column, using <TD></TD> tags.
However, an ASP segment is embedded within this table column. In
this ASP segment, we retrieve the value of the first column in the
returned record, or $row[0]. Actually, there are two
syntaxes we could have used here:
<TD><% = $row[0] %></TD>
or
<TD><% print $row[0]; %></TD>
The “print” syntax is a legitimate Perl statement, and so it
must be terminated with a semicolon. Alternatively, we can use ASP
shorthand to simply retrieve the value of a given variable, as seen
in the first syntax above. No semicolon follows the variable
because this is not a Perl statement, it’s simply telling ASP to
drop the value of this variable in this spot.
We mustn’t forget to close the while loop, and so you
see a final ASP segment which contains only a closing curly brace,
thus completing the while loop. As you can see, the Perl
code is broken up over various ASP segments, with HTML sprinkled
within.
Our last embedded Perl example, where we build a result table
from a database query, illustrates both the pros and cons of
working with embedded Perl. The primary advantage of embedding Perl
is seen as we can elegantly construct a table on-the-fly, allowing
Perl to “pull the strings” of the HTML. The primary disadvantage of
embedded Perl is the discontinuous nature of the code … creating
an ASP segment simply to insert a closing curly brace shows how the
Perl code is fragmented around the page.
Some developers find it difficult to work with scripts that are
broken up in this way, and debugging is certainly a greater
challenge since the Perl is “polluted” with tags. Some
organizations disallow the use of embedded programming because it
confounds their internal division of labor, where HTML authors work
on separate files from Perl programmers.
Having said all that, embedded scripting is gaining in
popularity, so many developers are not put off by these
disadvantages. Embedding is certainly a convenient way to rapidly
prototype pages and rapidly integrate the power of scripting into
the functional aesthetics of HTML templates.