Show Contents Previous Page Next Page
Chapter 10 - C API Reference Guide, Part I Server Core Routines In this section... Introduction Show Contents Go to Top Previous Page Next Page We now turn to less frequently used calls that are part of the Apache C-language
API. These calls allow you to create custom error handlers, to create and
manipulate subrequests, and to write formatted error messages to the log file.
The Subrequest API and Internal Redirects Show Contents Go to Top Previous Page Next Page The subrequest API can be used to ask Apache "what if" questions. A subrequest
acts just like an ordinary request, except that the response phase is never
actually run. The earlier phases, including the URI translation handler and
the MIME type checker, are run as usual, and you can use their output to do
such things as translating URIs into filenames. A special case of a subrequest is an internal redirect, in which the current
content handler discontinues processing the currently requested URI and tells
Apache to return a different local URI instead. The content handler that eventually
gets run is not necessarily the same as the one that invoked the internal
redirect, although you can arrange for this to happen with ap_internal_redirect_handler().
These routines are declared in the header file http_request.h.
int ap_is_initial_req (request_rec *r)
This function returns a true value if the current request is the initial
one. It will return false for handlers invoked as the result of subrequests
or internal redirects.
if(!ap_is_initial_req(r)) {
return DECLINED;
}
The Perl API provides a method called is_main() which returns true
for initial requests and for requests triggered by internal redirects but
not for subrequests. Although there is no direct equivalent in the C API,
you can get the same information by examining the main field
of the request record. If it is NULL , then the current request
is the main one.
if (r->main != NULL) {
return DECLINED; /* don't handle subrequests */
}
You might wish to declare a macro like the following:
#define is_main(r) (r->main == NULL)
The Perl API also defines a method called last() which returns
the last request in a subrequest chain. This can be useful in logging handlers
for recovering the status code of the last subrequest. A corresponding call
is not defined in the C API but can be easily reproduced by the following
function:
static request_rec *last(request_rec *r)
{
request_rec *last;
for(last=r; last->next != NULL; last=last->next) {
continue;
}
return last;
}
request_rec *ap_sub_req_lookup_uri (const char *uri, const request_rec
*r)
The ap_sub_req_lookup_uri() function creates a subrequest from
the given URI, returning the resulting request record as the function result.
You can then examine the request record to retrieve the URI's filename, MIME
type, or other information. The following example shows how you can use a
subrequest to translate a URI into a physical pathname:
request_rec *subr = ap_sub_req_lookup_uri(uri, r);
char *filename = subr->filename;
request_rec *ap_sub_req_lookup_file (const char *file, const request_rec
*r)
This call behaves similarly to ap_sub_req_lookup_uri(),
except that the first argument is a filename rather than a URI and that
Apache skips the URI translation phase while processing the subrequest.
This example uses a subrequest to fetch the MIME type of the file given
in filename :
request_rec *subr = ap_sub_req_lookup_file(filename, r);
char *mime_type = subr->content_type;
It isn't necessary that the specified file actually exist in order to get
useful information with ap_sub_req_lookup_file(). For example, the
default MIME type lookup operation depends only on the filename suffix, not
on the contents of the file.
void ap_destroy_sub_req (request_rec *r)
When you are through with a subrequest, you should release the memory
occupied by its data structures by passing the subrequest record to ap_destroy_sub_req().
If you forget to do this, the subrequest will be deallocated anyway when
the main transaction is complete.
ap_destroy_sub_req(subr);
int ap_run_sub_req (request_rec *r)
If you have already created a subrequest using ap_sub_req_lookup_uri()
or ap_sub_req_ lookup_file(), you can run its content
handler by calling ap_run_sub_req(). This is sometimes used by
modules that implement server-side include systems in order to incorporate
a CGI script's output into the HTML page. The function will return the status
code of the subrequest's content handler. Here's the definition of a utility function called include_virtual(),
which creates a subrequest, runs it, then destroys it:
static int include_virtual(request_rec *r, char *uri)
{
int status = OK;
request_rec *subr = ap_sub_req_lookup_uri(uri, r);
status = ap_run_sub_req(subr);
ap_destroy_sub_req(subr);
return status;
}
And here's how include_virtual() might be used:
int status = include_virtual("/footers/standard_footer.html", r);
void ap_internal_redirect (const char *new_uri, request_rec *r)
The ap_internal_redirect() method will cause
Apache to create a new request from the indicated URI
and then run it. The effect is for Apache to send the
client a different URI than the one originally requested.
Unlike a formal redirect (in which Apache sends the
browser a 301 or 302 redirect status code), the browser
is not informed that this substitution has taken place.
The content handler for the new URI is not necessarily
the same as the content handler that generated the redirect.
Apache will determine which content handler to run by
examining the new URI's MIME type and applicable configuration
directives, just as if the browser had requested the URI
directly.
ap_internal_redirect("/new/place", r);
After recalling this function, your handler should return
without further processing the request.
void ap_internal_redirect_handler (const char *new_uri, request_rec
*r)
If you wish to redirect to a new URI but continue to
use the current content handler, call ap_internal_redirect_handler()
instead of the previous function.
ap_internal_redirect_handler("/new/place", r);
The Cleanup API Show Contents Go to Top Previous Page Next Page As explained in Chapter 3, cleanup handlers
are code subroutines that Apache invokes after the transaction is finished.
These are usually used by modules to clean up data structures that could not
be allocated from resource pools, such as device drivers and database handles,
but can also be used for other tasks, such as deferring logging until after
the transaction is completed (see Chapter 7 for
a discussion of this technique). Cleanup handlers use a different calling convention than
that used by phase handlers. A cleanup handler takes a single
void* argument and returns no function result.
Its function prototype looks like this:
void cleanup_handler (void *data)
The data argument is provided for your convenience
as a way to pass runtime information to the cleanup handler.
It can be a pointer to any data structure of your choosing,
or NULL if you don't care to pass any information.
As we discuss later, the data argument is specified
when you install the cleanup handler using ap_register_cleanup().
One common trick is to pass a pointer to the current request
record so that the cleanup handler has access to information
about the transaction. In the examples that follow, we use
a cleanup handler that simply prints a message to standard
error indicating that it's been called:
static void my_cleanup(void *data)
{
request_rec *r = (request_rec *)data;
fprintf(stderr, "process %d all done with %s\n", (int)getpid(), r->uri);
}
Apache can accommodate an unlimited number of cleanup
handlers, although few modules will need more than one.
All cleanup functions are declared in the header file alloc.h.
void ap_register_cleanup (pool *p, void *data, void (*plain_cleanup)
(void *),
void (*child_cleanup) (void *))
To install a cleanup handler, call ap_register_cleanup().
It takes four arguments: a pool pointer (usually the one
stored in the request record), a block of module-specific
data to pass to the routine, and two function pointers
to cleanup handlers. The first function pointer is the
one you will usually use. It points to the cleanup handler
to be called when the transaction is terminated. The second
function pointer is only used when your module forks a
child process and you need a routine to perform cleanup
before the child terminates, for example, closing an open
file inherited from the parent process. Since it is highly
unusual for a module to fork, you will ordinarily pass
the "do nothing" routine ap_null_cleanup for
this argument. Always be sure to use ap_null_cleanup
rather than NULL . In the following example, we install my_cleanup()
as the cleanup handler and arrange for it to be passed a
copy of the current request record when it runs:
ap_register_cleanup(r->pool, (void *)r, my_cleanup, ap_null_cleanup);
void ap_kill_cleanup (pool *p, void *data, void (*cleanup)(void *))
Should you need to unregister a cleanup function before
it runs, pass the address of the routine and its data block
to ap_kill_cleanup(). Both the routine and the
data block must match the values passed to ap_register_cleanup()
in order for the removal to take effect.
ap_kill_cleanup(r->pool, (void *)r, my_cleanup);
void ap_run_cleanup (pool *p, void *data, void (*cleanup)(void *))
If you need to run a cleanup immediately, you can do
so by calling this routine. The cleanup will be unregistered
after it is run so that it is not run again during the ordinary
cleanup period. It is unlikely that you will need to use
this function, since it is easy enough to invoke the cleanup
function directly. Show Contents Go to Top Previous Page Next Page Copyright © 1999 by O'Reilly & Associates, Inc. |