Show Contents Previous Page Next Page
Chapter 9 - Perl API Reference Guide / The Apache Request Object Server Core Functions
This section covers the API methods that are available for your use during the processing of a request but are not directly related to incoming or outgoing data.
chdir_file()
Given a filename as argument, change from the current directory to the
directory in which the file is contained. This is a convenience routine
for modules that implement scripting engines, since it is common to run
the script from the directory in which it lives. The current directory
will remain here, unless your module changes back to the previous directory.
As there is significant overhead associated with determining the current
directory, we suggest using the $Apache::Server::CWD variable
or the server_root_ relative() method if you wish to return to
the previous directory afterward.
$r->chdir_file($r->filename);
child_terminate()
Calling this method will cause the current child process to shutdown
gracefully after the current transaction is completed and the logging
and cleanup phases are done. This method is not available on Win32 systems.
$r->child_terminate;
hard_timeout()
kill_timeout()
reset_timeout()
soft_timeout()
The timeout API governs the interaction of Apache with the client. At
various points during the request/response cycle, a browser that is no longer
responding can be timed out so that it doesn't continue to hold the connection
open. Timeouts are primarily of concern to C API programmers, as mod_perl
handles the details of timeouts internally for read and write methods. However,
these calls are included in the Perl API for completeness. The hard_timeout() method initiates a "hard" timeout. If the
client read or write operation takes longer than the time specified by Apache's
Timeout directive, then the current handler will be aborted immediately
and Apache will immediately enter the logging phase. hard_timeout()
takes a single string argument which should contain the name of your module
or some other identification. This identification will be incorporated into
the error message that is written to the server error log when the timeout
occurs.
soft_timeout(), in contrast, does not immediately abort the current
handler. Instead, when a timeout occurs control returns to the handler,
but all read and write operations are replaced with no-ops so that no further
data can be sent or received to the client. In addition, the Apache::Connection
object's aborted() method will return true. Like hard_ timeout(),
you should pass this method the name of your module in order to be able
to identify the source of the timeout in the error log. The reset_timeout() method can be called to set a previously
initiated timer back to zero. It is usually used between a series of read
or write operations in order to restart the timer. Finally, the kill_timeout() method is called to cancel a previously
initiated time-out. It is generally called when a series of I/O operations
are completely done. The following examples will give you the general idea of how these four
methods are used. Remember, however, that in the Perl API these methods
are not really necessary because they are called internally by the read()
and print() methods.
# typical hard_timeout() usage
$r->hard_timeout("Apache::Example while reading data");
while (... read data loop ...) {
...
$r->reset_timeout;
}
$r->kill_timeout;
# typical soft_timeout() usage
$r->soft_timeout("Apache::Example while reading data");
while (... read data loop ...) {
...
$r->reset_timeout;
}
$r->kill_timeout;
internal_redirect()
Unlike a full HTTP redirect in which the server tells the browser
to look somewhere else for the requested document, the internal_redirect()
method tells Apache to return a different URI without telling the client.
This is a lot faster than a full redirect. The required argument is an absolute URI path on the current server.
The server will process the URI as if it were a whole new request, running
the URI translation, MIME type checking, and other phases before invoking
the appropriate content handler for the new URI. The content handler
that eventually runs is not necessarily the same as the one that invoked
internal_redirect(). This method should only be called within
a content handler. Do not use internal_redirect() to redirect to a
different server. You'll need to do a full redirect for that. Both redirection
techniques are described in more detail in Chapter 4.
$r->internal_redirect("/new/place");
Apache implements its ErrorDocument feature as an internal
redirect, so many of the techniques that apply to internal redirects also
apply to custom error handling.
internal_redirect_handler()
This method does the same thing as internal_redirect() but
arranges for the content handler used to process the redirected URI
to be the same as the current content handler.
$r->internal_redirect_handler("/new/place");
is_initial_req()
There are several instances in which an incoming URI request can trigger
one or more secondary internal requests. An internal request is triggered
when internal_redirect() is called explicitly, and it also
happens behind the scenes when lookup_file() and lookup_uri()
are called. With the exception of the logging phase, which is run just once for
the primary request, secondary requests are run through each of the
transaction processing phases, and the appropriate handlers are called
each time. There may be times when you don't want a particular handler
running on a subrequest or internal redirect, either to avoid performance
overhead or to avoid infinite recursion. The is_initial_req()
method will return a true value if the current request is the primary
one and false if the request is the result of a subrequest or an internal
redirect.
return DECLINED unless $r->is_initial_req;
is_main()
This method can be used to distinguish between subrequests triggered
by handlers and the "main" request triggered by a browser's request
for a URI or an internal redirect. is_ main() returns a true
value for the primary request and for internal redirects and false for
subrequests. Notice that this is slightly different from is_initial_req(),
which returns false for internal redirects as well as subrequests. is_main() is commonly used to prevent infinite recursion
when a handler gets reinvoked after it has made a subrequest.
return DECLINED unless $r->is_main;
Like is_initial_req(), this is a read-only method.
last()
main()
next()
prev()
When a handler is called in response to a series of internal redirects,
ErrorDocuments, or subrequests, it is passed an ordinary-looking
request object and can usually proceed as if it were processing a normal
request. However, if a module has special needs, it can use these methods
to walk the chain to examine the request objects passed to other requests
in the series.
main() will return the request object of the parent request,
the top of the chain. last() will return the last request in
the chain. prev() and next() will return the previous
and next requests in the chain, respectively. Each of these methods
will return a reference to an object belonging to the Apache
class or undef if the request doesn't exist. The prev() method is handy inside an ErrorDocument
handler to get at the information from the request that triggered the
error. For example, this code fragment will find the URI of the failed
request:
my $failed_uri = $r->prev->uri;
The last() method is mainly used by logging modules. Since
Apache may have performed several subrequests while attempting to resolve
the request, the last object will always point to the final
result.
my $bytes_sent = $r->last->bytes_sent;
Should your module wish to log all internal requests, the next()
method will come in handy.
sub My::logger {
my $r = shift;
my $first = $r->uri;
my $last = $r->last->uri;
warn "first: $first, last: $last\n";
for (my $rr = $r; $rr; $rr = $rr->next) {
my $uri = $rr->uri;
my $status = $rr->status;
warn "request: $uri, status: $status\n";
}
return OK;
}
Assuming the requested URI was /, which was mapped to /index.html
by the DirectoryIndex configuration, the example above would
output these messages to the ErrorLog:
first: /, last: /index.html
request: /, status: 200
request: /index.html, status: 200
The next() and main() methods are rarely used, but
they are included for completeness. Handlers that need to determine whether
they are in the main request should call $r->is_main()
rather than !$r->main() , as the former is marginally more
efficient.
location()
If the current handler was triggered by a Perl*Handler directive
within a <Location> section, this method will return
the path indicated by the <Location> directive. For example, given this <Location> section:
<Location /images/dynamic_icons>
SetHandler perl-script
PerlHandler Apache::Icon
</Location>
location() will return /images/dynamic_icons. This method is handy for converting the current document's URI into
a relative path.
my $base = $r->location;
(my $relative = $r->uri) =~ s/^$base//;
lookup_file() lookup_uri()
lookup_file() and lookup_uri() invoke Apache subrequests.
A subrequest is treated exactly like an ordinary request, except that
the post read request, header parser, response generation, and logging
phases are not run. This allows modules to pose "what-if" questions
to the server. Subrequests can be used to learn the MIME type mapping
of an arbitrary file, map a URI to a filename, or find out whether a
file is under access control. After a successful lookup, the response
phase of the request can optionally be invoked. Both methods take a single argument corresponding to an absolute filename
or a URI path, respectively. lookup_uri() performs the URI
translation on the provided URI, passing the request to the access control
and authorization handlers, if any, and then proceeds to the MIME type
checking phase. lookup_file() behaves similarly but bypasses
the initial URI translation phase and treats its argument as a physical
file path. Both methods return an Apache::SubRequest object, which is
identical for all intents and purposes to a plain old Apache
request object, as it inherits all methods from the Apache
class. You can call the returned object's content_type(), filename(),
and other methods to retrieve the information left there during subrequest
processing. The subrequest mechanism is extremely useful, and there are many practical
examples of using it in Chapters 4, 5,
and 6. The following code snippets show how
to use subrequests to look up first the MIME type of a file and then
a URI:
my $subr = $r->lookup_file('/home/http/htdocs/images/logo.tif');
my $ct = $subr->content_type;
my $ct = $r->lookup_uri('/images/logo.tif')->content_type;
In the lookup_uri() example, /images/logo.tif will
be passed through the same series of Alias, ServerRoot,
and URI rewriting translations that the URI would be subjected to if
it were requested by a browser. If you need to pass certain HTTP header fields to the subrequest,
such as a particular value of Accept, you can do so by calling
headers_in() before invoking lookup_uri() or lookup_file(). It is often a good idea to check the status of a subrequest in case
something went wrong. If the subrequest was successful, the status
value will be that of HTTP_OK .
use Apache::Constants qw(:common HTTP_OK);
my $subr = $r->lookup_uri("/path/file.html");
my $status = $subr->status;
unless ($status == HTTP_OK) {
die "subrequest failed with status: $status";
}
notes()
There are times when handlers need to communicate among themselves
in a way that goes beyond setting the values of HTTP header fields.
To accommodate this, Apache maintains a "notes" table in the request
record. This table is simply a list of key/value pairs. One handler
can add its own key/value entry to the notes table, and later the handler
for a subsequent phase can retrieve the note. Notes are maintained for
the life of the current request and are deleted when the transaction
is finished. When called with two arguments, this method sets a note. When called
with a single argument, it retrieves the value of that note. Both the
keys and the values must be simple strings.
$r->notes('CALENDAR' => 'Julian');
my $cal = $r->notes('CALENDAR');
When called in a scalar context with no arguments, a hash reference
tied to the Apache::Table class will be returned.
my $notes = $r->notes;
my $cal = $notes->{CALENDAR};
This method comes in handy for communication between a module written
in Perl and one written in C. For example, the logging API saves error
messages under a key named error-notes , which could be
used by ErrorDocuments to provide a more informative error
message.
The LogFormat directive, part of the standard mod_log_config
module, can incorporate notes into log messages using the formatting character
%n . See the Apache documentation for details.
subprocess_env()
The subprocess_env() method is used to examine and change
the Apache environment table. Like other table-manipulation functions,
this method has a variety of behaviors depending on the number of arguments
it is called with and the context in which it is called. Call the method
with no arguments in a scalar context to return a hash reference tied
to the Apache::Table class:
my $env = $r->subprocess_env;
my $docroot = $env->{'DOCUMENT_ROOT'};
Call the method with a single argument to retrieve the current value
of the corresponding entry in the environment table, or undef
if no entry by that name exists:
my $doc_root = $r->subprocess_env("DOCUMENT_ROOT");
You may also call the method with a key/value pair to set the value
of an entry in the table:
$r->subprocess_env(DOOR => "open");
Finally, if you call subprocess_env() in a void context with
no arguments, it will reinitialize the table to contain the standard
variables that Apache adds to the environment before invoking CGI scripts
and server-side include files:
$r->subprocess_env;
Changes made to the environment table only persist for the length
of the request. The table is cleared out and reinitialized at the beginning
of every new transaction. In the Perl API, the primary use for this method is to set environment
variables for other modules to see and use. For example, a fixup handler
could use this call to set up environment variables that are later recognized
by mod_include and incorporated into server-side include pages.
You do not ordinarily need to call subprocess_env() to read
environment variables because mod_perl automatically copies
the environment table into the Perl %ENV array before entering
the response handler phase. A potential confusion arises when a Perl API handler needs to launch
a subprocess itself using system(), backticks, or a piped open.
If you need to pass environment variables to the subprocess, set the appropriate
keys in %ENV just as you would in an ordinary Perl script.
subprocess_env() is only required if you need to change the environment
in a subprocess launched by a different handler or module.
register_cleanup()
The register_cleanup() method registers a subroutine that
will be called after the logging stage of a request. This is much the
same as installing a cleanup handler with the PerlCleanupHandler
directive. See Chapter 7 for some
practical examples of using register_ cleanup(). The method expects a code reference argument:
sub callback {
my $r = shift;
my $uri = $r->uri;
warn "process $$ all done with $uri\n";
}
$r->register_cleanup(\&callback);
Show Contents Previous Page Next Page Copyright © 1999 by O'Reilly & Associates, Inc. |