
Beginning Perl Web Development - From Novice To Professional (2006)
.pdf
210 C H A P T E R 1 1 ■ D E V E L O P M E N T W I T H M O D _ P E R L
You can use the Apache request object to retrieve, inspect, and modify request and response headers. These headers are defined by the HTTP standard, which is codified in RFC 2616 (see http://www.rfc-editor.org/).
You can both retrieve incoming headers (the request) and set outgoing headers (the response). Setting a response header is required for CGI programming and is usually done by the CGI module or by a simple print statement. Remember from way back in Chapter 1, where one of the first CGI examples shown sent a Content-Type header as the first line of output:
print "Content-Type: text/html\n\n";
The Apache request object has a method for accomplishing this same task:
my $r = shift; $r->send_http_header('text/html');
Of course, you can send this header with the CGI module, too:
use CGI qw/:standard/; print header;
Note that you can use another method, content_type(), to set the Content-Type within the Apache response, as well as set other response headers with the Apache request object, as you’ll see in the “Accessing the Response” section later in this chapter. First things first though. In order to send a response, you first must receive a request.
Accessing the Request
The Apache request object gives you access to the actual request itself for the incoming request from the client. This includes the method used for the request such as GET, POST, and so on, as well as the path and HTTP version information.
Consider the code to print the incoming client request shown in Listing 11-2 (Printrequest.cgi).
Listing 11-2. Printing the Request
use strict;
my $r = shift;
$r->send_http_header('text/plain'); print $r->the_request();
When viewed through a browser, the output shows the incoming request, as shown in Figure 11-6.

C H A P T E R 1 1 ■ D E V E L O P M E N T W I T H M O D _ P E R L |
211 |
Figure 11-6. The incoming client request as viewed through the Apache request object
Using Methods to Retrieve Request Values
The request, through the_request() method just shown, is further broken down into the relevant parts through other methods. Listing 11-3 (Printrequestbits.cgi) prints the relevant items from the request.
Listing 11-3. Printing Some Relevant Items from the Request
use strict;
my $r = shift;
$r->send_http_header('text/plain');
print "Method: ", $r->method, "\n"; print "URI: ", $r->uri, "\n";
print "Path: ", $r->path_info, "\n"; print "Hostname: ", $r->hostname, "\n"; print "Protocol: ", $r->protocol, "\n"; print "File: ", $r->filename, "\n";
The output from this program is shown in Figure 11-7.

212 C H A P T E R 1 1 ■ D E V E L O P M E N T W I T H M O D _ P E R L
Figure 11-7. The relevant bits of the request
Missing from this example is the query string that can be included in a request. The query string is the portion of the URI that follows the path. Consider this example:
http://www.example.com/cgi-bin/order.cgi?name=Steve&value=ID
Here, the query string is as follows:
?customerid=5150&action=order
The items on the query string (after the ?) lend themselves to the name=value structure native in a hash. You can use the args() method to access the query string. It’s no surprise that there are many ways to work with these name=value pairs. The first and most basic simply accesses the args() method directly, as shown in Listing 11-4 (Printquery.cgi).
Listing 11-4. Printing the Query String
use strict;
my $r = shift;
$r->send_http_header('text/plain');
print "Query String: ", $r->args, "\n";
Examining the output from this program, illustrated in Figure 11-8, shows that the name=value pairs have been essentially concatenated by the call to $r->args.

C H A P T E R 1 1 ■ D E V E L O P M E N T W I T H M O D _ P E R L |
213 |
Figure 11-8. Output from the args() method
Another way to call the args() method is to cast it into a scalar, as shown in Listing 11-5 (Printquery2.cgi).
Listing 11-5. Casting args() into a Scalar
use strict;
my $r = shift;
$r->send_http_header('text/plain');
print "Query String: ", scalar $r->args, "\n";
This example produces output as it was received, including ampersands and equal signs, as illustrated in Figure 11-9.

214 C H A P T E R 1 1 ■ D E V E L O P M E N T W I T H M O D _ P E R L
Figure 11-9. Another way to produce output from the args() method
Yet another way to accomplish the task at hand is to place the output from the args() method into a hash, and then iterate through the hash, as shown in Listing 11-6 (Printquery3.cgi).
Listing 11-6. Iterating Through the Arguments
use strict;
my $r = shift;
$r->send_http_header('text/plain');
my %args = $r->args;
foreach my $arg (keys %args) { print "$arg = $args{$arg}\n";
}
This example has the effect of producing traditional name=value pairs that are easier to work with inside the program. This cleaner output is shown in Figure 11-10.

C H A P T E R 1 1 ■ D E V E L O P M E N T W I T H M O D _ P E R L |
215 |
Figure 11-10. The output from yet another way to retrieve the query string
Using the args() method as shown in the previous examples works well in most instances. However, for multivalued objects, the normal ways to access this hash can’t be used effectively. For instance, consider what would happen to the name=value nature of a CGI program called like this:
http://www.example.com/cgi-bin/order.cgi?action=order&action=final
Notice that there are two values for the action in the query string. The output in Figure 11-11 shows what happens when this query string is encountered by code similar to that shown in Listing 11-5.

216 C H A P T E R 1 1 ■ D E V E L O P M E N T W I T H M O D _ P E R L
Compare this output with that shown in Figure 11-12. This output was produced by placing the output from the args() method into a hash, as shown in Listing 11-6. Notice that only the final value for the action parameter is actually sent to output.
Figure 11-12. Output from a multivalued query string
Although you can iterate through multivalued parameters, if your CGI program will be using multivalued parameters, I recommend using the CGI.pm’s methods for accessing these values, rather than coding around the args() method.
So far, these methods retrieve values from GET requests. For POST requests, use the content() method, as shown in Listing 11-7 (Post.cgi).
Listing 11-7. Using the content() Method
use strict;
my $r = shift;
$r->send_http_header('text/plain');
my %data = $r->content;
foreach my $name (keys %data) { print "$name = $data{$name}\n";
}
This code looks and is largely similar to Listing 11-6, which retrieved arguments using the args() method. Mainly, the variable names have been changed to protect the innocent. The
content() in this case.

C H A P T E R 1 1 ■ D E V E L O P M E N T W I T H M O D _ P E R L |
217 |
The Apache::Request class provides the most flexible method for working with form data through the param() method, as in the example in Listing 11-8 (Param.cgi).
Listing 11-8. Using the param() Method to Look at Parameters
use Apache::Request;
my $r = Apache::Request->new(shift);
$r->send_http_header('text/plain');
foreach my $param ($r->param) {
print "Param: $param = " , $r->param($param), "\n";
}
The param() method works like CGI.pm, but is implemented in the C programming language as opposed to Perl. The param() method works with both GET and POST data.
■Note The examples in this section also demonstrate how to work with HTML form fields through mod_perl. They show how to parse the parameters from the GET or POST request.
Other methods related to the incoming request include header_only(), for determining whether or not the incoming request was a HEAD type request, and proxyreq(), for determining whether or not the request is a proxy request. Both of these methods return true if they are positive, meaning that the method will return true if it’s a HEAD request or if it’s a proxy request, respectively.
Accessing Request Headers
So far, you’ve seen the actual request and methods for working with the request. As noted earlier, the client may also send headers related to the request.
You can access request headers through the headers_in() method, which contains a set of name=value pairs. The headers_in() method is part of the Apache::Table class, which also contains other class methods, including the following:
•err_headers_out()
•headers_out()
•info()
•notes()
•subprocess_env()

218 C H A P T E R 1 1 ■ D E V E L O P M E N T W I T H M O D _ P E R L
Each of the class methods of Apache::Table has its own set of methods, including the following:
•add()
•clear()
•do()
•get()
•merge()
•new()
•set()
•unset()
Since name=value pairs are sent from the headers_in() method, the output naturally lends itself to being represented in a hash. Listing 11-9 (Headersin.cgi) prints the output from the headers_in() method.
Listing 11-9. The headers_in() Method to See Name=Value Pairs
use strict;
my $r = shift;
$r->send_http_header('text/plain');
my %headers = $r->headers_in();
foreach my $header (keys %headers) { print "$header = $headers{$header}\n";
}
The output is shown in Figure 11-13.

C H A P T E R 1 1 ■ D E V E L O P M E N T W I T H M O D _ P E R L |
219 |
Figure 11-13. The headers for a request retrieved using the headers_in() method
You could access individual headers by calling them within the hash. For example, Listing 11-10 (Printuseragent.cgi) shows the code to see the user agent used for the request.
Listing 11-10. Looking at the User Agent
use strict;
my $r = shift;
$r->send_http_header('text/plain');
my %headers = $r->headers_in();
print "The User-Agent is: $headers{'User-Agent'}\n";
The output from this program is shown in Figure 11-14.