📄 api.html.en
字号:
per-directory config structure for the MIME module is still valid, and we 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 (<em>e.g.</em>, 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 (<em>e.g.</em>, 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 class="bottomlang"><p><span>Available Languages: </span><a href="../en/developer/API.html" title="English"> en </a></p></div><div id="footer"><p class="apache">Copyright 2007 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p><p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -