- 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
Setting the Response Status
You want to tell the client the status of the request by indicating a successful response or an error response, such as a redirect or a server error.
Technique
Use constants exported by the Apache::Constants class to communicate the status of the response back to Apache.
package Cookbook::Regex; use Apache::Constants qw(:common); use Apache::File; use Apache::Log; use strict; sub handler { my $r = shift; my $log = $r->server->log; my @change = $r->dir_config->get('RegexChange'); my @to = $r->dir_config->get('RegexTo'); unless ($r->content_type eq 'text/html') { $log->info("Request is not for an html document - skipping..."); return DECLINED; } unless (@change && @to) { $log->info("Parameters not set - skipping..."); return DECLINED; } if (@change != @to) { $log->error("Number of regex terms do not match!"); return SERVER_ERROR; } my $fh = Apache::File->new($r->filename); unless ($fh) { $log->warn("Cannot open request - skipping... $!"); return DECLINED; } $r->send_http_header('text/html'); while (my $output = ) { for (my $i=0; $i < @change; $i++) { $output =~ s/$change[$i]/$to[$i]/eeg; } print $output; } return OK; } 1;
Comments
Built in to the HTTP/1.1 specification is a series of status codes for communicating the status of the request back to the client. Everyone is familiar with error responses like 404 Not Found and 500 Internal Server Error that appear occasionally while surfing the Web. The 200 OK responses that are the norm typically go by unnoticed, masked by the actual content displayed by the browser. In each of these cases, Apache is returning an HTTP status code through the Status-Line of the server response. Through the mod_perl API we have the ability to control the status of the request by returning the appropriate status as the return value from our handler. Thinking of handlers as functions, not procedures, helps the return code of the handler defines the status of the request. The Apache::Constants module provides the complete set of response codes as symbolic, human-readable names. These codes are based on the standard HTTP response codes, with the addition of some Apachespecific codes.
It is easiest to begin with the HTTP specific codes. Internally, Apache stores the HTTP status of the request in the status slot of the Apache request record. At the start of each request, the status is set to the constant HTTP_OK, which corresponds to a 200 OK HTTP response. As the different Apache modules step into the request, each has the ability to set the response status to something other than HTTP_OK by returning an HTTP return code. For instance, mod_dir returns HTTP_MOVED_PERMANENTLY whenever a URI is received for a directory but does not contain a trailing slash, such as http://www.example.com/sails. Apache then propagates that response back to the end user in the form of a 301 Moved Permanently response, the browser redirects to the target URI http://www.example.com/sails/, and things continue as normal.
The mechanism is the same for your Perl handlers. Sending a response back to the client with a status other than 200 OK only requires that you return the appropriate HTTP status code back from your handler. These status codes are made available to your code through the Apache::Constants class, which allows you to import each constant by name or use a set of import tags. For instance, we used the :common import tag in the preceding sample handler.
Table 3.8 shows a few of the more common HTTP return codes, along with their Apache::Constants names, suitable for importing into your code. A larger list can be found in Appendix B, whereas the authoritative source is section 10 of RFC 2616.
Table 3.8 Some Apache::Constants Server Response Constants
Apache::Constants Constant |
HTTP Response Code |
AUTH_REQUIRED |
401 Unauthorized |
FORBIDDEN |
403 Forbidden |
NOT_FOUND |
404 Not Found |
REDIRECT |
302 Found |
SERVER_ERROR |
500 Internal Server Error |
Aside from these HTTP return codes, Apache maintains three constants that are meant to help facilitate the interaction between Apache and the various request handlers: OK, DECLINED, and DONE. All of these are also available through the Apache::Constants class. The reason for these Apache-specific codes will become clear in Part III, where we examine the Apache request cycle in detail. For the moment, we can just focus on some mechanics and save the details for later.
The most common return code is OK, which indicates success. Remember that Apache has already set the response to 200 OK, so it generally is not appropriate to return HTTP_OK from your handlerOK is the proper value in nearly all cases. DECLINED tells Apache that you have declined to process the request. This does not necessarily mean that you have not altered the request, only that you have chosen not to inform Apache about it. The final Apache-specific return code is DONE, which indicates that all content has been sent to the client and Apache should immediately skip to the logging phase of the request. DONE is rarely used, but is useful in certain circumstances. Recipe 11.6 shows an interesting application of the DONE return code.
For the most part, all of your handlers will return OK or one of the HTTP-specific error codes, such as REDIRECT or SERVER_ERROR. In reality, Apache treats any return code other than OK, DECLINED, or DONE as an error. While this may sound strange, all it really means is that Apache will start its error response cycle, which allows you to capture responses other than HTTP_OK with an ErrorDocument or the custom response mechanism discussed in Recipe 8.6. Reasons to choose DECLINED over OK as a return code are more fully discussed in later chapters, where each phase of the request cycle has its own peculiarities.
As we have mentioned a few times, Apache::Registry is really a mod_perl handler that wraps your Perl CGI code within a handler() subroutine. One of the side effects of the Apache::Registry design, however, is that any return value from Registry scripts is ignored by Apache::Registry::handler(). This means that the model we have described here does not apply, even though Apache::Registry scripts have access to the entire mod_perl API.
The way around this is to set the status of the request directly using the status() method from the Apache class. For instance, a typical idiom for Registry scripts that use the mod_perl API is:
$r->headers_out(Location => "/pirate_map.html"); $r->status(REDIRECT); return REDIRECT;
The interesting thing to note here is that, in the case of Registry scripts, the return value actually just serves as a way to exit the script gracefully without any further processing$r->status(REDIRECT) is the actual mechanism that is telling Apache to return 302 Found back to the client. Actually, it is a bit trickier than that. Apache::Registry returns the status you set with $r->status() back to Apache, then sets $r->status() back to HTTP_OK, because handlers typically do not alter $r->status() directly.
For our example and discussion we have only used a few of the constants available through the Apache::Constants class: Apache::Constants contains over 90 different constants used for the many different aspects of mod_perl, from the server-response codes we have discussed so far to constants only useful when dealing with the internal Apache API. Importing all those constants into your script wastes precious memory and is excessive for all but the most demanding Web application. To make life easier, Apache::Constants defines several import tags that group constants of similar purpose together, such as the :common tag used in the example code. Other convenient tags are listed in the Apache::Constants manpage.
Because every constant you import into your code increases your process size (albeit slightly), you can slim down this list by importing only those constants you actually use:
use Apache::Constants qw(OK REDIRECT SERVER_ERROR);
Not only does this keep unneeded symbols out of your process, as discussed in Chapter 9, but it also increases readability of your code. For the most part, our examples will make use of this more explicit syntax.