|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
|
Packit |
90a5c9 |
<meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type" />
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
Packit |
90a5c9 |
This file is generated from xml source: DO NOT EDIT
|
|
Packit |
90a5c9 |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|
Packit |
90a5c9 |
-->
|
|
Packit |
90a5c9 |
<title>Apache 1.3 API notes - Apache HTTP Server Version 2.4</title>
|
|
Packit |
90a5c9 |
<link href="../style/css/manual.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
|
|
Packit |
90a5c9 |
<link href="../style/css/manual-loose-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
|
|
Packit |
90a5c9 |
<link href="../style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" /><link rel="stylesheet" type="text/css" href="../style/css/prettify.css" />
|
|
Packit |
90a5c9 |
<script src="../style/scripts/prettify.min.js" type="text/javascript">
|
|
Packit |
90a5c9 |
</script>
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
<link href="../images/favicon.ico" rel="shortcut icon" /></head>
|
|
Packit |
90a5c9 |
<body id="manual-page">
|
|
Packit |
90a5c9 |
Modules | Directives | FAQ | Glossary | Sitemap
|
|
Packit |
90a5c9 |
Apache HTTP Server Version 2.4
|
|
Packit |
90a5c9 |
![](../images/feather.png)
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Apache > HTTP Server > Documentation > Version 2.4 > Developer Documentation
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Available Languages: en
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Warning
|
|
Packit |
90a5c9 |
This document has not been updated to take into account changes made
|
|
Packit |
90a5c9 |
in the 2.0 version of the Apache HTTP Server. Some of the information may
|
|
Packit |
90a5c9 |
still be relevant, but please use it with care.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
These are some notes on the Apache API and the data structures you have
|
|
Packit |
90a5c9 |
to deal with, etc. They are not yet nearly complete, but hopefully,
|
|
Packit |
90a5c9 |
they will help you get your bearings. Keep in mind that the API is still
|
|
Packit |
90a5c9 |
subject to change as we gain experience with it. (See the TODO file for
|
|
Packit |
90a5c9 |
what might be coming). However, it will be easy to adapt modules
|
|
Packit |
90a5c9 |
to any changes that are made. (We have more modules to adapt than you
|
|
Packit |
90a5c9 |
do).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
A few notes on general pedagogical style here. In the interest of
|
|
Packit |
90a5c9 |
conciseness, all structure declarations here are incomplete -- the real
|
|
Packit |
90a5c9 |
ones have more slots that I'm not telling you about. For the most part,
|
|
Packit |
90a5c9 |
these are reserved to one component of the server core or another, and
|
|
Packit |
90a5c9 |
should be altered by modules with caution. However, in some cases, they
|
|
Packit |
90a5c9 |
really are things I just haven't gotten around to yet. Welcome to the
|
|
Packit |
90a5c9 |
bleeding edge.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Finally, here's an outline, to give you some bare idea of what's coming
|
|
Packit |
90a5c9 |
up, and in what order:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Basic concepts.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Handlers, Modules, and
|
|
Packit |
90a5c9 |
Requests
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
A brief tour of a
|
|
Packit |
90a5c9 |
module
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
How handlers work
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
A brief tour of the
|
|
Packit |
90a5c9 |
request_rec
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Where request_rec structures come
|
|
Packit |
90a5c9 |
from
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Handling requests, declining,
|
|
Packit |
90a5c9 |
and returning error codes
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Special considerations for
|
|
Packit |
90a5c9 |
response handlers
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Special considerations for
|
|
Packit |
90a5c9 |
authentication handlers
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Special considerations for
|
|
Packit |
90a5c9 |
logging handlers
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Resource allocation and resource
|
|
Packit |
90a5c9 |
pools
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Configuration, commands and the like
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Per-directory configuration
|
|
Packit |
90a5c9 |
structures
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Command handling
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Side notes --- per-server
|
|
Packit |
90a5c9 |
configuration, virtual servers, etc.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
How handlers work
|
|
Packit |
90a5c9 |
Resource allocation and resource pools
|
|
Packit |
90a5c9 |
Configuration, commands and the like
|
|
Packit |
90a5c9 |
See also
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We begin with an overview of the basic concepts behind the API, and how
|
|
Packit |
90a5c9 |
they are manifested in the code.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Apache breaks down request handling into a series of steps, more or
|
|
Packit |
90a5c9 |
less the same way the Netscape server API does (although this API has a
|
|
Packit |
90a5c9 |
few more stages than NetSite does, as hooks for stuff I thought might be
|
|
Packit |
90a5c9 |
useful in the future). These are:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
URI -> Filename translation
|
|
Packit |
90a5c9 |
Auth ID checking [is the user who they say they are?]
|
|
Packit |
90a5c9 |
Auth access checking [is the user authorized here?]
|
|
Packit |
90a5c9 |
Access checking other than auth
|
|
Packit |
90a5c9 |
Determining MIME type of the object requested
|
|
Packit |
90a5c9 |
`Fixups' -- there aren't any of these yet, but the phase is intended
|
|
Packit |
90a5c9 |
as a hook for possible extensions like SetEnv , which don't really fit well elsewhere.
|
|
Packit |
90a5c9 |
Actually sending a response back to the client.
|
|
Packit |
90a5c9 |
Logging the request
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
These phases are handled by looking at each of a succession of
|
|
Packit |
90a5c9 |
modules, looking to see if each of them has a handler for the
|
|
Packit |
90a5c9 |
phase, and attempting invoking it if so. The handler can typically do one
|
|
Packit |
90a5c9 |
of three things:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Handle the request, and indicate that it has done so by
|
|
Packit |
90a5c9 |
returning the magic constant OK .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Decline to handle the request, by returning the magic integer
|
|
Packit |
90a5c9 |
constant DECLINED . In this case, the server behaves in all
|
|
Packit |
90a5c9 |
respects as if the handler simply hadn't been there.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Signal an error, by returning one of the HTTP error codes. This
|
|
Packit |
90a5c9 |
terminates normal handling of the request, although an ErrorDocument may
|
|
Packit |
90a5c9 |
be invoked to try to mop up, and it will be logged in any case.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Most phases are terminated by the first module that handles them;
|
|
Packit |
90a5c9 |
however, for logging, `fixups', and non-access authentication checking,
|
|
Packit |
90a5c9 |
all handlers always run (barring an error). Also, the response phase is
|
|
Packit |
90a5c9 |
unique in that modules may declare multiple handlers for it, via a
|
|
Packit |
90a5c9 |
dispatch table keyed on the MIME type of the requested object. Modules may
|
|
Packit |
90a5c9 |
declare a response-phase handler which can handle any request,
|
|
Packit |
90a5c9 |
by giving it the key */* (i.e., a wildcard MIME type
|
|
Packit |
90a5c9 |
specification). However, wildcard handlers are only invoked if the server
|
|
Packit |
90a5c9 |
has already tried and failed to find a more specific response handler for
|
|
Packit |
90a5c9 |
the MIME type of the requested object (either none existed, or they all
|
|
Packit |
90a5c9 |
declined).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The handlers themselves are functions of one argument (a
|
|
Packit |
90a5c9 |
request_rec structure. vide infra), which returns an integer,
|
|
Packit |
90a5c9 |
as above.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
At this point, we need to explain the structure of a module. Our
|
|
Packit |
90a5c9 |
candidate will be one of the messier ones, the CGI module -- this handles
|
|
Packit |
90a5c9 |
both CGI scripts and the ScriptAlias config file command. It's actually a great deal
|
|
Packit |
90a5c9 |
more complicated than most modules, but if we're going to have only one
|
|
Packit |
90a5c9 |
example, it might as well be the one with its fingers in every place.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Let's begin with handlers. In order to handle the CGI scripts, the
|
|
Packit |
90a5c9 |
module declares a response handler for them. Because of ScriptAlias , it also has handlers for the
|
|
Packit |
90a5c9 |
name translation phase (to recognize ScriptAlias ed URIs), the type-checking phase (any
|
|
Packit |
90a5c9 |
ScriptAlias ed request is typed
|
|
Packit |
90a5c9 |
as a CGI script).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The module needs to maintain some per (virtual) server information,
|
|
Packit |
90a5c9 |
namely, the ScriptAlias es in
|
|
Packit |
90a5c9 |
effect; the module structure therefore contains pointers to a functions
|
|
Packit |
90a5c9 |
which builds these structures, and to another which combines two of them
|
|
Packit |
90a5c9 |
(in case the main server and a virtual server both have ScriptAlias es declared).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Finally, this module contains code to handle the ScriptAlias command itself. This particular
|
|
Packit |
90a5c9 |
module only declares one command, but there could be more, so modules have
|
|
Packit |
90a5c9 |
command tables which declare their commands, and describe where
|
|
Packit |
90a5c9 |
they are permitted, and how they are to be invoked.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
A final note on the declared types of the arguments of some of these
|
|
Packit |
90a5c9 |
commands: a pool is a pointer to a resource pool
|
|
Packit |
90a5c9 |
structure; these are used by the server to keep track of the memory which
|
|
Packit |
90a5c9 |
has been allocated, files opened, etc., either to service a
|
|
Packit |
90a5c9 |
particular request, or to handle the process of configuring itself. That
|
|
Packit |
90a5c9 |
way, when the request is over (or, for the configuration pool, when the
|
|
Packit |
90a5c9 |
server is restarting), the memory can be freed, and the files closed,
|
|
Packit |
90a5c9 |
en masse, without anyone having to write explicit code to track
|
|
Packit |
90a5c9 |
them all down and dispose of them. Also, a cmd_parms
|
|
Packit |
90a5c9 |
structure contains various information about the config file being read,
|
|
Packit |
90a5c9 |
and other status information, which is sometimes of use to the function
|
|
Packit |
90a5c9 |
which processes a config-file command (such as ScriptAlias ). With no further ado, the
|
|
Packit |
90a5c9 |
module itself:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Declarations of handlers. */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int translate_scriptalias (request_rec *);
|
|
Packit |
90a5c9 |
int type_scriptalias (request_rec *);
|
|
Packit |
90a5c9 |
int cgi_handler (request_rec *);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Subsidiary dispatch table for response-phase
|
|
Packit |
90a5c9 |
* handlers, by MIME type */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
handler_rec cgi_handlers[] = {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
{ "application/x-httpd-cgi", cgi_handler },
|
|
Packit |
90a5c9 |
{ NULL }
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Declarations of routines to manipulate the
|
|
Packit |
90a5c9 |
* module's configuration info. Note that these are
|
|
Packit |
90a5c9 |
* returned, and passed in, as void *'s; the server
|
|
Packit |
90a5c9 |
* core keeps track of them, but it doesn't, and can't,
|
|
Packit |
90a5c9 |
* know their internal structure.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
void *make_cgi_server_config (pool *);
|
|
Packit |
90a5c9 |
void *merge_cgi_server_config (pool *, void *, void *);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Declarations of routines to handle config-file commands */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
extern char *script_alias(cmd_parms *, void *per_dir_config, char *fake,
|
|
Packit |
90a5c9 |
char *real);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
command_rec cgi_cmds[] = {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
{ "ScriptAlias", script_alias, NULL, RSRC_CONF, TAKE2,
|
|
Packit |
90a5c9 |
"a fakename and a realname"},
|
|
Packit |
90a5c9 |
{ NULL }
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
module cgi_module = {
|
|
Packit |
90a5c9 |
STANDARD_MODULE_STUFF,
|
|
Packit |
90a5c9 |
NULL, /* initializer */
|
|
Packit |
90a5c9 |
NULL, /* dir config creator */
|
|
Packit |
90a5c9 |
NULL, /* dir merger */
|
|
Packit |
90a5c9 |
make_cgi_server_config, /* server config */
|
|
Packit |
90a5c9 |
merge_cgi_server_config, /* merge server config */
|
|
Packit |
90a5c9 |
cgi_cmds, /* command table */
|
|
Packit |
90a5c9 |
cgi_handlers, /* handlers */
|
|
Packit |
90a5c9 |
translate_scriptalias, /* filename translation */
|
|
Packit |
90a5c9 |
NULL, /* check_user_id */
|
|
Packit |
90a5c9 |
NULL, /* check auth */
|
|
Packit |
90a5c9 |
NULL, /* check access */
|
|
Packit |
90a5c9 |
type_scriptalias, /* type_checker */
|
|
Packit |
90a5c9 |
NULL, /* fixups */
|
|
Packit |
90a5c9 |
NULL, /* logger */
|
|
Packit |
90a5c9 |
NULL /* header parser */
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The sole argument to handlers is a request_rec structure.
|
|
Packit |
90a5c9 |
This structure describes a particular request which has been made to the
|
|
Packit |
90a5c9 |
server, on behalf of a client. In most cases, each connection to the
|
|
Packit |
90a5c9 |
client generates only one request_rec structure.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The request_rec contains pointers to a resource pool
|
|
Packit |
90a5c9 |
which will be cleared when the server is finished handling the request;
|
|
Packit |
90a5c9 |
to structures containing per-server and per-connection information, and
|
|
Packit |
90a5c9 |
most importantly, information on the request itself.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The most important such information is a small set of character strings
|
|
Packit |
90a5c9 |
describing attributes of the object being requested, including its URI,
|
|
Packit |
90a5c9 |
filename, content-type and content-encoding (these being filled in by the
|
|
Packit |
90a5c9 |
translation and type-check handlers which handle the request,
|
|
Packit |
90a5c9 |
respectively).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Other commonly used data items are tables giving the MIME headers on
|
|
Packit |
90a5c9 |
the client's original request, MIME headers to be sent back with the
|
|
Packit |
90a5c9 |
response (which modules can add to at will), and environment variables for
|
|
Packit |
90a5c9 |
any subprocesses which are spawned off in the course of servicing the
|
|
Packit |
90a5c9 |
request. These tables are manipulated using the ap_table_get
|
|
Packit |
90a5c9 |
and ap_table_set routines.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Note that the Content-type header value cannot
|
|
Packit |
90a5c9 |
be set by module content-handlers using the ap_table_*()
|
|
Packit |
90a5c9 |
routines. Rather, it is set by pointing the content_type
|
|
Packit |
90a5c9 |
field in the request_rec structure to an appropriate
|
|
Packit |
90a5c9 |
string. e.g.,
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
r->content_type = "text/html";
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Finally, there are pointers to two data structures which, in turn,
|
|
Packit |
90a5c9 |
point to per-module configuration structures. Specifically, these hold
|
|
Packit |
90a5c9 |
pointers to the data structures which the module has built to describe
|
|
Packit |
90a5c9 |
the way it has been configured to operate in a given directory (via
|
|
Packit |
90a5c9 |
.htaccess files or <Directory> sections), for private data it has built in the
|
|
Packit |
90a5c9 |
course of servicing the request (so modules' handlers for one phase can
|
|
Packit |
90a5c9 |
pass `notes' to their handlers for other phases). There is another such
|
|
Packit |
90a5c9 |
configuration vector in the server_rec data structure pointed
|
|
Packit |
90a5c9 |
to by the request_rec , which contains per (virtual) server
|
|
Packit |
90a5c9 |
configuration data.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Here is an abridged declaration, giving the fields most commonly
|
|
Packit |
90a5c9 |
used:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct request_rec {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
pool *pool;
|
|
Packit |
90a5c9 |
conn_rec *connection;
|
|
Packit |
90a5c9 |
server_rec *server;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* What object is being requested */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
char *uri;
|
|
Packit |
90a5c9 |
char *filename;
|
|
Packit |
90a5c9 |
char *path_info;
|
|
Packit |
90a5c9 |
char *args; /* QUERY_ARGS, if any */
|
|
Packit |
90a5c9 |
struct stat finfo; /* Set by server core;
|
|
Packit |
90a5c9 |
* st_mode set to zero if no such file */
|
|
Packit |
90a5c9 |
char *content_type;
|
|
Packit |
90a5c9 |
char *content_encoding;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* MIME header environments, in and out. Also,
|
|
Packit |
90a5c9 |
* an array containing environment variables to
|
|
Packit |
90a5c9 |
* be passed to subprocesses, so people can write
|
|
Packit |
90a5c9 |
* modules to add to that environment.
|
|
Packit |
90a5c9 |
*
|
|
Packit |
90a5c9 |
* The difference between headers_out and
|
|
Packit |
90a5c9 |
* err_headers_out is that the latter are printed
|
|
Packit |
90a5c9 |
* even on error, and persist across internal
|
|
Packit |
90a5c9 |
* redirects (so the headers printed for
|
|
Packit |
90a5c9 |
* ErrorDocument handlers will have
|
|
Packit |
90a5c9 |
them).
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
table *headers_in;
|
|
Packit |
90a5c9 |
table *headers_out;
|
|
Packit |
90a5c9 |
table *err_headers_out;
|
|
Packit |
90a5c9 |
table *subprocess_env;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Info about the request itself... */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int header_only; /* HEAD request, as opposed to GET */
|
|
Packit |
90a5c9 |
char *protocol; /* Protocol, as given to us, or HTTP/0.9 */
|
|
Packit |
90a5c9 |
char *method; /* GET, HEAD, POST, etc. */
|
|
Packit |
90a5c9 |
int method_number; /* M_GET, M_POST, etc. */
|
|
Packit |
90a5c9 |
/* Info for logging */
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
char *the_request;
|
|
Packit |
90a5c9 |
int bytes_sent;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* A flag which modules can set, to indicate that
|
|
Packit |
90a5c9 |
* the data being returned is volatile, and clients
|
|
Packit |
90a5c9 |
* should be told not to cache it.
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int no_cache;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* Various other config info which may change
|
|
Packit |
90a5c9 |
* with .htaccess files
|
|
Packit |
90a5c9 |
* These are config vectors, with one void*
|
|
Packit |
90a5c9 |
* pointer for each module (the thing pointed
|
|
Packit |
90a5c9 |
* to being the module's business).
|
|
Packit |
90a5c9 |
*/
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
void *per_dir_config; /* Options set in config files, etc. */
|
|
Packit |
90a5c9 |
void *request_config; /* Notes on *this* request */
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Most request_rec structures are built by reading an HTTP
|
|
Packit |
90a5c9 |
request from a client, and filling in the fields. However, there are a
|
|
Packit |
90a5c9 |
few exceptions:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
If the request is to an imagemap, a type map (i.e., a
|
|
Packit |
90a5c9 |
*.var file), or a CGI script which returned a local
|
|
Packit |
90a5c9 |
`Location:', then the resource which the user requested is going to be
|
|
Packit |
90a5c9 |
ultimately located by some URI other than what the client originally
|
|
Packit |
90a5c9 |
supplied. In this case, the server does an internal redirect,
|
|
Packit |
90a5c9 |
constructing a new request_rec for the new URI, and
|
|
Packit |
90a5c9 |
processing it almost exactly as if the client had requested the new URI
|
|
Packit |
90a5c9 |
directly.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
If some handler signaled an error, and an ErrorDocument
|
|
Packit |
90a5c9 |
is in scope, the same internal redirect machinery comes into play.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Finally, a handler occasionally needs to investigate `what would
|
|
Packit |
90a5c9 |
happen if' some other request were run. For instance, the directory
|
|
Packit |
90a5c9 |
indexing module needs to know what MIME type would be assigned to a
|
|
Packit |
90a5c9 |
request for each directory entry, in order to figure out what icon to
|
|
Packit |
90a5c9 |
use.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Such handlers can construct a sub-request, using the
|
|
Packit |
90a5c9 |
functions ap_sub_req_lookup_file ,
|
|
Packit |
90a5c9 |
ap_sub_req_lookup_uri , and ap_sub_req_method_uri ;
|
|
Packit |
90a5c9 |
these construct a new request_rec structure and processes it
|
|
Packit |
90a5c9 |
as you would expect, up to but not including the point of actually sending
|
|
Packit |
90a5c9 |
a response. (These functions skip over the access checks if the
|
|
Packit |
90a5c9 |
sub-request is for a file in the same directory as the original
|
|
Packit |
90a5c9 |
request).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(Server-side includes work by building sub-requests and then actually
|
|
Packit |
90a5c9 |
invoking the response handler for them, via the function
|
|
Packit |
90a5c9 |
ap_run_sub_req ).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
error codes
|
|
Packit |
90a5c9 |
As discussed above, each handler, when invoked to handle a particular
|
|
Packit |
90a5c9 |
request_rec , has to return an int to indicate
|
|
Packit |
90a5c9 |
what happened. That can either be
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
OK -- the request was handled successfully. This may or
|
|
Packit |
90a5c9 |
may not terminate the phase.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
DECLINED -- no erroneous condition exists, but the module
|
|
Packit |
90a5c9 |
declines to handle the phase; the server tries to find another.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
an HTTP error code, which aborts handling of the request.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Note that if the error code returned is REDIRECT , then
|
|
Packit |
90a5c9 |
the module should put a Location in the request's
|
|
Packit |
90a5c9 |
headers_out , to indicate where the client should be
|
|
Packit |
90a5c9 |
redirected to.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
handlers
|
|
Packit |
90a5c9 |
Handlers for most phases do their work by simply setting a few fields
|
|
Packit |
90a5c9 |
in the request_rec structure (or, in the case of access
|
|
Packit |
90a5c9 |
checkers, simply by returning the correct error code). However, response
|
|
Packit |
90a5c9 |
handlers have to actually send a request back to the client.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
They should begin by sending an HTTP response header, using the
|
|
Packit |
90a5c9 |
function ap_send_http_header . (You don't have to do anything
|
|
Packit |
90a5c9 |
special to skip sending the header for HTTP/0.9 requests; the function
|
|
Packit |
90a5c9 |
figures out on its own that it shouldn't do anything). If the request is
|
|
Packit |
90a5c9 |
marked header_only , that's all they should do; they should
|
|
Packit |
90a5c9 |
return after that, without attempting any further output.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Otherwise, they should produce a request body which responds to the
|
|
Packit |
90a5c9 |
client as appropriate. The primitives for this are ap_rputc
|
|
Packit |
90a5c9 |
and ap_rprintf , for internally generated output, and
|
|
Packit |
90a5c9 |
ap_send_fd , to copy the contents of some FILE *
|
|
Packit |
90a5c9 |
straight to the client.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
At this point, you should more or less understand the following piece
|
|
Packit |
90a5c9 |
of code, which is the handler which handles GET requests
|
|
Packit |
90a5c9 |
which have no more specific handler; it also shows how conditional
|
|
Packit |
90a5c9 |
GET s can be handled, if it's desirable to do so in a
|
|
Packit |
90a5c9 |
particular response handler -- ap_set_last_modified checks
|
|
Packit |
90a5c9 |
against the If-modified-since value supplied by the client,
|
|
Packit |
90a5c9 |
if any, and returns an appropriate code (which will, if nonzero, be
|
|
Packit |
90a5c9 |
USE_LOCAL_COPY). No similar considerations apply for
|
|
Packit |
90a5c9 |
ap_set_content_length , but it returns an error code for
|
|
Packit |
90a5c9 |
symmetry.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int default_handler (request_rec *r)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int errstatus;
|
|
Packit |
90a5c9 |
FILE *f;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (r->method_number != M_GET) return DECLINED;
|
|
Packit |
90a5c9 |
if (r->finfo.st_mode == 0) return NOT_FOUND;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((errstatus = ap_set_content_length (r, r->finfo.st_size))
|
|
Packit |
90a5c9 |
||
|
|
Packit |
90a5c9 |
(errstatus = ap_set_last_modified (r, r->finfo.st_mtime)))
|
|
Packit |
90a5c9 |
return errstatus;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
f = fopen (r->filename, "r");
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (f == NULL) {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
log_reason("file permissions deny server access", r->filename, r);
|
|
Packit |
90a5c9 |
return FORBIDDEN;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
register_timeout ("send", r);
|
|
Packit |
90a5c9 |
ap_send_http_header (r);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!r->header_only) send_fd (f, r);
|
|
Packit |
90a5c9 |
ap_pfclose (r->pool, f);
|
|
Packit |
90a5c9 |
return OK;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Finally, if all of this is too much of a challenge, there are a few
|
|
Packit |
90a5c9 |
ways out of it. First off, as shown above, a response handler which has
|
|
Packit |
90a5c9 |
not yet produced any output can simply return an error code, in which
|
|
Packit |
90a5c9 |
case the server will automatically produce an error response. Secondly,
|
|
Packit |
90a5c9 |
it can punt to some other handler by invoking
|
|
Packit |
90a5c9 |
ap_internal_redirect , which is how the internal redirection
|
|
Packit |
90a5c9 |
machinery discussed above is invoked. A response handler which has
|
|
Packit |
90a5c9 |
internally redirected should always return OK .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(Invoking ap_internal_redirect from handlers which are
|
|
Packit |
90a5c9 |
not response handlers will lead to serious confusion).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
handlers
|
|
Packit |
90a5c9 |
Stuff that should be discussed here in detail:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Authentication-phase handlers not invoked unless auth is
|
|
Packit |
90a5c9 |
configured for the directory.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Common auth configuration stored in the core per-dir
|
|
Packit |
90a5c9 |
configuration; it has accessors ap_auth_type ,
|
|
Packit |
90a5c9 |
ap_auth_name , and ap_requires .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Common routines, to handle the protocol end of things, at
|
|
Packit |
90a5c9 |
least for HTTP basic authentication
|
|
Packit |
90a5c9 |
(ap_get_basic_auth_pw , which sets the
|
|
Packit |
90a5c9 |
connection->user structure field
|
|
Packit |
90a5c9 |
automatically, and ap_note_basic_auth_failure ,
|
|
Packit |
90a5c9 |
which arranges for the proper WWW-Authenticate:
|
|
Packit |
90a5c9 |
header to be sent back).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
handlers
|
|
Packit |
90a5c9 |
When a request has internally redirected, there is the question of
|
|
Packit |
90a5c9 |
what to log. Apache handles this by bundling the entire chain of redirects
|
|
Packit |
90a5c9 |
into a list of request_rec structures which are threaded
|
|
Packit |
90a5c9 |
through the r->prev and r->next pointers.
|
|
Packit |
90a5c9 |
The request_rec which is passed to the logging handlers in
|
|
Packit |
90a5c9 |
such cases is the one which was originally built for the initial request
|
|
Packit |
90a5c9 |
from the client; note that the bytes_sent field will only be
|
|
Packit |
90a5c9 |
correct in the last request in the chain (the one for which a response was
|
|
Packit |
90a5c9 |
actually sent).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
One of the problems of writing and designing a server-pool server is
|
|
Packit |
90a5c9 |
that of preventing leakage, that is, allocating resources (memory, open
|
|
Packit |
90a5c9 |
files, etc.), without subsequently releasing them. The resource
|
|
Packit |
90a5c9 |
pool machinery is designed to make it easy to prevent this from happening,
|
|
Packit |
90a5c9 |
by allowing resource to be allocated in such a way that they are
|
|
Packit |
90a5c9 |
automatically released when the server is done with them.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The way this works is as follows: the memory which is allocated, file
|
|
Packit |
90a5c9 |
opened, etc., to deal with a particular request are tied to a
|
|
Packit |
90a5c9 |
resource pool which is allocated for the request. The pool is a
|
|
Packit |
90a5c9 |
data structure which itself tracks the resources in question.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
When the request has been processed, the pool is cleared. At
|
|
Packit |
90a5c9 |
that point, all the memory associated with it is released for reuse, all
|
|
Packit |
90a5c9 |
files associated with it are closed, and any other clean-up functions which
|
|
Packit |
90a5c9 |
are associated with the pool are run. When this is over, we can be confident
|
|
Packit |
90a5c9 |
that all the resource tied to the pool have been released, and that none of
|
|
Packit |
90a5c9 |
them have leaked.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Server restarts, and allocation of memory and resources for per-server
|
|
Packit |
90a5c9 |
configuration, are handled in a similar way. There is a configuration
|
|
Packit |
90a5c9 |
pool, which keeps track of resources which were allocated while reading
|
|
Packit |
90a5c9 |
the server configuration files, and handling the commands therein (for
|
|
Packit |
90a5c9 |
instance, the memory that was allocated for per-server module configuration,
|
|
Packit |
90a5c9 |
log files and other files that were opened, and so forth). When the server
|
|
Packit |
90a5c9 |
restarts, and has to reread the configuration files, the configuration pool
|
|
Packit |
90a5c9 |
is cleared, and so the memory and file descriptors which were taken up by
|
|
Packit |
90a5c9 |
reading them the last time are made available for reuse.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
It should be noted that use of the pool machinery isn't generally
|
|
Packit |
90a5c9 |
obligatory, except for situations like logging handlers, where you really
|
|
Packit |
90a5c9 |
need to register cleanups to make sure that the log file gets closed when
|
|
Packit |
90a5c9 |
the server restarts (this is most easily done by using the function ap_pfopen , which also arranges for the
|
|
Packit |
90a5c9 |
underlying file descriptor to be closed before any child processes, such as
|
|
Packit |
90a5c9 |
for CGI scripts, are exec ed), or in case you are using the
|
|
Packit |
90a5c9 |
timeout machinery (which isn't yet even documented here). However, there are
|
|
Packit |
90a5c9 |
two benefits to using it: resources allocated to a pool never leak (even if
|
|
Packit |
90a5c9 |
you allocate a scratch string, and just forget about it); also, for memory
|
|
Packit |
90a5c9 |
allocation, ap_palloc is generally faster than
|
|
Packit |
90a5c9 |
malloc .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
We begin here by describing how memory is allocated to pools, and then
|
|
Packit |
90a5c9 |
discuss how other resources are tracked by the resource pool machinery.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Allocation of memory in pools
|
|
Packit |
90a5c9 |
Memory is allocated to pools by calling the function
|
|
Packit |
90a5c9 |
ap_palloc , which takes two arguments, one being a pointer to
|
|
Packit |
90a5c9 |
a resource pool structure, and the other being the amount of memory to
|
|
Packit |
90a5c9 |
allocate (in char s). Within handlers for handling requests,
|
|
Packit |
90a5c9 |
the most common way of getting a resource pool structure is by looking at
|
|
Packit |
90a5c9 |
the pool slot of the relevant request_rec ; hence
|
|
Packit |
90a5c9 |
the repeated appearance of the following idiom in module code:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int my_handler(request_rec *r)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
struct my_structure *foo;
|
|
Packit |
90a5c9 |
...
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
foo = (foo *)ap_palloc (r->pool, sizeof(my_structure));
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Note that there is no ap_pfree --
|
|
Packit |
90a5c9 |
ap_palloc ed memory is freed only when the associated resource
|
|
Packit |
90a5c9 |
pool is cleared. This means that ap_palloc does not have to
|
|
Packit |
90a5c9 |
do as much accounting as malloc() ; all it does in the typical
|
|
Packit |
90a5c9 |
case is to round up the size, bump a pointer, and do a range check.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(It also raises the possibility that heavy use of
|
|
Packit |
90a5c9 |
ap_palloc could cause a server process to grow excessively
|
|
Packit |
90a5c9 |
large. There are two ways to deal with this, which are dealt with below;
|
|
Packit |
90a5c9 |
briefly, you can use malloc , and try to be sure that all of
|
|
Packit |
90a5c9 |
the memory gets explicitly free d, or you can allocate a
|
|
Packit |
90a5c9 |
sub-pool of the main pool, allocate your memory in the sub-pool, and clear
|
|
Packit |
90a5c9 |
it out periodically. The latter technique is discussed in the section
|
|
Packit |
90a5c9 |
on sub-pools below, and is used in the directory-indexing code, in order
|
|
Packit |
90a5c9 |
to avoid excessive storage allocation when listing directories with
|
|
Packit |
90a5c9 |
thousands of files).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Allocating initialized memory
|
|
Packit |
90a5c9 |
There are functions which allocate initialized memory, and are
|
|
Packit |
90a5c9 |
frequently useful. The function ap_pcalloc has the same
|
|
Packit |
90a5c9 |
interface as ap_palloc , but clears out the memory it
|
|
Packit |
90a5c9 |
allocates before it returns it. The function ap_pstrdup
|
|
Packit |
90a5c9 |
takes a resource pool and a char * as arguments, and
|
|
Packit |
90a5c9 |
allocates memory for a copy of the string the pointer points to, returning
|
|
Packit |
90a5c9 |
a pointer to the copy. Finally ap_pstrcat is a varargs-style
|
|
Packit |
90a5c9 |
function, which takes a pointer to a resource pool, and at least two
|
|
Packit |
90a5c9 |
char * arguments, the last of which must be
|
|
Packit |
90a5c9 |
NULL . It allocates enough memory to fit copies of each of
|
|
Packit |
90a5c9 |
the strings, as a unit; for instance:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_pstrcat (r->pool, "foo", "/", "bar", NULL);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
returns a pointer to 8 bytes worth of memory, initialized to
|
|
Packit |
90a5c9 |
"foo/bar" .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
server
|
|
Packit |
90a5c9 |
A pool is really defined by its lifetime more than anything else.
|
|
Packit |
90a5c9 |
There are some static pools in http_main which are passed to various
|
|
Packit |
90a5c9 |
non-http_main functions as arguments at opportune times. Here they
|
|
Packit |
90a5c9 |
are:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
permanent_pool
|
|
Packit |
90a5c9 |
never passed to anything else, this is the ancestor of all pools
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
pconf
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
subpool of permanent_pool
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
created at the beginning of a config "cycle"; exists
|
|
Packit |
90a5c9 |
until the server is terminated or restarts; passed to all
|
|
Packit |
90a5c9 |
config-time routines, either via cmd->pool, or as the
|
|
Packit |
90a5c9 |
"pool *p" argument on those which don't take pools
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
passed to the module init() functions
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ptemp
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
sorry I lie, this pool isn't called this currently in
|
|
Packit |
90a5c9 |
1.3, I renamed it this in my pthreads development. I'm
|
|
Packit |
90a5c9 |
referring to the use of ptrans in the parent... contrast
|
|
Packit |
90a5c9 |
this with the later definition of ptrans in the
|
|
Packit |
90a5c9 |
child.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
subpool of permanent_pool
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
created at the beginning of a config "cycle"; exists
|
|
Packit |
90a5c9 |
until the end of config parsing; passed to config-time
|
|
Packit |
90a5c9 |
routines via cmd->temp_pool. Somewhat of a
|
|
Packit |
90a5c9 |
"bastard child" because it isn't available everywhere.
|
|
Packit |
90a5c9 |
Used for temporary scratch space which may be needed by
|
|
Packit |
90a5c9 |
some config routines but which is deleted at the end of
|
|
Packit |
90a5c9 |
config.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
pchild
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
subpool of permanent_pool
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
created when a child is spawned (or a thread is
|
|
Packit |
90a5c9 |
created); lives until that child (thread) is
|
|
Packit |
90a5c9 |
destroyed
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
passed to the module child_init functions
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
destruction happens right after the child_exit
|
|
Packit |
90a5c9 |
functions are called... (which may explain why I think
|
|
Packit |
90a5c9 |
child_exit is redundant and unneeded)
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ptrans
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
should be a subpool of pchild, but currently is a
|
|
Packit |
90a5c9 |
subpool of permanent_pool, see above
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
cleared by the child before going into the accept()
|
|
Packit |
90a5c9 |
loop to receive a connection
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
used as connection->pool
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
r->pool
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
for the main request this is a subpool of
|
|
Packit |
90a5c9 |
connection->pool; for subrequests it is a subpool of
|
|
Packit |
90a5c9 |
the parent request's pool.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
exists until the end of the request (i.e.,
|
|
Packit |
90a5c9 |
ap_destroy_sub_req, or in child_main after
|
|
Packit |
90a5c9 |
process_request has finished)
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
note that r itself is allocated from r->pool;
|
|
Packit |
90a5c9 |
i.e., r->pool is first created and then r is
|
|
Packit |
90a5c9 |
the first thing palloc()d from it
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
For almost everything folks do, r->pool is the pool to
|
|
Packit |
90a5c9 |
use. But you can see how other lifetimes, such as pchild, are useful to
|
|
Packit |
90a5c9 |
some modules... such as modules that need to open a database connection
|
|
Packit |
90a5c9 |
once per child, and wish to clean it up when the child dies.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
You can also see how some bugs have manifested themself, such as
|
|
Packit |
90a5c9 |
setting connection->user to a value from
|
|
Packit |
90a5c9 |
r->pool -- in this case connection exists for the
|
|
Packit |
90a5c9 |
lifetime of ptrans , which is longer than
|
|
Packit |
90a5c9 |
r->pool (especially if r->pool is a
|
|
Packit |
90a5c9 |
subrequest!). So the correct thing to do is to allocate from
|
|
Packit |
90a5c9 |
connection->pool .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
And there was another interesting bug in mod_include
|
|
Packit |
90a5c9 |
/ mod_cgi . You'll see in those that they do this test
|
|
Packit |
90a5c9 |
to decide if they should use r->pool or
|
|
Packit |
90a5c9 |
r->main->pool . In this case the resource that they are
|
|
Packit |
90a5c9 |
registering for cleanup is a child process. If it were registered in
|
|
Packit |
90a5c9 |
r->pool , then the code would wait() for the
|
|
Packit |
90a5c9 |
child when the subrequest finishes. With mod_include this
|
|
Packit |
90a5c9 |
could be any old #include , and the delay can be up to 3
|
|
Packit |
90a5c9 |
seconds... and happened quite frequently. Instead the subprocess is
|
|
Packit |
90a5c9 |
registered in r->main->pool which causes it to be
|
|
Packit |
90a5c9 |
cleaned up when the entire request is done -- i.e., after the
|
|
Packit |
90a5c9 |
output has been sent to the client and logging has happened.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
As indicated above, resource pools are also used to track other sorts
|
|
Packit |
90a5c9 |
of resources besides memory. The most common are open files. The routine
|
|
Packit |
90a5c9 |
which is typically used for this is ap_pfopen , which takes a
|
|
Packit |
90a5c9 |
resource pool and two strings as arguments; the strings are the same as
|
|
Packit |
90a5c9 |
the typical arguments to fopen , e.g.,
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
...
|
|
Packit |
90a5c9 |
FILE *f = ap_pfopen (r->pool, r->filename, "r");
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (f == NULL) { ... } else { ... }
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
There is also a ap_popenf routine, which parallels the
|
|
Packit |
90a5c9 |
lower-level open system call. Both of these routines arrange
|
|
Packit |
90a5c9 |
for the file to be closed when the resource pool in question is
|
|
Packit |
90a5c9 |
cleared.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Unlike the case for memory, there are functions to close files
|
|
Packit |
90a5c9 |
allocated with ap_pfopen , and ap_popenf , namely
|
|
Packit |
90a5c9 |
ap_pfclose and ap_pclosef . (This is because, on
|
|
Packit |
90a5c9 |
many systems, the number of files which a single process can have open is
|
|
Packit |
90a5c9 |
quite limited). It is important to use these functions to close files
|
|
Packit |
90a5c9 |
allocated with ap_pfopen and ap_popenf , since to
|
|
Packit |
90a5c9 |
do otherwise could cause fatal errors on systems such as Linux, which
|
|
Packit |
90a5c9 |
react badly if the same FILE* is closed more than once.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(Using the close functions is not mandatory, since the
|
|
Packit |
90a5c9 |
file will eventually be closed regardless, but you should consider it in
|
|
Packit |
90a5c9 |
cases where your module is opening, or could open, a lot of files).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Other sorts of resources -- cleanup functions
|
|
Packit |
90a5c9 |
More text goes here. Describe the cleanup primitives in terms of
|
|
Packit |
90a5c9 |
which the file stuff is implemented; also, spawn_process .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Pool cleanups live until clear_pool() is called:
|
|
Packit |
90a5c9 |
clear_pool(a) recursively calls destroy_pool()
|
|
Packit |
90a5c9 |
on all subpools of a ; then calls all the cleanups for
|
|
Packit |
90a5c9 |
a ; then releases all the memory for a .
|
|
Packit |
90a5c9 |
destroy_pool(a) calls clear_pool(a) and then
|
|
Packit |
90a5c9 |
releases the pool structure itself. i.e.,
|
|
Packit |
90a5c9 |
clear_pool(a) doesn't delete a , it just frees
|
|
Packit |
90a5c9 |
up all the resources and you can start using it again immediately.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Fine control -- creating and dealing with sub-pools, with
|
|
Packit |
90a5c9 |
a note on sub-requests
|
|
Packit |
90a5c9 |
On rare occasions, too-free use of ap_palloc() and the
|
|
Packit |
90a5c9 |
associated primitives may result in undesirably profligate resource
|
|
Packit |
90a5c9 |
allocation. You can deal with such a case by creating a sub-pool,
|
|
Packit |
90a5c9 |
allocating within the sub-pool rather than the main pool, and clearing or
|
|
Packit |
90a5c9 |
destroying the sub-pool, which releases the resources which were
|
|
Packit |
90a5c9 |
associated with it. (This really is a rare situation; the only
|
|
Packit |
90a5c9 |
case in which it comes up in the standard module set is in case of listing
|
|
Packit |
90a5c9 |
directories, and then only with very large directories.
|
|
Packit |
90a5c9 |
Unnecessary use of the primitives discussed here can hair up your code
|
|
Packit |
90a5c9 |
quite a bit, with very little gain).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The primitive for creating a sub-pool is ap_make_sub_pool ,
|
|
Packit |
90a5c9 |
which takes another pool (the parent pool) as an argument. When the main
|
|
Packit |
90a5c9 |
pool is cleared, the sub-pool will be destroyed. The sub-pool may also be
|
|
Packit |
90a5c9 |
cleared or destroyed at any time, by calling the functions
|
|
Packit |
90a5c9 |
ap_clear_pool and ap_destroy_pool , respectively.
|
|
Packit |
90a5c9 |
(The difference is that ap_clear_pool frees resources
|
|
Packit |
90a5c9 |
associated with the pool, while ap_destroy_pool also
|
|
Packit |
90a5c9 |
deallocates the pool itself. In the former case, you can allocate new
|
|
Packit |
90a5c9 |
resources within the pool, and clear it again, and so forth; in the
|
|
Packit |
90a5c9 |
latter case, it is simply gone).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
One final note -- sub-requests have their own resource pools, which are
|
|
Packit |
90a5c9 |
sub-pools of the resource pool for the main request. The polite way to
|
|
Packit |
90a5c9 |
reclaim the resources associated with a sub request which you have
|
|
Packit |
90a5c9 |
allocated (using the ap_sub_req_... functions) is
|
|
Packit |
90a5c9 |
ap_destroy_sub_req , which frees the resource pool. Before
|
|
Packit |
90a5c9 |
calling this function, be sure to copy anything that you care about which
|
|
Packit |
90a5c9 |
might be allocated in the sub-request's resource pool into someplace a
|
|
Packit |
90a5c9 |
little less volatile (for instance, the filename in its
|
|
Packit |
90a5c9 |
request_rec structure).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(Again, under most circumstances, you shouldn't feel obliged to call
|
|
Packit |
90a5c9 |
this function; only 2K of memory or so are allocated for a typical sub
|
|
Packit |
90a5c9 |
request, and it will be freed anyway when the main request pool is
|
|
Packit |
90a5c9 |
cleared. It is only when you are allocating many, many sub-requests for a
|
|
Packit |
90a5c9 |
single main request that you should seriously consider the
|
|
Packit |
90a5c9 |
ap_destroy_... functions).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
One of the design goals for this server was to maintain external
|
|
Packit |
90a5c9 |
compatibility with the NCSA 1.3 server --- that is, to read the same
|
|
Packit |
90a5c9 |
configuration files, to process all the directives therein correctly, and
|
|
Packit |
90a5c9 |
in general to be a drop-in replacement for NCSA. On the other hand, another
|
|
Packit |
90a5c9 |
design goal was to move as much of the server's functionality into modules
|
|
Packit |
90a5c9 |
which have as little as possible to do with the monolithic server core. The
|
|
Packit |
90a5c9 |
only way to reconcile these goals is to move the handling of most commands
|
|
Packit |
90a5c9 |
from the central server into the modules.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
However, just giving the modules command tables is not enough to divorce
|
|
Packit |
90a5c9 |
them completely from the server core. The server has to remember the
|
|
Packit |
90a5c9 |
commands in order to act on them later. That involves maintaining data which
|
|
Packit |
90a5c9 |
is private to the modules, and which can be either per-server, or
|
|
Packit |
90a5c9 |
per-directory. Most things are per-directory, including in particular access
|
|
Packit |
90a5c9 |
control and authorization information, but also information on how to
|
|
Packit |
90a5c9 |
determine file types from suffixes, which can be modified by
|
|
Packit |
90a5c9 |
AddType and ForceType directives, and so forth. In general,
|
|
Packit |
90a5c9 |
the governing philosophy is that anything which can be made
|
|
Packit |
90a5c9 |
configurable by directory should be; per-server information is generally
|
|
Packit |
90a5c9 |
used in the standard set of modules for information like
|
|
Packit |
90a5c9 |
Alias es and Redirect s which come into play before the
|
|
Packit |
90a5c9 |
request is tied to a particular place in the underlying file system.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Another requirement for emulating the NCSA server is being able to handle
|
|
Packit |
90a5c9 |
the per-directory configuration files, generally called
|
|
Packit |
90a5c9 |
.htaccess files, though even in the NCSA server they can
|
|
Packit |
90a5c9 |
contain directives which have nothing at all to do with access control.
|
|
Packit |
90a5c9 |
Accordingly, after URI -> filename translation, but before performing any
|
|
Packit |
90a5c9 |
other phase, the server walks down the directory hierarchy of the underlying
|
|
Packit |
90a5c9 |
filesystem, following the translated pathname, to read any
|
|
Packit |
90a5c9 |
.htaccess files which might be present. The information which
|
|
Packit |
90a5c9 |
is read in then has to be merged with the applicable information
|
|
Packit |
90a5c9 |
from the server's own config files (either from the <Directory> sections in
|
|
Packit |
90a5c9 |
access.conf , or from defaults in srm.conf , which
|
|
Packit |
90a5c9 |
actually behaves for most purposes almost exactly like <Directory
|
|
Packit |
90a5c9 |
/>).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Finally, after having served a request which involved reading
|
|
Packit |
90a5c9 |
.htaccess files, we need to discard the storage allocated for
|
|
Packit |
90a5c9 |
handling them. That is solved the same way it is solved wherever else
|
|
Packit |
90a5c9 |
similar problems come up, by tying those structures to the per-transaction
|
|
Packit |
90a5c9 |
resource pool.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Let's look out how all of this plays out in mod_mime.c ,
|
|
Packit |
90a5c9 |
which defines the file typing handler which emulates the NCSA server's
|
|
Packit |
90a5c9 |
behavior of determining file types from suffixes. What we'll be looking
|
|
Packit |
90a5c9 |
at, here, is the code which implements the AddType and AddEncoding commands. These commands can appear in
|
|
Packit |
90a5c9 |
.htaccess files, so they must be handled in the module's
|
|
Packit |
90a5c9 |
private per-directory data, which in fact, consists of two separate
|
|
Packit |
90a5c9 |
tables for MIME types and encoding information, and is declared as
|
|
Packit |
90a5c9 |
follows:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
table *forced_types; /* Additional AddTyped stuff */
|
|
Packit |
90a5c9 |
table *encoding_types; /* Added with AddEncoding... */
|
|
Packit |
90a5c9 |
} mime_dir_config;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
When the server is reading a configuration file, or <Directory> section, which includes
|
|
Packit |
90a5c9 |
one of the MIME module's commands, it needs to create a
|
|
Packit |
90a5c9 |
mime_dir_config structure, so those commands have something
|
|
Packit |
90a5c9 |
to act on. It does this by invoking the function it finds in the module's
|
|
Packit |
90a5c9 |
`create per-dir config slot', with two arguments: the name of the
|
|
Packit |
90a5c9 |
directory to which this configuration information applies (or
|
|
Packit |
90a5c9 |
NULL for srm.conf ), and a pointer to a
|
|
Packit |
90a5c9 |
resource pool in which the allocation should happen.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(If we are reading a .htaccess file, that resource pool
|
|
Packit |
90a5c9 |
is the per-request resource pool for the request; otherwise it is a
|
|
Packit |
90a5c9 |
resource pool which is used for configuration data, and cleared on
|
|
Packit |
90a5c9 |
restarts. Either way, it is important for the structure being created to
|
|
Packit |
90a5c9 |
vanish when the pool is cleared, by registering a cleanup on the pool if
|
|
Packit |
90a5c9 |
necessary).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
For the MIME module, the per-dir config creation function just
|
|
Packit |
90a5c9 |
ap_palloc s the structure above, and a creates a couple of
|
|
Packit |
90a5c9 |
tables to fill it. That looks like this:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
void *create_mime_dir_config (pool *p, char *dummy)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
mime_dir_config *new =
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(mime_dir_config *) ap_palloc (p, sizeof(mime_dir_config));
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
new->forced_types = ap_make_table (p, 4);
|
|
Packit |
90a5c9 |
new->encoding_types = ap_make_table (p, 4);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return new;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Now, suppose we've just read in a .htaccess file. We
|
|
Packit |
90a5c9 |
already have the per-directory configuration structure for the next
|
|
Packit |
90a5c9 |
directory up in the hierarchy. If the .htaccess file we just
|
|
Packit |
90a5c9 |
read in didn't have any AddType
|
|
Packit |
90a5c9 |
or AddEncoding commands, its
|
|
Packit |
90a5c9 |
per-directory config structure for the MIME module is still valid, and we
|
|
Packit |
90a5c9 |
can just use it. Otherwise, we need to merge the two structures
|
|
Packit |
90a5c9 |
somehow.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
To do that, the server invokes the module's per-directory config merge
|
|
Packit |
90a5c9 |
function, if one is present. That function takes three arguments: the two
|
|
Packit |
90a5c9 |
structures being merged, and a resource pool in which to allocate the
|
|
Packit |
90a5c9 |
result. For the MIME module, all that needs to be done is overlay the
|
|
Packit |
90a5c9 |
tables from the new per-directory config structure with those from the
|
|
Packit |
90a5c9 |
parent:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
void *merge_mime_dir_configs (pool *p, void *parent_dirv, void *subdirv)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
mime_dir_config *parent_dir = (mime_dir_config *)parent_dirv;
|
|
Packit |
90a5c9 |
mime_dir_config *subdir = (mime_dir_config *)subdirv;
|
|
Packit |
90a5c9 |
mime_dir_config *new =
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
(mime_dir_config *)ap_palloc (p, sizeof(mime_dir_config));
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
new->forced_types = ap_overlay_tables (p, subdir->forced_types,
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
parent_dir->forced_types);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
new->encoding_types = ap_overlay_tables (p, subdir->encoding_types,
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
parent_dir->encoding_types);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return new;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
As a note -- if there is no per-directory merge function present, the
|
|
Packit |
90a5c9 |
server will just use the subdirectory's configuration info, and ignore
|
|
Packit |
90a5c9 |
the parent's. For some modules, that works just fine (e.g., for
|
|
Packit |
90a5c9 |
the includes module, whose per-directory configuration information
|
|
Packit |
90a5c9 |
consists solely of the state of the XBITHACK ), and for those
|
|
Packit |
90a5c9 |
modules, you can just not declare one, and leave the corresponding
|
|
Packit |
90a5c9 |
structure slot in the module itself NULL .
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Now that we have these structures, we need to be able to figure out how
|
|
Packit |
90a5c9 |
to fill them. That involves processing the actual AddType and AddEncoding commands. To find commands, the server looks in
|
|
Packit |
90a5c9 |
the module's command table. That table contains information on how many
|
|
Packit |
90a5c9 |
arguments the commands take, and in what formats, where it is permitted,
|
|
Packit |
90a5c9 |
and so forth. That information is sufficient to allow the server to invoke
|
|
Packit |
90a5c9 |
most command-handling functions with pre-parsed arguments. Without further
|
|
Packit |
90a5c9 |
ado, let's look at the AddType
|
|
Packit |
90a5c9 |
command handler, which looks like this (the AddEncoding command looks basically the same, and won't be
|
|
Packit |
90a5c9 |
shown here):
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
char *add_type(cmd_parms *cmd, mime_dir_config *m, char *ct, char *ext)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (*ext == '.') ++ext;
|
|
Packit |
90a5c9 |
ap_table_set (m->forced_types, ext, ct);
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
This command handler is unusually simple. As you can see, it takes
|
|
Packit |
90a5c9 |
four arguments, two of which are pre-parsed arguments, the third being the
|
|
Packit |
90a5c9 |
per-directory configuration structure for the module in question, and the
|
|
Packit |
90a5c9 |
fourth being a pointer to a cmd_parms structure. That
|
|
Packit |
90a5c9 |
structure contains a bunch of arguments which are frequently of use to
|
|
Packit |
90a5c9 |
some, but not all, commands, including a resource pool (from which memory
|
|
Packit |
90a5c9 |
can be allocated, and to which cleanups should be tied), and the (virtual)
|
|
Packit |
90a5c9 |
server being configured, from which the module's per-server configuration
|
|
Packit |
90a5c9 |
data can be obtained if required.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Another way in which this particular command handler is unusually
|
|
Packit |
90a5c9 |
simple is that there are no error conditions which it can encounter. If
|
|
Packit |
90a5c9 |
there were, it could return an error message instead of NULL ;
|
|
Packit |
90a5c9 |
this causes an error to be printed out on the server's
|
|
Packit |
90a5c9 |
stderr , followed by a quick exit, if it is in the main config
|
|
Packit |
90a5c9 |
files; for a .htaccess file, the syntax error is logged in
|
|
Packit |
90a5c9 |
the server error log (along with an indication of where it came from), and
|
|
Packit |
90a5c9 |
the request is bounced with a server error response (HTTP error status,
|
|
Packit |
90a5c9 |
code 500).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The MIME module's command table has entries for these commands, which
|
|
Packit |
90a5c9 |
look like this:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
command_rec mime_cmds[] = {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
{ "AddType", add_type, NULL, OR_FILEINFO, TAKE2,
|
|
Packit |
90a5c9 |
"a mime type followed by a file extension" },
|
|
Packit |
90a5c9 |
{ "AddEncoding", add_encoding, NULL, OR_FILEINFO, TAKE2,
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
"an encoding (e.g., gzip), followed by a file extension" },
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
{ NULL }
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
};
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The entries in these tables are:
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The name of the command
|
|
Packit |
90a5c9 |
The function which handles it
|
|
Packit |
90a5c9 |
a (void *) pointer, which is passed in the
|
|
Packit |
90a5c9 |
cmd_parms structure to the command handler ---
|
|
Packit |
90a5c9 |
this is useful in case many similar commands are handled by
|
|
Packit |
90a5c9 |
the same function.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
A bit mask indicating where the command may appear. There
|
|
Packit |
90a5c9 |
are mask bits corresponding to each
|
|
Packit |
90a5c9 |
AllowOverride option, and an additional mask
|
|
Packit |
90a5c9 |
bit, RSRC_CONF , indicating that the command may
|
|
Packit |
90a5c9 |
appear in the server's own config files, but not in
|
|
Packit |
90a5c9 |
any .htaccess file.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
A flag indicating how many arguments the command handler
|
|
Packit |
90a5c9 |
wants pre-parsed, and how they should be passed in.
|
|
Packit |
90a5c9 |
TAKE2 indicates two pre-parsed arguments. Other
|
|
Packit |
90a5c9 |
options are TAKE1 , which indicates one
|
|
Packit |
90a5c9 |
pre-parsed argument, FLAG , which indicates that
|
|
Packit |
90a5c9 |
the argument should be On or Off ,
|
|
Packit |
90a5c9 |
and is passed in as a boolean flag, RAW_ARGS ,
|
|
Packit |
90a5c9 |
which causes the server to give the command the raw, unparsed
|
|
Packit |
90a5c9 |
arguments (everything but the command name itself). There is
|
|
Packit |
90a5c9 |
also ITERATE , which means that the handler looks
|
|
Packit |
90a5c9 |
the same as TAKE1 , but that if multiple
|
|
Packit |
90a5c9 |
arguments are present, it should be called multiple times,
|
|
Packit |
90a5c9 |
and finally ITERATE2 , which indicates that the
|
|
Packit |
90a5c9 |
command handler looks like a TAKE2 , but if more
|
|
Packit |
90a5c9 |
arguments are present, then it should be called multiple
|
|
Packit |
90a5c9 |
times, holding the first argument constant.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Finally, we have a string which describes the arguments
|
|
Packit |
90a5c9 |
that should be present. If the arguments in the actual config
|
|
Packit |
90a5c9 |
file are not as required, this string will be used to help
|
|
Packit |
90a5c9 |
give a more specific error message. (You can safely leave
|
|
Packit |
90a5c9 |
this NULL ).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Finally, having set this all up, we have to use it. This is ultimately
|
|
Packit |
90a5c9 |
done in the module's handlers, specifically for its file-typing handler,
|
|
Packit |
90a5c9 |
which looks more or less like this; note that the per-directory
|
|
Packit |
90a5c9 |
configuration structure is extracted from the request_rec 's
|
|
Packit |
90a5c9 |
per-directory configuration vector by using the
|
|
Packit |
90a5c9 |
ap_get_module_config function.
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int find_ct(request_rec *r)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
int i;
|
|
Packit |
90a5c9 |
char *fn = ap_pstrdup (r->pool, r->filename);
|
|
Packit |
90a5c9 |
mime_dir_config *conf = (mime_dir_config *)
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_get_module_config(r->per_dir_config, &mime_module);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
char *type;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (S_ISDIR(r->finfo.st_mode)) {
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
r->content_type = DIR_MAGIC_TYPE;
|
|
Packit |
90a5c9 |
return OK;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if((i=ap_rind(fn,'.')) < 0) return DECLINED;
|
|
Packit |
90a5c9 |
++i;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((type = ap_table_get (conf->encoding_types, &fn[i])))
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
r->content_encoding = type;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
/* go back to previous extension to try to use it as a type */
|
|
Packit |
90a5c9 |
fn[i-1] = '\0';
|
|
Packit |
90a5c9 |
if((i=ap_rind(fn,'.')) < 0) return OK;
|
|
Packit |
90a5c9 |
++i;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if ((type = ap_table_get (conf->forced_types, &fn[i])))
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
r->content_type = type;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
return OK;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
virtual servers, etc.
|
|
Packit |
90a5c9 |
The basic ideas behind per-server module configuration are basically
|
|
Packit |
90a5c9 |
the same as those for per-directory configuration; there is a creation
|
|
Packit |
90a5c9 |
function and a merge function, the latter being invoked where a virtual
|
|
Packit |
90a5c9 |
server has partially overridden the base server configuration, and a
|
|
Packit |
90a5c9 |
combined structure must be computed. (As with per-directory configuration,
|
|
Packit |
90a5c9 |
the default if no merge function is specified, and a module is configured
|
|
Packit |
90a5c9 |
in some virtual server, is that the base configuration is simply
|
|
Packit |
90a5c9 |
ignored).
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
The only substantial difference is that when a command needs to
|
|
Packit |
90a5c9 |
configure the per-server private module data, it needs to go to the
|
|
Packit |
90a5c9 |
cmd_parms data to get at it. Here's an example, from the
|
|
Packit |
90a5c9 |
alias module, which also indicates how a syntax error can be returned
|
|
Packit |
90a5c9 |
(note that the per-directory configuration argument to the command
|
|
Packit |
90a5c9 |
handler is declared as a dummy, since the module doesn't actually have
|
|
Packit |
90a5c9 |
per-directory config data):
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
char *add_redirect(cmd_parms *cmd, void *dummy, char *f, char *url)
|
|
Packit |
90a5c9 |
{
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
server_rec *s = cmd->server;
|
|
Packit |
90a5c9 |
alias_server_conf *conf = (alias_server_conf *)
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
ap_get_module_config(s->module_config,&alias_module);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
alias_entry *new = ap_push_array (conf->redirects);
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
if (!ap_is_url (url)) return "Redirect to non-URL";
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
new->fake = f; new->real = url;
|
|
Packit |
90a5c9 |
return NULL;
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
|
|
Packit |
90a5c9 |
Available Languages: en
|
|
Packit |
90a5c9 |
Notice:This is not a Q&A section. Comments placed here should be pointed towards suggestions on improving the documentation or server, and may be removed again by our moderators if they are either implemented or considered invalid/off-topic. Questions on how to manage the Apache HTTP Server should be directed at either our IRC channel, #httpd, on Freenode, or sent to our mailing lists.
|
|
Packit |
90a5c9 |
<script type="text/javascript">
|
|
Packit |
90a5c9 |
var comments_shortname = 'httpd';
|
|
Packit |
90a5c9 |
var comments_identifier = 'http://httpd.apache.org/docs/2.4/developer/API.html';
|
|
Packit |
90a5c9 |
(function(w, d) {
|
|
Packit |
90a5c9 |
if (w.location.hostname.toLowerCase() == "httpd.apache.org") {
|
|
Packit |
90a5c9 |
d.write('
|
|
Packit |
90a5c9 |
var s = d.createElement('script');
|
|
Packit |
90a5c9 |
s.type = 'text/javascript';
|
|
Packit |
90a5c9 |
s.async = true;
|
|
Packit |
90a5c9 |
s.src = 'https://comments.apache.org/show_comments.lua?site=' + comments_shortname + '&page=' + comments_identifier;
|
|
Packit |
90a5c9 |
(d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(s);
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
else {
|
|
Packit |
90a5c9 |
d.write('
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
})(window, document);
|
|
Packit |
90a5c9 |
//--></script>
|
|
Packit |
90a5c9 |
Copyright 2018 The Apache Software Foundation. Licensed under the Apache License, Version 2.0.
|
|
Packit |
90a5c9 |
Modules | Directives | FAQ | Glossary | Sitemap <script type="text/javascript">
|
|
Packit |
90a5c9 |
if (typeof(prettyPrint) !== 'undefined') {
|
|
Packit |
90a5c9 |
prettyPrint();
|
|
Packit |
90a5c9 |
}
|
|
Packit |
90a5c9 |
//--></script>
|
|
Packit |
90a5c9 |
</body></html>
|