API.html.en 63.9 KB
Newer Older
powelld's avatar
powelld committed
            (mime_dir_config *)ap_palloc (p, sizeof(mime_dir_config));<br />
          </span>
          <br />
          new-&gt;forced_types = ap_overlay_tables (p, subdir-&gt;forced_types,<br />
          <span class="indent">
            parent_dir-&gt;forced_types);<br />
          </span>
          new-&gt;encoding_types = ap_overlay_tables (p, subdir-&gt;encoding_types,<br />
          <span class="indent">
            parent_dir-&gt;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-&gt;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-&gt;pool, r-&gt;filename);<br />
          mime_dir_config *conf = (mime_dir_config *)<br />
          <span class="indent">
            ap_get_module_config(r-&gt;per_dir_config, &amp;mime_module);<br />
          </span>
          char *type;<br />
          <br />
          if (S_ISDIR(r-&gt;finfo.st_mode)) {<br />
          <span class="indent">
            r-&gt;content_type = DIR_MAGIC_TYPE;<br />
            return OK;<br />
          </span>
          }<br />
          <br />
          if((i=ap_rind(fn,'.')) &lt; 0) return DECLINED;<br />
          ++i;<br />
          <br />
          if ((type = ap_table_get (conf-&gt;encoding_types, &amp;fn[i])))<br />
          {<br />
          <span class="indent">
            r-&gt;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,'.')) &lt; 0) return OK;<br />
            ++i;<br />
          </span>
          }<br />
          <br />
          if ((type = ap_table_get (conf-&gt;forced_types, &amp;fn[i])))<br />
          {<br />
          <span class="indent">
            r-&gt;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-&gt;server;<br />
          alias_server_conf *conf = (alias_server_conf *)<br />
          <span class="indent">
            ap_get_module_config(s-&gt;module_config,&amp;alias_module);<br />
          </span>
          alias_entry *new = ap_push_array (conf-&gt;redirects);<br />
          <br />
          if (!ap_is_url (url)) return "Redirect to non-URL";<br />
          <br />
          new-&gt;fake = f; new-&gt;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">&nbsp;en&nbsp;</a></p>
</div><div class="top"><a href="#page-header"><img src="../images/up.gif" alt="top" /></a></div><div class="section"><h2><a id="comments_section" name="comments_section">Comments</a></h2><div class="warning"><strong>Notice:</strong><br />This is not a Q&amp;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 <a href="http://httpd.apache.org/lists.html">mailing lists</a>.</div>
<script type="text/javascript"><!--//--><![CDATA[//><!--
var comments_shortname = 'httpd';
var comments_identifier = 'http://httpd.apache.org/docs/2.4/developer/API.html';
(function(w, d) {
    if (w.location.hostname.toLowerCase() == "httpd.apache.org") {
        d.write('<div id="comments_thread"><\/div>');
        var s = d.createElement('script');
        s.type = 'text/javascript';
        s.async = true;
        s.src = 'https://comments.apache.org/show_comments.lua?site=' + comments_shortname + '&page=' + comments_identifier;
        (d.getElementsByTagName('head')[0] || d.getElementsByTagName('body')[0]).appendChild(s);
    }
    else { 
        d.write('<div id="comments_thread">Comments are disabled for this page at the moment.<\/div>');
    }
})(window, document);
//--><!]]></script></div><div id="footer">
<p class="apache">Copyright 2017 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="http://wiki.apache.org/httpd/FAQ">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div><script type="text/javascript"><!--//--><![CDATA[//><!--
if (typeof(prettyPrint) !== 'undefined') {
    prettyPrint();
}
//--><!]]></script>
</body></html>