Text::Templet 2.8 released
Download it here. This release includes two new features for building web application servers.
Download it here. This release includes two new features for building web application servers.
A new version of JavaScript Object Explorer is available here: http://www.denispetrov.com/js/oe.php. The main new feature is the ability to analyze other sites – the page contains a link which you can save as a bookmark in your browser, then select it while displaying the target page. There are also numerous stability improvements, making it a more useful tool overall.
If your web site is hosted on Apache server, you can configure it so that you can use Text::Templet and Perl with the ease of PHP. No more CGI/Perl scripts! The reason PHP is easy to use is that in the simplest case it is just an HTML page. You can create as many as you want, you don’t need to worry about setting permissions, and it’s very easy to debug because you get a meaningful response right in the browser instead of a 500 Server Error and digging error details from server logs.
Apache server has a mechanism that allows you to create custom content handlers – you can make Apache launch a specific program or script when a file with a particular extension is requested, and send its output to the browser. Best of all, this feature can be configured from the .htaccess file, and thus is available at many shared web hosting accounts.
To make this work, we need three things: a content handler script, a folder with template files containing your application, and an .htaccess file in the root of that folder.
Let’s start with the handler code:
#!/usr/bin/perl
use Text::Templet;
eval
{
my $pagetext;
local(*PAGE, $/);
open (PAGE, $ENV{'PATH_TRANSLATED'})Â Â Â Â || die "can't open file $_[0]: $!";
my @fstat = stat(PAGE);
read(PAGE,$pagetext,$fstat[7]); # $fstat[7] is the size of the file
close PAGE;
print "Content-type: text/html\r\n\r\n";
Templet($pagetext);
};
if ( $@ )
{
my $errortext = $@;
print "<body><div>Error:</div><div><pre>$errortext</pre></div><div></body>";
}
The handler is very simple – it loads the requested file passed to it by Apache in PATH_TRANSLATED environment variable, sends a standard HTTP header and passes the contents of the file to Text::Templet for processing. Any errors in the template will be reported through the $@ variable and displayed in the browser.
.htaccess file looks like this:
AddHandler pa-handler .pa Action pa-handler /cgi-bin/pa.pl DirectoryIndex index.pa
The following assumptions are made: the handler code above is saved in /cgi-bin/pa.pl, with executable permission set, and our template files have .pa extension. In addition, index.pa will be called when only directory is requested.
Finally, a simple template to get you started:
<% use vars qw($hello); $hello = "Hello, World!"; '' %> <html> <head> <title>$hello</title> <body> Perl Application says: $hello </body> </html>
I’ve put all these pieces together to make it easy for you to try it out. Download pa.tar.gz or pa.zip, extract pa.pl and Text/Templet.pm from cgi-bin into cgi-bin folder on your web server, then create a new folder somewhere in your html document tree and extract .htaccess and hello.pa into it. Verify that pa.pl has execute permission set and open http://yourserver/folder/hello.pa . Click here to see this example code running on my web host.
You can use this example as a starting point and add features such as authentication and security. You can also put your Perl code in modules and reference them from your templates.
Perl owes much of its power to regular expressions, making programming easier and more intuitive. But this power often comes at a cost – parsing and processing regular expressions is a non-trivial task that uses quite a few CPU cycles.
In some situations it is possible to significantly reduce the amount of time necessary for a particular processing routine by avoiding regular expressions altogether and using other techniques. Consider, for example, a task of extracting file name from a string containing a full path. Presented below are three functions that accomplish this using three different methods, along with their performance analysis.
Function filename1 splits the path into parts using path separator and returns the last part as the file name:
sub filename1
{
my @tok = split /\//,$_[0];
return $tok[-1];
}
The same result can be achieved using a slightly different approach – write a regexp that takes the part between the last path separator and the end of string:
sub filename2
{
$_[0] =~ /\/([^\/]+)$/;
return $1;
}
Both functions are elegant and neat, but when it comes to performance, the following code is the best:
sub filename3
{
return substr($_[0],rindex($_[0],'/')+1);
}
rindex() finds the index of the rightmost separator character in the string and then the file name is extracted using substr().
Here’s how long it takes all three functions to parse ‘/abc/def/geg-geg/page.pl’ 30000 times:
function1: 0.580 seconds
function2: 0.541 seconds
function3: 0.260 seconds
With a longer path ‘/abc/def/geg-geg/page.pl/abc/def/geg-geg/page.pl/ abc/def/geg-geg/page.pl/abc/def/geg-geg/page.pl’ the difference is more dramatic:
function1: 1.191 seconds
function2: 1.101 seconds
function3: 0.271 seconds
These are typical performance figures produced by the Perl profiler (Devel::DProf.) In this particular example, replacing a regular expression with search and substring extraction has reduced execution time by 50 to 75%.