Tables are similar to Perl hashes in that they are lists of key/value pairs.However, unlike a Perl hash, keys are case-insensitive, and a single keymay correspond to a list of several va
Trang 1Apache provides a general API for creating and maintaining lookup
tables Apache tables are ubiquitous, used for everything from storing thecurrent request's outgoing HTTP headers to maintaining the list of
environment variables passed to subprocesses
Tables are similar to Perl hashes in that they are lists of key/value pairs.However, unlike a Perl hash, keys are case-insensitive, and a single keymay correspond to a list of several values.[2] In addition, Apache tablekeys and values are always strings; arbitrary data types cannot be used
[2] Despite the differences between Perl hashes and Apache tables,the Perl API allows programmers to access tables via tied Perl
hashes See Section 9.2.5
10.5.1 The table and table_entry Data Types
Currently, a table is an Apache array containing array elements of thetable_entry data type (defined in include/alloc.h):
access the table_entry directly, but use API function calls to
manipulate the keys and values for you If you do read directly from thetable_entry, a note in the include file indicates that you should checkthe key for null This is because the table_entry may be made part of
a more sophisticated hash table in the future
The table structure itself is a private data type intended to be accessedvia an opaque table * If you want to peek at its definition, you can find
Trang 5ap_table_merge(r->headers_out, "Content-language", "fr");ap_table_merge(r->headers_out, "Content-language", "sp");
Trang 8client However, as a convenience, mod_perl ties the STDIN and
STDOUT filehandles to the Apache class prior to invoking Perl API
modules This allows handlers to read from standard input and write tostandard output exactly as if they were in the CGI environment
Trang 9its methods from there Here are two examples of fetching subrequestobjects:
would like to invoke the content handler, the run( ) method will do it:
my $status = $subr->run;
When you invoke the subrequest's response handler in this way, itwill do everything a response handler is supposed to, including
sending the HTTP headers and the document body run( ) returns
the content handler's status code as its function result If you are
invoking the subrequest run( ) method from within your own content
handler, you must not send the HTTP header and document bodyyourself, as this would be appended to the bottom of the information
that has already been sent Most handlers that invoke run() will
immediately return its status code, pretending to Apache that theyhandled the request themselves:
Apache::Server object can be obtained by calling the Apache request object's server( ) method At Perl startup time (such as within a startup
Trang 10is_virtual()
This method returns true if the current request is being applied to avirtual server This is a read-only method
messages logged with Apache::log() will include the IP address of
the browser and add the messages to the notes table under a key
named error-notes See the description of notes() under Section
Trang 11port()
This method returns the port on which this (virtual) server is listening
If no port is explicitly listed in the server configuration file (that is, theserver is listening on the default port 80), this method will return 0
Trang 13object's connection( ) method The connection object is not available
outside of handlers for the various request phases because there is noconnection established in those cases By convention, we use the
aborted()
This method returns true if the client has broken the connection
prematurely This can happen if the remote user's computer hascrashed, a network error has occurred, or, more trivially, the userpressed the stop button before the request or response was fullytransmitted However, this value is only set if a soft timeout occurred.if($c->aborted) {
the request object's auth_type( ) method, which we discussed
earlier, because the request object's method returns the value of the
AuthType configuration directive; in other words, the type of
authentication the server would like to use The connection object's
Trang 16the case of a single request that has been forwarded across multipleproxies It's safest to choose the last IP address in the list since this
Trang 17tables API function calls allow you to obtain the list of defined keys,iterate through them, get the value of a key, and set key values Sincemany HTTP header fields are potentially multivalued, Apache also
provides functionality for getting, setting, and merging the contents ofmultivalued fields
interface that allows transparent access to its methods via a tied hashreference, as well as API methods that can be called directly
The TIEHASH interface is easy to use Simply call one of the methodslisted earlier in a scalar context to return a tied hash reference For
Trang 18defined value of the field You can get around this by using the object-or by using the each operator to access each key and value sequentially The following code snippet shows one way to fetch all the Set-cookie
fields in the outgoing HTTP header:
while (my($key, $value) = each %{$r->headers_out}) { push @cookies, $value if lc($key) eq 'set-cookie';}
When you treat an Apache::Table object as a hash reference, you are accessing its internal get() and set() methods (among others) indirectly.
To gain access to the full power of the table API, you can invoke thesemethods directly by using the method call syntax
Trang 19do()
This method provides a way to iterate through an entire table item byitem Pass it a reference to a code subroutine to be called once for
each table entry The subroutine should accept two arguments
corresponding to the key and value, respectively, and should return atrue value The routine can return a false value to terminate the
Trang 22An Apache::URI object is returned when you call the request object's parsed_uri() method You may also call the Apache::URI parse()
my $fragment = $uri->fragment;
$uri->fragment('section_1');
hostinfo()
This method gets or sets the remote host information, which usuallyconsists of a hostname and port number in the format
hostname:port Some rare URIs, such as those used for
nonanonymous FTP, attach a username and password to this
information, for use in accessing private resources In this case, theinformation returned is in the format
username:password@hostname:port
This method returns the host information when called without
arguments, or sets the information when called with a single stringargument
my $hostinfo = $uri->hostinfo;
$uri->hostinfo('www.modperl.com:8000');
hostname()
This method returns or sets the hostname component of the URIobject
Trang 24path_info() gets or sets the additional path information portion of the
URI, using the current request object to determine what part of thepath is real and what part is additional
my $query = $uri->query;
$uri->query('one+two+three');
rpath()
This method returns the "real path;" that is, the path( ) minus the path_info( ).
my $scheme = $uri->scheme;
$uri->scheme('http');
Trang 25This method returns the string representation of the URI RelativeURIs are resolved into absolute ones
my $string = $uri->unparse;
Beware that the unparse() method does not take the additional path
information into account It returns the URI minus the additionalinformation
corresponding Perl functions and avoid the memory bloat of pulling in yetanother Perl package
URI::Escape::uri_escape( ) function from the LWP package.
Trang 29the presence of individual features
# require Authen and Authz handlers to be enableduse mod_perl qw(PerlAuthenHandler PerlAuthzHandler);
Trang 30The hook( ) function can be used at runtime to determine whether the current mod_perl installation provides support for a certain
feature This is the internal function that import() uses to check for
configured features This function is not exported, so you have to
refer to it using its fully qualified name, mod_perl::hook() hook() recognizes the same list of features that import() does.
Trang 34:server
Trang 35These are constants related to the version of the Apache serversoftware:
Trang 37keep memory consumption at a reasonable level
There are two options if you need to access a constant that is not
exportable by default One is simply to use the fully qualified subroutinename, for example:
die FORBIDDEN;
}
Trang 38The previous chapters have taken you on a wide-ranging tour of the mostpopular and useful areas of the Apache API But we're not done yet! TheApache API allows you to customize URI translation, logging, the
handling of proxy transactions, and the manner in which HTTP headersare parsed There's even a way to incorporate snippets of Perl code
directly into HTML pages that use server-side includes
We've already shown you how to customize the response, authentication,authorization, and access control phases of the Apache request cycle.Now we'll fill in the cracks At the end of the chapter, we show you thePerl server-side include system, and demonstrate a technique for
extending the Apache Perl API by subclassing the Apache request objectitself
Trang 39The last two chapters of this book, Chapters Chapter 10 and Chapter
11, focus on aspects of the Apache module API that C-language
programmers need to know The majority of the API has already beencovered in previous chapters, where we looked at it from the perspective
of its Perl incarnation We will briefly revisit each of the topics that we'vealready discussed in order to show you how the API appears in C Topicsthat are specific to the C API, such as memory management, are covered
in more detail
Because the C API is so much of a recapitulation of the Perl API,[1] wewon't show you as many complete examples in this chapter as we have
arrays, tables, and resource pools, and techniques for getting and settinginformation about the request The next chapter describes how to defineand manage configuration directives and covers the less essential parts
of the C API, such as string manipulation functions, and esoterica such
as opening pipes to subprocesses
We do our best to follow the Apache coding style guide throughout You'llfind this guide along with other developer resources at the Apache
Project Development site, http://dev.apache.org/
Trang 40The Apache request object implements a huge number of methods Tohelp you find the method you're looking for, we've broken them down intoeight broad categories:
Client request methods
Methods that have to do with retrieving information about the currentrequest, such as fetching the requested URI, learning the requestdocument's filename, or reading incoming HTTP headers
Server response methods
Methods that are concerned with setting outgoing information, such
as setting outgoing headers and controlling the document languageand compression
Sending data to the client
Methods for sending document content data to the client
Server core functions
Methods that control key aspects of transaction processing but arenot directly related to processing browser data input or output Forexample, the subrequest API is covered in this section
Server configuration methods
Methods for retrieving configuration information about the server
Logging
Methods for logging error messages and warnings to the server errorlog
Access control methods
Trang 41my $query = $r->args;
my %in = $r->args;
One trap to be wary of: if the same argument name is present severaltimes (as can happen with a selection list in a fill-out form), assignment of
args() to a hash will discard all but the last argument To avoid this, you'll
need to use the more complex argument processing scheme described inChapter 4
Trang 42This method returns an object blessed into the Apache::Connection
class See Section 9.2.4" later in this chapter for information onwhat you can do with this object once you get it
my $c = $r->connection;
content()
When the client request method is POST, which generally occurswhen the remote client is submitting the contents of a fill-out form,
the $r->content method returns the submitted information but only if the request content type is application/x-www-form-urlencoded.
When called in a scalar context, the entire string is returned Whencalled in a list context, a list of parsed name=value pairs is returned
To handle other types of PUT or POSTed content, you'll need to use
a module such as CGI.pm or Apache::Request or use the read()
method and parse the data yourself
Note that you can only call content() once If you call the method more than once, it will return undef (or an empty list) after the first try filename()
The filename( ) method sets or returns the result of the URI
translation phase During the URI translation phase, your handler willcall this method with the physical path to a file in order to set thefilename During later phases of the transaction, calling this methodwith no arguments returns its current value
Trang 43finfo()
Immediately following the translation phase, Apache walks along thecomponents of the requested URI trying to determine where the
physical file path ends and the additional path information begins(this is described at greater length at the beginning of Chapter 4) In
Trang 44for manipulating the contents of the stat structure For example, the
ht_time() routine turns Unix timestamps into HTTP-compatible human readable strings See the Apache::Util manpage and the section Section
Chapter 10, and provides for timeouts and other niceties Althoughthe Perl API supports them, Perl programmers should generally use
the simpler read() method instead.
get_remote_host()
This method can be used to look up the remote client's DNS
hostname or simply return its IP address When a DNS lookup issuccessful, its result is cached and returned on subsequent calls to
get_remote_host( ) to avoid costly multiple lookups This cached value can also be retrieved with the Apache::Connection object's remote_host() method.
This method takes an optional argument The type of lookup
performed by this method is affected by this argument, as well as the
value of the HostNameLookups directive Possible arguments to this
method, whose symbolic names can be imported from the
Trang 45following:
REMOTE_HOST
If this argument is specified, Apache will try to look up the DNSname of the remote host This lookup will fail if the Apache
representation of the client's IP address otherwise This is thedefault lookup type when no argument is specified
REMOTE_NOLOOKUP
When this argument is specified, get_remote_host() will not perform a new DNS lookup (even if the HostNameLookups
directive says so) If a successful lookup was done earlier in therequest, the cached hostname will be returned Otherwise, themethod returns the dotted decimal representation of the client's
returns the hostname Otherwise, it returns undef The reason
for this baroque procedure is that standard DNS lookups aresusceptible to DNS spoofing in which a remote machine
temporarily assumes the apparent identity of a trusted host.Double-reverse DNS lookups make spoofing much harder and
Trang 47it also provides object methods for dealing correctly with multivaluedentries See Section 9.2.5" later in this chapter for details
my %headers_in = $r->headers_in;
my $headers_in = $r->headers_in;
Once you have copied the headers to a hash, you can refer to them
by name See Table 9.1 for a list of incoming headers that you mayneed to use For example, you can view the length of the data that
For these reasons it's better to call headers_in() in a scalar context and use the returned tied hash Since Apache::Table sits on top of
the C table API, lookup comparisons are performed in a case-insensitive manner The tied interface also allows you to add orchange the value of a header field, in case you want to modify therequest headers seen by handlers downstream This code fragmentshows the tied hash being used to get and set fields: