Linux Today: Linux News On Internet Time.
Search Linux Today
Linux News Sections:  Developer -  High Performance -  Infrastructure -  IT Management -  Security -  Storage -
Linux Today Navigation
LT Home
Contribute
Contribute
Link to Us
Linux Jobs


Top White Papers

More on LinuxToday


WDVL: The Perl You Need to Know: Embedded Perl

Jul 23, 2000, 13:13 (0 Talkback[s])
(Other stories by Aaron Weiss)

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.

Related Stories: