My journey to Perl, day 1.
Thursday, 19. March 2009, 20:24:41
I've started delving into Perl today. Well, I spent a good share of the day to simply figure out how the heck mod_perl was supposed to work, but after some advice from nicomen, things started rolling, and soon I started digging myself down through the book and, hopefully, the understanding.
My first real WTF about Perl, when using it to improve and dynamicalize web pages, was that I didn't have any way of getting POST and GET (or rather, when the user submits a form with either POST or GET as the method) in the Perl script, as I for instance have in PHP (where I can use the arrays $_POST and $_GET).
Acknowledging this, I found a that I had to read the data from Perl's STDIN, and I found a heavy piece of script that did about this. "Heck, do I have to do this everytime I want some data?", I thought, and started digging through the code.
After fiddling with it at the end of work today, I finally got something working:
What this code does, is basically that it reads the string submitted by the form (which is of the form a=something&b=somethingelse&c=somethingelseagain). It then splits the string on "&" and then stuffs the entries splitted into an array @parts and iterates through the array of elements that looks like a=something and splits each string on "=" and puts it into the hash %_POST. An example of how it would look with my initial string example would be:
One question that might arise: What happens if the string contains "=" or "&" or other special characters? It's quite simple really; when submitting the initial form, everything's uri encoded. For instance, "=" will be shown as "%3D".
I then tried to make another script call my initial Perl module (cuddingly named HTTPerl for a poor pun and no laugh), which didn't prove to be an easy task. HTTPerl.pm, the file name of the module, must, apparently, be in one of the folders of Perl's include folders (@INC). However, getting the current folder added to there was no simple task, and I still do not know how I can do that. Apparently, most that asked on other forums stated "Hah, no, you can't", or failed miserably trying to get it working as a workaround.
In either way, I made a test script for today's work, and it's accessible from http://shael.ath.cx/test.html. Below is the entire script in its "glory". I have not included the test.html file since it is merely a form. NB! There's a bug going on for some reason; half of the time the script won't load, giving an "Server Misconfiguration Error", while the other half it runs perfectly. I am puzzled by this, as the log file says that Perl exited with this error:
[Thu Mar 19 21:01:06 2009] [error] "getPost" is not exported by the HTTPerl module\nCan't continue after import errors at /home/robert/public_html/perl/skript.pl line 2\nBEGIN failed--compilation aborted at /home/robert/public_html/perl/skript.pl line 2.\n
Any ideas to why it is like this? I am empty of ideas.
HTTPerl.pm
Skript.pl
My first real WTF about Perl, when using it to improve and dynamicalize web pages, was that I didn't have any way of getting POST and GET (or rather, when the user submits a form with either POST or GET as the method) in the Perl script, as I for instance have in PHP (where I can use the arrays $_POST and $_GET).
Acknowledging this, I found a that I had to read the data from Perl's STDIN, and I found a heavy piece of script that did about this. "Heck, do I have to do this everytime I want some data?", I thought, and started digging through the code.
After fiddling with it at the end of work today, I finally got something working:
sub getPost
{
my %_POST, $r, @parts;
%_POST = ();
read( STDIN, $r, $ENV{ "CONTENT_LENGTH" } );
@parts = split( /\&/, $r);
foreach my $p (@parts)
{
my($n, $v) = split( /\=/, $p);
$v = uri_decode($v);
$_POST{ "$n" } = $v;
}
return %_POST;
}
What this code does, is basically that it reads the string submitted by the form (which is of the form a=something&b=somethingelse&c=somethingelseagain). It then splits the string on "&" and then stuffs the entries splitted into an array @parts and iterates through the array of elements that looks like a=something and splits each string on "=" and puts it into the hash %_POST. An example of how it would look with my initial string example would be:
$_POST{"a"} = "something"
$_POST{"b"} = "somethingelse"
$_POST{"c"} = "somethingelseagain"
One question that might arise: What happens if the string contains "=" or "&" or other special characters? It's quite simple really; when submitting the initial form, everything's uri encoded. For instance, "=" will be shown as "%3D".
I then tried to make another script call my initial Perl module (cuddingly named HTTPerl for a poor pun and no laugh), which didn't prove to be an easy task. HTTPerl.pm, the file name of the module, must, apparently, be in one of the folders of Perl's include folders (@INC). However, getting the current folder added to there was no simple task, and I still do not know how I can do that. Apparently, most that asked on other forums stated "Hah, no, you can't", or failed miserably trying to get it working as a workaround.
In either way, I made a test script for today's work, and it's accessible from http://shael.ath.cx/test.html. Below is the entire script in its "glory". I have not included the test.html file since it is merely a form. NB! There's a bug going on for some reason; half of the time the script won't load, giving an "Server Misconfiguration Error", while the other half it runs perfectly. I am puzzled by this, as the log file says that Perl exited with this error:
[Thu Mar 19 21:01:06 2009] [error] "getPost" is not exported by the HTTPerl module\nCan't continue after import errors at /home/robert/public_html/perl/skript.pl line 2\nBEGIN failed--compilation aborted at /home/robert/public_html/perl/skript.pl line 2.\n
Any ideas to why it is like this? I am empty of ideas.
HTTPerl.pm
#!/usr/bin/perl
package HTTPerl;
use base 'Exporter';
our sub getPost
{
my %_POST, $r, @parts;
%_POST = ();
read( STDIN, $r, $ENV{ "CONTENT_LENGTH" } );
@parts = split( /\&/, $r);
foreach my $p (@parts)
{
my($n, $v) = split( /\=/, $p);
$v = uri_decode($v);
$_POST{ "$n" } = $v;
}
return %_POST;
}
our @EXPORT_OK = ('getPost');
our @EXPORT = {'getPost');
1;
Skript.pl
#!/usr/bin/perl -I .
use HTTPerl 'getPost';
%_POST = getPost();
print "content-type: text/html\n\n";
print "<html><head><title>Testing the script</title></head>";
print "<style type=\"text/css\">* { font-family: Verdana; font-size: 10px; } h1 { font-size: 16px; }</style>";
print "<body><h1>Using the information</h1>";
printf("<p>Hello %s!<br />You're %d years old and you just said: '%s'.</p>", $_POST{"name"}, $_POST{"age"}, $_POST{"text"});
print "</body></html>";



