561N/A<?
xml version="1.0" encoding="ISO-8859-1"?>
561N/A XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 561N/A This file is generated from xml source: DO NOT EDIT 919N/A XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 919N/A<
title>Converting Modules from Apache 1.3 to Apache 2.0 - Apache HTTP Server</
title>
919N/A<
body id="manual-page"><
div id="page-header">
919N/A<
p class="apache">Apache HTTP Server Version 2.5</
p>
919N/A<
div class="up"><
a href="./"><
img title="<-" alt="<-" src="/images/left.gif" /></
a></
div>
561N/A <
p>This is a first attempt at writing the lessons I learned
970N/A when trying to convert the <
code>mod_mmap_static</
code> module to Apache
970N/A 2.0. It's by no means definitive and probably won't even be
970N/A correct in some ways, but it's a start.</
p>
561N/A<
div id="quickview"><
ul id="toc"><
li><
img alt="" src="/images/down.gif" /> <
a href="#easy">The easier changes ...</
a></
li>
561N/A</
ul><
ul class="seealso"><
li><
a href="#comments_section">Comments</
a></
li></
ul></
div>
911N/A<
div class="top"><
a href="#page-header"><
img alt="top" src="/images/up.gif" /></
a></
div>
911N/A<
h2><
a name="easy" id="easy">The easier changes ...</
a></
h2>
561N/A <
h3><
a name="cleanup" id="cleanup">Cleanup Routines</
a></
h3>
963N/A <
p>These now need to be of type <
code>apr_status_t</
code> and return a
963N/A value of that type. Normally the return value will be
561N/A <
code>APR_SUCCESS</
code> unless there is some need to signal an error in
561N/A the cleanup. Be aware that even though you signal an error not all code
561N/A yet checks and acts upon the error.</
p>
<
h3><
a name="init" id="init">Initialisation Routines</
a></
h3>
<
p>These should now be renamed to better signify where they sit
in the overall process. So the name gets a small change from
<
code>mmap_init</
code> to <
code>mmap_post_config</
code>. The arguments
passed have undergone a radical change and now look like</
p>
<
li><
code>apr_pool_t *p</
code></
li>
<
li><
code>apr_pool_t *plog</
code></
li>
<
li><
code>apr_pool_t *ptemp</
code></
li>
<
li><
code>server_rec *s</
code></
li>
<
h3><
a name="datatypes" id="datatypes">Data Types</
a></
h3>
<
p>A lot of the data types have been moved into the <
a href="http://apr.apache.org/">APR</
a>. This means that some have had
a name change, such as the one shown above. The following is a brief
list of some of the changes that you are likely to have to make.</
p>
<
li><
code>pool</
code> becomes <
code>apr_pool_t</
code></
li>
<
li><
code>table</
code> becomes <
code>apr_table_t</
code></
li>
</
div><
div class="top"><
a href="#page-header"><
img alt="top" src="/images/up.gif" /></
a></
div>
<
h2><
a name="messy" id="messy">The messier changes...</
a></
h2>
<
h3><
a name="register-hooks" id="register-hooks">Register Hooks</
a></
h3>
<
p>The new architecture uses a series of hooks to provide for
calling your functions. These you'll need to add to your module
by way of a new function, <
code>static void register_hooks(void)</
code>.
The function is really reasonably straightforward once you
understand what needs to be done. Each function that needs
calling at some stage in the processing of a request needs to
be registered, handlers do not. There are a number of phases
where functions can be added, and for each you can specify with
a high degree of control the relative order that the function
<
p>This is the code that was added to <
code>mod_mmap_static</
code>:</
p>
<
div class="example"><
pre>
static void register_hooks(void)
static const char * const aszPre[]={ "
http_core.c",NULL };
ap_hook_post_config(mmap_post_config,NULL,NULL,HOOK_MIDDLE);
ap_hook_translate_name(mmap_static_xlat,aszPre,NULL,HOOK_LAST);
<
p>This registers 2 functions that need to be called, one in
the <
code>post_config</
code> stage (virtually every module will need this
one) and one for the <
code>translate_name</
code> phase. note that while
there are different function names the format of each is
identical. So what is the format?</
p>
<
div class="example"><
p><
code>
ap_hook_<
var>phase_name</
var>(<
var>function_name</
var>,
<
var>predecessors</
var>, <
var>successors</
var>, <
var>position</
var>);
<
p>There are 3 hook positions defined...</
p>
<
li><
code>HOOK_FIRST</
code></
li>
<
li><
code>HOOK_MIDDLE</
code></
li>
<
li><
code>HOOK_LAST</
code></
li>
<
p>To define the position you use the position and then modify
it with the predecessors and successors. Each of the modifiers
can be a list of functions that should be called, either before
the function is run (predecessors) or after the function has
<
p>In the <
code>mod_mmap_static</
code> case I didn't care about the
<
code>post_config</
code> stage, but the <
code>mmap_static_xlat</
code>
<
strong>must</
strong> be called after the core module had done it's name
translation, hence the use of the aszPre to define a modifier to the
position <
code>HOOK_LAST</
code>.</
p>
<
h3><
a name="moddef" id="moddef">Module Definition</
a></
h3>
<
p>There are now a lot fewer stages to worry about when
creating your module definition. The old definition looked
<
div class="example"><
pre>
module MODULE_VAR_EXPORT <
var>module_name</
var>_module =
/* dir merger --- default is to override */
/* merge server config */
/* filename translation */
<
p>The new structure is a great deal simpler...</
p>
<
div class="example"><
pre>
module MODULE_VAR_EXPORT <
var>module_name</
var>_module =
/* create per-directory config structures */
/* merge per-directory config structures */
/* create per-server config structures */
/* merge per-server config structures */
<
p>Some of these read directly across, some don't. I'll try to
summarise what should be done below.</
p>
<
p>The stages that read directly across :</
p>
<
dt><
code>/* dir config creater */</
code></
dt>
<
dd><
code>/* create per-directory config structures */</
code></
dd>
<
dt><
code>/* server config */</
code></
dt>
<
dd><
code>/* create per-server config structures */</
code></
dd>
<
dt><
code>/* dir merger */</
code></
dt>
<
dd><
code>/* merge per-directory config structures */</
code></
dd>
<
dt><
code>/* merge server config */</
code></
dt>
<
dd><
code>/* merge per-server config structures */</
code></
dd>
<
dt><
code>/* command table */</
code></
dt>
<
dd><
code>/* command apr_table_t */</
code></
dd>
<
dt><
code>/* handlers */</
code></
dt>
<
dd><
code>/* handlers */</
code></
dd>
<
p>The remainder of the old functions should be registered as
hooks. There are the following hook stages defined so
<
dt><
code>ap_hook_pre_config</
code></
dt>
<
dd>do any setup required prior to processing configuration
<
dt><
code>ap_hook_check_config</
code></
dt>
<
dd>review configuration directive interdependencies</
dd>
<
dt><
code>ap_hook_test_config</
code></
dt>
<
dd>executes only with <
code>-t</
code> option</
dd>
<
dt><
code>ap_hook_open_logs</
code></
dt>
<
dd>open any specified logs</
dd>
<
dt><
code>ap_hook_post_config</
code></
dt>
<
dd>this is where the old <
code>_init</
code> routines get
<
dt><
code>ap_hook_http_method</
code></
dt>
<
dd>retrieve the http method from a request. (legacy)</
dd>
<
dt><
code>ap_hook_auth_checker</
code></
dt>
<
dd>check if the resource requires authorization</
dd>
<
dt><
code>ap_hook_access_checker</
code></
dt>
<
dd>check for module-specific restrictions</
dd>
<
dt><
code>ap_hook_check_user_id</
code></
dt>
<
dd>check the user-id and password</
dd>
<
dt><
code>ap_hook_default_port</
code></
dt>
<
dd>retrieve the default port for the server</
dd>
<
dt><
code>ap_hook_pre_connection</
code></
dt>
<
dd>do any setup required just before processing, but after
<
dt><
code>ap_hook_process_connection</
code></
dt>
<
dd>run the correct protocol</
dd>
<
dt><
code>ap_hook_child_init</
code></
dt>
<
dd>call as soon as the child is started</
dd>
<
dt><
code>ap_hook_create_request</
code></
dt>
<
dt><
code>ap_hook_fixups</
code></
dt>
<
dd>last chance to modify things before generating content</
dd>
<
dt><
code>ap_hook_handler</
code></
dt>
<
dd>generate the content</
dd>
<
dt><
code>ap_hook_header_parser</
code></
dt>
<
dd>lets modules look at the headers, not used by most modules, because
they use <
code>post_read_request</
code> for this</
dd>
<
dt><
code>ap_hook_insert_filter</
code></
dt>
<
dd>to insert filters into the filter chain</
dd>
<
dt><
code>ap_hook_log_transaction</
code></
dt>
<
dd>log information about the request</
dd>
<
dt><
code>ap_hook_optional_fn_retrieve</
code></
dt>
<
dd>retrieve any functions registered as optional</
dd>
<
dt><
code>ap_hook_post_read_request</
code></
dt>
<
dd>called after reading the request, before any other phase</
dd>
<
dt><
code>ap_hook_quick_handler</
code></
dt>
<
dd>called before any request processing, used by cache modules.</
dd>
<
dt><
code>ap_hook_translate_name</
code></
dt>
<
dd>translate the URI into a filename</
dd>
<
dt><
code>ap_hook_type_checker</
code></
dt>
<
dd>determine
and/
or set the doc type</
dd>
</
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>This section is experimental!</
strong><
br />Comments placed here should not be expected
to last beyond the testing phase of this system, nor do we in any way guarantee that we'll read them.</
div>
var disqus_shortname = 'httpd'; d.write('<div id="disqus_thread"><\/div>'); d.write('<div id="disqus_thread">Comments are disabled for this page at the moment.<\/div>'); //--><!]]></
script></
div><
div id="footer">
if (typeof(prettyPrint) !== 'undefined') {