📄 api.html
字号:
can just use it. Otherwise, we need to merge the two structures
somehow.</p>
<p>To do that, the server invokes the module's per-directory config merge
function, if one is present. That function takes three arguments: the two
structures being merged, and a resource pool in which to allocate the
result. For the MIME module, all that needs to be done is overlay the
tables from the new per-directory config structure with those from the
parent:</p>
<div class="example"><p><code>
void *merge_mime_dir_configs (pool *p, void *parent_dirv, void *subdirv)<br />
{<br />
<span class="indent">
mime_dir_config *parent_dir = (mime_dir_config *)parent_dirv;<br />
mime_dir_config *subdir = (mime_dir_config *)subdirv;<br />
mime_dir_config *new =<br />
<span class="indent">
(mime_dir_config *)ap_palloc (p, sizeof(mime_dir_config));<br />
</span>
<br />
new->forced_types = ap_overlay_tables (p, subdir->forced_types,<br />
<span class="indent">
parent_dir->forced_types);<br />
</span>
new->encoding_types = ap_overlay_tables (p, subdir->encoding_types,<br />
<span class="indent">
parent_dir->encoding_types);<br />
</span>
<br />
return new;<br />
</span>
}
</code></p></div>
<p>As a note -- if there is no per-directory merge function present, the
server will just use the subdirectory's configuration info, and ignore
the parent's. For some modules, that works just fine (例如,for
the includes module, whose per-directory configuration information
consists solely of the state of the <code>XBITHACK</code>), and for those
modules, you can just not declare one, and leave the corresponding
structure slot in the module itself <code>NULL</code>.</p>
<h3><a name="commands" id="commands">Command handling</a></h3>
<p>Now that we have these structures, we need to be able to figure out how
to fill them. That involves processing the actual <code class="directive"><a href="../mod/mod_mime.html#addtype">AddType</a></code> and <code class="directive"><a href="../mod/mod_mime.html#addencoding">AddEncoding</a></code> commands. To find commands, the server looks in
the module's command table. That table contains information on how many
arguments the commands take, and in what formats, where it is permitted,
and so forth. That information is sufficient to allow the server to invoke
most command-handling functions with pre-parsed arguments. Without further
ado, let's look at the <code class="directive"><a href="../mod/mod_mime.html#addtype">AddType</a></code>
command handler, which looks like this (the <code class="directive"><a href="../mod/mod_mime.html#addencoding">AddEncoding</a></code> command looks basically the same, and won't be
shown here):</p>
<div class="example"><p><code>
char *add_type(cmd_parms *cmd, mime_dir_config *m, char *ct, char *ext)<br />
{<br />
<span class="indent">
if (*ext == '.') ++ext;<br />
ap_table_set (m->forced_types, ext, ct);<br />
return NULL;<br />
</span>
}
</code></p></div>
<p>This command handler is unusually simple. As you can see, it takes
four arguments, two of which are pre-parsed arguments, the third being the
per-directory configuration structure for the module in question, and the
fourth being a pointer to a <code>cmd_parms</code> structure. That
structure contains a bunch of arguments which are frequently of use to
some, but not all, commands, including a resource pool (from which memory
can be allocated, and to which cleanups should be tied), and the (virtual)
server being configured, from which the module's per-server configuration
data can be obtained if required.</p>
<p>Another way in which this particular command handler is unusually
simple is that there are no error conditions which it can encounter. If
there were, it could return an error message instead of <code>NULL</code>;
this causes an error to be printed out on the server's
<code>stderr</code>, followed by a quick exit, if it is in the main config
files; for a <code>.htaccess</code> file, the syntax error is logged in
the server error log (along with an indication of where it came from), and
the request is bounced with a server error response (HTTP error status,
code 500).</p>
<p>The MIME module's command table has entries for these commands, which
look like this:</p>
<div class="example"><p><code>
command_rec mime_cmds[] = {<br />
<span class="indent">
{ "AddType", add_type, NULL, OR_FILEINFO, TAKE2,<br />
<span class="indent">"a mime type followed by a file extension" },<br /></span>
{ "AddEncoding", add_encoding, NULL, OR_FILEINFO, TAKE2,<br />
<span class="indent">
"an encoding (例如,gzip), followed by a file extension" },<br />
</span>
{ NULL }<br />
</span>
};
</code></p></div>
<p>The entries in these tables are:</p>
<ul>
<li>The name of the command</li>
<li>The function which handles it</li>
<li>a <code>(void *)</code> pointer, which is passed in the
<code>cmd_parms</code> structure to the command handler ---
this is useful in case many similar commands are handled by
the same function.</li>
<li>A bit mask indicating where the command may appear. There
are mask bits corresponding to each
<code>AllowOverride</code> option, and an additional mask
bit, <code>RSRC_CONF</code>, indicating that the command may
appear in the server's own config files, but <em>not</em> in
any <code>.htaccess</code> file.</li>
<li>A flag indicating how many arguments the command handler
wants pre-parsed, and how they should be passed in.
<code>TAKE2</code> indicates two pre-parsed arguments. Other
options are <code>TAKE1</code>, which indicates one
pre-parsed argument, <code>FLAG</code>, which indicates that
the argument should be <code>On</code> or <code>Off</code>,
and is passed in as a boolean flag, <code>RAW_ARGS</code>,
which causes the server to give the command the raw, unparsed
arguments (everything but the command name itself). There is
also <code>ITERATE</code>, which means that the handler looks
the same as <code>TAKE1</code>, but that if multiple
arguments are present, it should be called multiple times,
and finally <code>ITERATE2</code>, which indicates that the
command handler looks like a <code>TAKE2</code>, but if more
arguments are present, then it should be called multiple
times, holding the first argument constant.</li>
<li>Finally, we have a string which describes the arguments
that should be present. If the arguments in the actual config
file are not as required, this string will be used to help
give a more specific error message. (You can safely leave
this <code>NULL</code>).</li>
</ul>
<p>Finally, having set this all up, we have to use it. This is ultimately
done in the module's handlers, specifically for its file-typing handler,
which looks more or less like this; note that the per-directory
configuration structure is extracted from the <code>request_rec</code>'s
per-directory configuration vector by using the
<code>ap_get_module_config</code> function.</p>
<div class="example"><p><code>
int find_ct(request_rec *r)<br />
{<br />
<span class="indent">
int i;<br />
char *fn = ap_pstrdup (r->pool, r->filename);<br />
mime_dir_config *conf = (mime_dir_config *)<br />
<span class="indent">
ap_get_module_config(r->per_dir_config, &mime_module);<br />
</span>
char *type;<br />
<br />
if (S_ISDIR(r->finfo.st_mode)) {<br />
<span class="indent">
r->content_type = DIR_MAGIC_TYPE;<br />
return OK;<br />
</span>
}<br />
<br />
if((i=ap_rind(fn,'.')) < 0) return DECLINED;<br />
++i;<br />
<br />
if ((type = ap_table_get (conf->encoding_types, &fn[i])))<br />
{<br />
<span class="indent">
r->content_encoding = type;<br />
<br />
/* go back to previous extension to try to use it as a type */<br />
fn[i-1] = '\0';<br />
if((i=ap_rind(fn,'.')) < 0) return OK;<br />
++i;<br />
</span>
}<br />
<br />
if ((type = ap_table_get (conf->forced_types, &fn[i])))<br />
{<br />
<span class="indent">
r->content_type = type;<br />
</span>
}<br />
<br />
return OK;
</span>
}
</code></p></div>
<h3><a name="servconf" id="servconf">Side notes -- per-server configuration,
virtual servers, <em>etc</em>.</a></h3>
<p>The basic ideas behind per-server module configuration are basically
the same as those for per-directory configuration; there is a creation
function and a merge function, the latter being invoked where a virtual
server has partially overridden the base server configuration, and a
combined structure must be computed. (As with per-directory configuration,
the default if no merge function is specified, and a module is configured
in some virtual server, is that the base configuration is simply
ignored).</p>
<p>The only substantial difference is that when a command needs to
configure the per-server private module data, it needs to go to the
<code>cmd_parms</code> data to get at it. Here's an example, from the
alias module, which also indicates how a syntax error can be returned
(note that the per-directory configuration argument to the command
handler is declared as a dummy, since the module doesn't actually have
per-directory config data):</p>
<div class="example"><p><code>
char *add_redirect(cmd_parms *cmd, void *dummy, char *f, char *url)<br />
{<br />
<span class="indent">
server_rec *s = cmd->server;<br />
alias_server_conf *conf = (alias_server_conf *)<br />
<span class="indent">
ap_get_module_config(s->module_config,&alias_module);<br />
</span>
alias_entry *new = ap_push_array (conf->redirects);<br />
<br />
if (!ap_is_url (url)) return "Redirect to non-URL";<br />
<br />
new->fake = f; new->real = url;<br />
return NULL;<br />
</span>
}
</code></p></div>
</div></div>
<div id="footer">
<p class="apache">本文允许自由使用、分发、转载,但必须保留译者署名;详见:<a href="../translator_announcement.html#announcement">译者声明</a>。</p>
<p class="menu"><a href="../mod/index.html">模块索引</a> | <a href="../mod/directives.html">指令索引</a> | <a href="../faq/index.html">常见问题</a> | <a href="../glossary.html">词汇表</a> | <a href="../sitemap.html">站点导航</a></p></div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -