📄 api.html
字号:
merge_cgi_server_config, /* merge server config */
cgi_cmds, /* command table */
cgi_handlers, /* handlers */
translate_scriptalias, /* filename translation */
NULL, /* check_user_id */
NULL, /* check auth */
NULL, /* check access */
type_scriptalias, /* type_checker */
NULL, /* fixups */
NULL, /* logger */
NULL /* header parser */
};</pre></div>
</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="handlers" id="handlers">How handlers work</a></h2>
<p>The sole argument to handlers is a <code>request_rec</code> structure.
This structure describes a particular request which has been made to the
server, on behalf of a client. In most cases, each connection to the
client generates only one <code>request_rec</code> structure.</p>
<h3><a name="req_tour" id="req_tour">A brief tour of the request_rec</a></h3>
<p><code>request_rec</code> contains pointers to a resource pool
which will be cleared when the server is finished handling the request;
to structures containing per-server and per-connection information, and
most importantly, information on the request itself.</p>
<p>The most important such information is a small set of character strings
describing attributes of the object being requested, including its URI,
filename, content-type and content-encoding (these being filled in by the
translation and type-check handlers which handle the request,
respectively).</p>
<p>Other commonly used data items are tables giving the MIME headers on
the client's original request, MIME headers to be sent back with the
response (which modules can add to at will), and environment variables for
any subprocesses which are spawned off in the course of servicing the
request. These tables are manipulated using the <code>ap_table_get</code>
and <code>ap_table_set</code> routines.</p>
<div class="note">
<p>Note that the <code>Content-type</code> header value <em>cannot</em>
be set by module content-handlers using the <code>ap_table_*()</code>
routines. Rather, it is set by pointing the <code>content_type</code>
field in the <code>request_rec</code> structure to an appropriate
string. 例如,</p>
<div class="example"><p><code>
r->content_type = "text/html";
</code></p></div>
</div>
<p>Finally, there are pointers to two data structures which, in turn,
point to per-module configuration structures. Specifically, these hold
pointers to the data structures which the module has built to describe
the way it has been configured to operate in a given directory (via
<code>.htaccess</code> files or <code class="directive"><a href="../mod/core.html#directory"><Directory></a></code> sections), for private data it has built in the
course of servicing the request (so modules' handlers for one phase can
pass 'notes' to their handlers for other phases). There is another such
configuration vector in the <code>server_rec</code> data structure pointed
to by the <code>request_rec</code>, which contains per (virtual) server
configuration data.</p>
<p>Here is an abridged declaration, giving the fields most commonly
used:</p>
<div class="example"><p><code>
struct request_rec {<br />
<br />
pool *pool;<br />
conn_rec *connection;<br />
server_rec *server;<br />
<br />
/* What object is being requested */<br />
<br />
char *uri;<br />
char *filename;<br />
char *path_info;
</code></p><pre>char *args; /* QUERY_ARGS, if any */
struct stat finfo; /* Set by server core;
* st_mode set to zero if no such file */</pre><p><code>
char *content_type;<br />
char *content_encoding;<br />
<br />
/* MIME header environments, in and out. Also, <br />
* an array containing environment variables to<br />
* be passed to subprocesses, so people can write<br />
* modules to add to that environment.<br />
*<br />
* The difference between headers_out and <br />
* err_headers_out is that the latter are printed <br />
* even on error, and persist across internal<br />
* redirects (so the headers printed for <br />
* <code class="directive"><a href="../mod/core.html#errordocument">ErrorDocument</a></code> handlers will have
them).<br />
*/<br />
<br />
table *headers_in;<br />
table *headers_out;<br />
table *err_headers_out;<br />
table *subprocess_env;<br />
<br />
/* Info about the request itself... */<br />
<br />
</code></p><pre>int header_only; /* HEAD request, as opposed to GET */
char *protocol; /* Protocol, as given to us, or HTTP/0.9 */
char *method; /* GET, HEAD, POST, <em>etc.</em> */
int method_number; /* M_GET, M_POST, <em>etc.</em> */
</pre><p><code>
/* Info for logging */<br />
<br />
char *the_request;<br />
int bytes_sent;<br />
<br />
/* A flag which modules can set, to indicate that<br />
* the data being returned is volatile, and clients<br />
* should be told not to cache it.<br />
*/<br />
<br />
int no_cache;<br />
<br />
/* Various other config info which may change<br />
* with .htaccess files<br />
* These are config vectors, with one void*<br />
* pointer for each module (the thing pointed<br />
* to being the module's business).<br />
*/<br />
<br />
</code></p><pre>void *per_dir_config; /* Options set in config files, <em>etc.</em> */
void *request_config; /* Notes on *this* request */</pre><p><code>
<br />
};
</code></p></div>
<h3><a name="req_orig" id="req_orig">Where request_rec structures come from</a></h3>
<p>Most <code>request_rec</code> structures are built by reading an HTTP
request from a client, and filling in the fields. However, there are a
few exceptions:</p>
<ul>
<li>If the request is to an imagemap, a type map (<em>i.e.</em>, a
<code>*.var</code> file), or a CGI script which returned a local
'Location:', then the resource which the user requested is going to be
ultimately located by some URI other than what the client originally
supplied. In this case, the server does an <em>internal redirect</em>,
constructing a new <code>request_rec</code> for the new URI, and
processing it almost exactly as if the client had requested the new URI
directly.</li>
<li>If some handler signaled an error, and an <code>ErrorDocument</code>
is in scope, the same internal redirect machinery comes into play.</li>
<li><p>Finally, a handler occasionally needs to investigate 'what would
happen if' some other request were run. For instance, the directory
indexing module needs to know what MIME type would be assigned to a
request for each directory entry, in order to figure out what icon to
use.</p>
<p>Such handlers can construct a <em>sub-request</em>, using the
functions <code>ap_sub_req_lookup_file</code>,
<code>ap_sub_req_lookup_uri</code>, and <code>ap_sub_req_method_uri</code>;
these construct a new <code>request_rec</code> structure and processes it
as you would expect, up to but not including the point of actually sending
a response. (These functions skip over the access checks if the
sub-request is for a file in the same directory as the original
request).</p>
<p>(Server-side includes work by building sub-requests and then actually
invoking the response handler for them, via the function
<code>ap_run_sub_req</code>).</p>
</li>
</ul>
<h3><a name="req_return" id="req_return">Handling requests, declining, and returning
error codes</a></h3>
<p>As discussed above, each handler, when invoked to handle a particular
<code>request_rec</code>, has to return an <code>int</code> to indicate
what happened. That can either be</p>
<ul>
<li><code>OK</code> -- the request was handled successfully. This may or
may not terminate the phase.</li>
<li><code>DECLINED</code> -- no erroneous condition exists, but the module
declines to handle the phase; the server tries to find another.</li>
<li>an HTTP error code, which aborts handling of the request.</li>
</ul>
<p>Note that if the error code returned is <code>REDIRECT</code>, then
the module should put a <code>Location</code> in the request's
<code>headers_out</code>, to indicate where the client should be
redirected <em>to</em>.</p>
<h3><a name="resp_handlers" id="resp_handlers">Special considerations for response
handlers</a></h3>
<p>Handlers for most phases do their work by simply setting a few fields
in the <code>request_rec</code> structure (or, in the case of access
checkers, simply by returning the correct error code). However, response
handlers have to actually send a request back to the client.</p>
<p>They should begin by sending an HTTP response header, using the
function <code>ap_send_http_header</code>. (You don't have to do anything
special to skip sending the header for HTTP/0.9 requests; the function
figures out on its own that it shouldn't do anything). If the request is
marked <code>header_only</code>, that's all they should do; they should
return after that, without attempting any further output.</p>
<p>Otherwise, they should produce a request body which responds to the
client as appropriate. The primitives for this are <code>ap_rputc</code>
and <code>ap_rprintf</code>, for internally generated output, and
<code>ap_send_fd</code>, to copy the contents of some <code>FILE *</code>
straight to the client.</p>
<p>At this point, you should more or less understand the following piece
of code, which is the handler which handles <code>GET</code> requests
which have no more specific handler; it also shows how conditional
<code>GET</code>s can be handled, if it's desirable to do so in a
particular response handler -- <code>ap_set_last_modified</code> checks
against the <code>If-modified-since</code> value supplied by the client,
if any, and returns an appropriate code (which will, if nonzero, be
USE_LOCAL_COPY). No similar considerations apply for
<code>ap_set_content_length</code>, but it returns an error code for
symmetry.</p>
<div class="example"><p><code>
int default_handler (request_rec *r)<br />
{<br />
<span class="indent">
int errstatus;<br />
FILE *f;<br />
<br />
if (r->method_number != M_GET) return DECLINED;<br />
if (r->finfo.st_mode == 0) return NOT_FOUND;<br />
<br />
if ((errstatus = ap_set_content_length (r, r->finfo.st_size))<br />
||
(errstatus = ap_set_last_modified (r, r->finfo.st_mtime)))<br />
return errstatus;<br />
<br />
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -