Post Method with Perl CGI Scripts

This is part of a series of articles discussing CGI processing. Part I introduces the basic HTML elements that are used to create a form. Part II discusses how those elements are transferred to the web server and processed by a CGI program. Part III discusses the difference between POST and GET. Finally, Part IV shows how data collected by a CGI program can be stored on the server.

Part III: Post vs Get

Up to this point, I've concentrated on the "GET" method for submitting form data. There is another method called "POST" that also sends data in a similar fashion. The examples in this section will use the following HTML example:
<HTML>
 <BODY>
  <FORM METHOD="post" ACTION="/cgi-bin/script.pl">
   <INPUT TYPE="text" NAME="in" SIZE="20" 
    MAXLENGTH="40" VALUE="hello there">
   <INPUT TYPE="submit" NAME="button" VALUE="Send">
  </FORM>
 </BODY>
</HTML>
Now, when the form data is sent by the web browser, the URL will be unchanged. Instead, the HTTP request received by the web browser from the POST method will look like this:
POST /cgi-bin/script.pl HTTP/1.0
Content-type: application/x-www-form-urlencoded
Content-length: 26

in=hello+there&button=Send

In contrast, the HTTP request for the GET method is simpler:

GET /cgi-bin/script.pl?in=hello+there&button=Send HTTP/1.0

To read the data from the POST method, we won't use the QUERY_STRING environment variable. Instead, the CONTENT_LENGTH variable will tell us the length of the URL-encoded string containing the form data. Here are the steps:

  1. Read $ENV{'CONTENT_LENGTH'} bytes from STDIN (standard input) into a temporary variable called $temp
  2. Split $temp into separate keywords on "&"
  3. Each key-value will be split on "="
  4. Each key and value will be unencoded: each "+" will be changed to a space and %xx codes will be translated back to characters.
Here's a Perl script that does it:
#! /usr/local/bin/perl
# a simple CGI script that demonstrates
# how to unencode form data from a POST method

# this script will spit out only plain text
print "Content-type: text/plain\n\nHere's the form data:\n\n";

# read POST data from STDIN
read STDIN, $temp, $ENV{'CONTENT_LENGTH'};

# separate each keyword
foreach ( split( /&/, $temp ) ) {
    # separate the key and value
    ( $key, $val ) = split( /=/, $_, 2 );

    # translate + to spaces
    $key=~s/\+/ /g;
    $val=~s/\+/ /g;

    # translate %xx codes to characters
    $key=~s/%([0-9a-f]{2})/pack("c",hex($1))/gie;
    $val=~s/%([0-9a-f]{2})/pack("c",hex($1))/gie;

    print "$key = $val\n";
}

You've probably noticed that processing for POST and GET are quite similar. In fact, it's possible to write a single script that will handle both types of input:

#! /usr/local/bin/perl
# CGI script that demonstrates how to unencode 
# form data from both GET and POST methods

# this script will spit out only plain text
print "Content-type: text/plain\n\nHere's the form data:\n\n";

if ($ENV{'CONTENT_LENGTH'} > 0) {
    # read POST data from STDIN
    read STDIN, $temp, $ENV{'CONTENT_LENGTH'};
    # add in the GET data:
    $temp.="&".$ENV{'QUERY_STRING'} if length $ENV{'QUERY_STRING'};
} else {
    # read only the GET data
    $temp=$ENV{'QUERY_STRING'};
}

# separate each keyword
foreach ( split( /&/, $temp ) ) {
    # separate the keys and values
    ( $key, $val ) = split( /=/, $_, 2 );

    # translate + to spaces
    $key=~s/\+/ /g;
    $val=~s/\+/ /g;

    # translate %xx codes to characters
    $key=~s/%([0-9a-f]{2})/pack("c",hex($1))/gie;
    $val=~s/%([0-9a-f]{2})/pack("c",hex($1))/gie;

    print "$key = $val\n";
}
So, when should one method be used instead of the other? Well, the POST method is used to submit data from a form that should be sent in only once, such as signing up for a newsletter or entering address information. The GET method is useful for storing data in the URL so that after submitting the data, someone could bookmark the resulting URL and return to it later, saving all the settings. In fact, it's possible to combine both methods in one form:

<FORM METHOD="post" ACTION="/cgi-bin/script.pl?this=that&one=two">

In this example, this=that and one=two will be passed in the URL like a GET operation (and available in QUERY_STRING on the server), and all the form elements will be sent using POST.

  • 3 Users Found This Useful
Was this answer helpful?

Related Articles

How to install ionCube Loader on Ubuntu

ionCube is a Zend-Engine extension to encode PHP files. To install it on Ubuntu first...

Install Postfix to configure SMTP Server. -- Fedora 16

[root@mail ~]# yum -y install postfix [root@mail ~]# vi /etc/postfix/main.cf #...

Install Dovecot to Configure POP/IMAP Server. -- Fedora 16

[root@mail ~]# yum -y install dovecot [root@mail ~]# vi /etc/dovecot/dovecot.conf # line...

Create SSL Certficates for Mail server - Fedora 16

[root@www ~]# cd /etc/pki/tls/certs [root@www certs]# make server.key umask 77 ; \...

Configure Postfix and Dovecot for SSL - Fedora 16

[1] Create certifcate first. Click here[2] Configure Postfix and Dovecot for SSL [root@www ~]#...