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:
- Read $ENV{'CONTENT_LENGTH'} bytes from STDIN (standard input) into a temporary variable called $temp
- Split $temp into separate keywords on "&"
- Each key-value will be split on "="
- Each key and value will be unencoded: each "+" will be changed to a space and %xx codes will be translated back to characters.
#! /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.