Anonymous # 20. March 2009, 00:50
Good luck on the perl journey!
Per
Aleksander Aas # 20. March 2009, 09:54
Jess Robinson # 26. March 2009, 21:17
Welcome to the world of Perl!
I'll attempt to answer some of your questions. Though I would also point you at the many perl community sites where you can get lots of good help, for example http://www.perlmonks.org.
Perl as a language wasn't developed solely for use on the web, thus it doesn't have a lot of stuff built-in, like PHP does. It does however come with a suite of libraries for various tasks. One of them is CGI.pm, which you can use to read POST/GET data for you, and yes, even tell which one was done.
Since you're under Apache, you'll be better off using the Apache2 modules, which you should have installed as you're using mod_perl. To get the POST/GET params, write something like:
package MyHandler;
use Apache2::Const
use Apache2::Request;
sub handler {
my $requestrec = shift;
my $request = Apache2::Request->new($requestrec);
print "You did ", $r->method, "\n";
print "Params: ", join(":", $request->params);
return Apache2::Const::OK;
}
Where method will be POST or GET, and params are names of the parameters you passed. see perldoc Apache2::RequestRec and perldoc Apache2::Request.
To add more directorys to your @INC, use the mod_perl directive: PerlSwitches, in your Apache config, eg:
PerlSwitches -I/home/stas/modperl
There's a syntax typo in your HTTPerl.pm: our @EXPORT = ('getPost'); (brackets dont match)
To test if your perl files are syntactically valid, try: perl -cw <filename>
Robert Jacobsen # 27. March 2009, 08:56
Again, thank you for a very enlightening post! I highly appreciate it!
Cosimo Streppone # 31. March 2009, 12:59
And if you're not using mod_perl, just
use CGIinstead of parsing STDIN. That's pre-1995 perl... Just curious, can you tell me where you found that code?Robert Jacobsen # 10. April 2009, 21:12
I found that code as a part of a monster script of doom, extracted it and was like: "HEY! IT ACTUALLY WORKS!", and then started to work on a function to parse POST. I haven't gotten to work much on Perl lately. I have a project in Java coming up and it'll eat a good share of time until the beginning of May. Then, after and between some exam reading, I'll dig into Perl. :-)