CGI Forms   «Prev  Next»

Lesson 5 GET and POST
ObjectiveExplore the differences between GET and POST methods

GET and POST Methods in Perl

The main difference between the GET method and the POST method is the way the data is sent from the browser to the CGI program. The GET method sends data as part of the URL request, so it is limited by the amount of data that can reasonably be sent in the URL. This limit is usually 1,024 characters or so. Additionally, since the GET method data gets passed from the server to the CGI program in an environment variable, the limit on the size of each environment variable may be even tighter. So the GET method is only good for small amounts of data.
The POST method sends data as a separate stream. From the browser to the server, the data travels as the body of the message. From the server to the CGI program, the data is in the standard I/O stream. This allows for data of a more arbitrary length. (Practicality dictates that you still keep it to less than a few K, or it may take a long time to travel over a modem link.) The formtest.cgi program that we have been using for this discussion (see below), uses the GET method. Here is the part that retrieves the form data from the query string:

GET and POST URL

A URL (Uniform Resource Locator) is designed to be a very flexible type of identifier. It has several different parts, which rarely are all used at once. The graphic shows the different parts of a URL.

URL diagram
The "query" part of the URL is the part that's passed to a CGI program when it's called with the GET method. In the example below, everything after the question mark is passed to the CGI program in the QUERY_STRING variable. (I had to add a line break in this example so it would fit on your screen. It would typically be a continuous string):
http://luna/test/test.cgi?name=Fooplah+Klinczaghi&age=Over+
the+hill&listening=on&formis=Mauve&formalso=Plethoric&info=NRP+1-56205-571-2

HTTP GET Perl example

use LWP::UserAgent;
 
my $ua = LWP::UserAgent->new;
my $server_endpoint = "http://192.168.1.1:8000/service";
 
# set custom HTTP request header fields
my $req = HTTP::Request->new(GET => $server_endpoint);
$req->header('content-type' => 'application/json');
$req->header('x-auth-token' => 'kfksj48sdfj4jd9d');
 
my $resp = $ua->request($req);
if ($resp->is_success) {
    my $message = $resp->decoded_content;
    print "Received reply: $message\n";
}
else {
    print "HTTP GET error code: ", $resp->code, "\n";
    print "HTTP GET error message: ", $resp->message, "\n";
}


HTTP POST Perl example

use LWP::UserAgent;
 
my $ua = LWP::UserAgent->new;
 
my $server_endpoint = "http://192.168.1.1:8000/service";
 
# set custom HTTP request header fields
my $req = HTTP::Request->new(POST => $server_endpoint);
$req->header('content-type' => 'application/json');
$req->header('x-auth-token' => 'kfksj48sdfj4jd9d');
 
# add POST data to HTTP request body
my $post_data = '{ "name": "Dan", "address": "NY" }';
$req->content($post_data);
 
my $resp = $ua->request($req);
if ($resp->is_success) {
    my $message = $resp->decoded_content;
    print "Received reply: $message\n";
}
else {
    print "HTTP POST error code: ", $resp->code, "\n";
    print "HTTP POST error message: ", $resp->message, "\n";
}


formtest.cgi

#!/usr/bin/perl

$CRLF = "\x0d\x0a";

print "Content-type: text/html$CRLF$CRLF";

foreach $pair (split(/&/, $ENV{'QUERY_STRING'})) {
  $pair =~ s/\+/ /g;
  $pair =~ s/%([\da-f]{2})/pack('c',hex($1))/ieg;
  ($_qsname, $_qsvalue) = split(/=/, $pair);
  eval "$$_qsname='$_qsvalue'";
  }

$title = $blue ? "I'm Blue" : "Big Light in Sky";

$listening = $listening? "Yes" : "No";
$blue = $blue ? "Yes" : "No";

print <<HERE;

<title>$title</title>

<table>
  <tr><th align=right>Name:               <td>$name
  <tr><th align=right>Age:                <td>$age
  <tr><th align=right>Are they listening? <td>$listening
  <tr><th align=right>Are you Blue?       <td>$blue
  <tr><th align=right>This form is:       <td>$formis
  <tr><th align=right>This form is also:  <td>$formalso
  <tr><th align=right>The secret word is: <td>$info

</table>

HERE

foreach $pair (split(/&/, 
$ENV{'QUERY_STRING'})) {
  . . . 
}

If the data were instead using the POST method, we could do the same thing like this:
foreach $pair (split(/&/, <STDIN>)) {
    . . . 
}

In many cases, it is best if you do not count on getting your data in one or the other method. Instead, you may want to handle whichever method may be in use. If so, here is a subroutine that will handle either method:

# getquery
# returns hash of CGI query strings
#
sub getquery{
my $method = $ENV{'REQUEST_METHOD'};
my ($query_string, $pair);
my %query_hash;

$query_string = $ENV{'QUERY_STRING'} 
if $method eq 'GET';
$query_string = <STDIN> 
if $method eq 'POST';
return undef unless $query_string;

foreach $pair (split(/&/, $query_string)) {
 $pair =~ s/\+/ /g; 
 $pair =~ s/%([\da-f]{2})/pack('c',hex($1))/ieg;
 ($_qsname, $_qsvalue) = split(/=/, $pair);
 $query_hash{$_qsname} = $_qsvalue; 
}
return %query_hash;
}

You might be wondering what these lines are for:
$pair =~ s/\+/ /g; 
$pair =~ s/%([\da-f]{2})/pack('c',hex($1))/ieg;

Get Post - Exercise

In the next lesson, you will learn about how the query string is encoded and what all it takes to decode it for use. But first, take a stab at the exercise for this lesson and test the GET and POST methods.
Get Post - Exercise

Ad Advanced Perl Programming