- Introduction
- The Apache Request Object
- The HTTP Request Message
- The Client Request
- Accessing Client Request Headers
- Accessing HTML Form Fields
- Reading POSTed Data Manually
- Manipulating Cookies
- Handling File Uploads
- Setting Server Response Headers
- Controlling Caching Behavior
- Sending Server Response Headers
- Setting the Response Status
- Setting Error Headers
- Manipulating Headers with Multiple Like Fields
- Using Subrequests
- Setting Headers for Subrequests
- Short-Circuiting Subrequests
- Getting or Setting the Request Method
- Accessing the Request Object from XS
Accessing HTML Form Fields
You need access to user HTML form input.
Technique
Use the args() or content() methods provided by the Apache class or, for greater flexibility, the param() method from the Apache::Request class.
The simple, but less flexible way is
sub handler { my $r = shift; my %query_string = $r->args; # GET data my %post_data = $r->content; # POST data # Continue along... }
Or, using the Apache::Request class
use Apache::Request; sub handler { my $r = Apache::Request->new(shift); $r->send_http_header('text/plain'); # Now, we use the param() method, which covers both GET and POST data. foreach my $param ($r->param) { print "$param => ", $r->param($param), "\n"; } # Continue along... }
Comments
Recipe 3.3 illustrates the args() method as a way of gaining access to form data. Unlike a GET request, which has a field in the Apache request record dedicated to holding the query string portion of the URI, data from a POST request is contained within the message body of the incoming request. To access this, mod_perl provides the content() method. Both args() and content() return a list of unescaped key/value pairs in a list context, providing a simple interface to end-user form data.
The Web has become an increasingly more complex programming environment, using HTML forms for more and more intricate uses. As such, you may find that typical args() and content() syntax is rather limiting. For instance, assigning the results of either method to a hash will remove any like named keys, whereas using an array instead will preserve the keys but does not lend itself to easy manipulation. Additionally, both will mishandle form fields that allow multiple choices, like
<form> <select name="castaways" multiple> <option>Gilligan</option> <option>The Skipper</option> <option>Mr. Howell</option> </select> </form>
For those cases where args() or content() prove to be too restrictive, or for a more general solution that handles (nearly) all types of HTML form data, consider using the Apache::Request module.
Apache::Request is part of the libapreq package, which you can find on CPAN under the Apache tree, and which you must install separately from mod_perl. As a whole, libapreq implements a Perl interface to underlying Apache C API methods that can manipulate client request data such as cookies, file uploads, and GET and POST data of type application/x-www-form-urlencoded or multipart/form-data.
The interface for Apache::Request is modeled after that of CGI.pm. It parses and unescapes both GET and POST data, and can be used to either get or set input parameters. The provided param() method functions just like that of CGI.pm, but unlike CGI.pm, the back-end is implemented in C instead of Perl. Apache::Request also has no methods for creating form elements. Both of these aspects make Apache::Request smaller and more efficient for simply accessing form data.
Another advantage is that Apache::Request is a complete subclass of the Apache class. Apache::Request->new() can be used as a drop-in replacement for Apache->request(), allowing you to add Apache::Request features while only requiring minimal changes to your existing code.
In addition to the new() constructor, Apache::Request also offers the instance() method. Instead of returning a new object every time, instance() always returns the same Apache::Request object for the current request.
my $r = Apache::Request->instance(Apache->request);
The instance() method becomes particularly useful when you need access to POST data from more than one handler (for instance, when processing the actual request and during logging). Because POST data is contained within the message body of the incoming request, it can only be read directly from the socket once per request. When you call param(), POSTed data is parsed, stashed in memory, and associated with the current Apache::Request object. A later call to new() creates an entirely new Apache::Request object that will not have access to the previous object's data. However, if you use the instance() method to create all of your Apache::Request objects instead of new(), then you can be sure that all calls to param() will have access to POSTed content, because they will access the data through the exact same object.
One thing worth keeping in mind is that param() is actually tied to the Apache::Table class. When called in a scalar context without any arguments, it will return an Apache::Table object, allowing you to use all the methods of the Apache::Table class for manipulating your data. See Recipe 3.14 later in this chapter for more information on the Apache::Table class.