A quick start guide to CGI scripting in Perl

Published: 2022-07-19 - Updated: 2022-07-19

Introduction

Common Gateway Interface (CGI) is a way of calling an external script to generate dynamic content on webpages. The scripts can be written in any language you prefer, but I'll be using Perl because it has easy to use libaries.

Setup

This guide assumes that you already a working NGINX server setup. First you'll have to install fcgiwrap, which will be sitting in between the script and NGINX.

sudo apt-get install fcgiwrap
sudo systemctl enable fcgiwrap
sudo systemctl start fcgiwrap

Now you'll have to add a location block to your current NGINX config. The example below will make the script located /var/www/scripts/test.cgi avaliable on the path /scripts/test.cgi

location /scripts/test.cgi {
    gzip           off;
    include        fastcgi_params;
    fastcgi_pass   unix:/var/run/fcgiwrap.socket;
    fastcgi_param  SCRIPT_FILENAME /var/www/scripts/test.cgi;
}

Scripting

Now that we have path pointing to a script, let's create it. I'll make use of CGI.pm, which is a Perl libary which helps you process and prepare HTTP requests, instead of manually sending the HTTP headers.

sudo apt-get install libcgi-pm-perl

The example below will show the current date and time to the user that visits our path at /scripts/test.cgi. The script has to print a valid HTTP header such as text/html or text/plain, else fcgiwrap will invalidate the scripts response and return a 502 Bad Gateway instead (same will happen if the script fails to compile).

#!/usr/bin/env perl
use strict;
use warnings;

use CGI;
my $cgi = CGI->new();

my $date = localtime();
print $cgi->header('text/plain');
print "The current date and time is $date";

Once your script is done. You'll have to make it executable, which could be done like this

chmod +x /var/www/scripts/test.cgi

And now that we vist our path at /scripts/test.cgi, you'll be able to see the following

The current date and time is Tue Jul 19 13:03:22 2022

Variables

CGI.pm provides you wide a selection of functions which can be used to get specific variables, such as the user's IP. These can be found documented here.

my $REMOTE_IP = $cgi->remote_addr();
print "Your IP is $REMOTE_IP";

Taking input

Let's say you wanna create a form where users can submit their name. Add the action property to the form and set it to the path of your CGI script.

<form action='/scripts/test.cgi'>
    <input name='firstname' type='text'>
    <input name='lastname' type='text'>
    <input type='submit' value="Submit">
</form>

The script will be able to access the input like this. If the user doesn't send any input the function will return an empty string. One thing note is that should never trust the user in submitting valid data.

my $firstname = $cgi->param('firstname');
my $lastname = $cgi->param('lastname')
print "Welcome $firstname $lastname!";

Debugging

Testing and debugging can be quite cruelsome when you have to submit a form in the browser. Therefore CGI.pm has this great feature where you can execute the script along with a query string as a parameter.

> perl test.cgi 'firstname=Bob&lastname=Smith'
Content-Type: text/plain; charset=ISO-8859-1

Welcome Bob Smith!
Questions or comments? contact me!