326N/A<!
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 326N/A <
title>Converting Modules from Apache 1.3 to Apache 2.0</
title>
326N/A <!-- Background white, links blue (unvisited), navy (visited), red (active) --> 326N/A <
body bgcolor="#FFFFFF" text="#000000" link="#0000FF" 326N/A vlink="#000080" alink="#FF0000">
326N/A <
h1 align="CENTER">From Apache 1.3 to Apache 2.0<
br />
326N/A <
p>This is a first attempt at writing the lessons I learned
326N/A when trying to convert the mod_mmap_static module to Apache
326N/A 2.0. It's by no means definitive and probably won't even be
326N/A correct in some ways, but it's a start.</
p>
326N/A <
h2>The easier changes...</
h2>
326N/A <
h3>Cleanup Routines</
h3>
326N/A <
p>These now need to be of type apr_status_t and return a value
326N/A of that type. Normally the return value will be APR_SUCCESS
326N/A unless there is some need to signal an error in the cleanup. Be
326N/A aware that even though you signal an error not all code yet
851N/A checks and acts upon the error.</
p>
326N/A <
h3>Initialisation Routines</
h3>
493N/A <
p>These should now be renamed to better signify where they sit
326N/A in the overall process. So the name gets a small change from
326N/A mmap_init to mmap_post_config. The arguments passed have
851N/A undergone a radical change and now look like</
p>
326N/A <
ul style="list-style:none">
326N/A <
li>apr_pool_t *p,</
li>
326N/A <
li>apr_pool_t *plog,</
li>
493N/A <
li>apr_pool_t *ptemp,</
li>
<
p>A lot of the data types have been moved into the APR. 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>
<
ul style="list-style:none">
<
li>pool becomes apr_pool_t</
li>
<
li>table becomes apr_table_t</
li>
<
h2>The <
em>messier</
em> changes...</
h2>
<
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, static void register_hooks(void). 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 mod_mmap_static:</
p>
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 post_config stage (virtually every module will need this
one) and one for the translate_name phase. note that while
there are different function names the format of each is
identical. So what is the format?</
p>
<
p><
strong>ap_hook_[phase_name](function_name, predecessors,
successors, position);</
strong></
p>
<
p>There are 3 hook positions defined...</
p>
<
ul style="list-style:none">
<
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 mod_mmap_static case I didn't care about the
post_config stage, but the mmap_static_xlat MUST 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
<
h3>Module Definition</
h3>
<
p>There are now a lot fewer stages to worry about when
creating your module definition. The old defintion looked
module MODULE_VAR_EXPORT [module_name]_module =
/* dir merger --- default is to override */
/* merge server config */
/* filename translation */
<
p>The new structure is a great deal simpler...</
p>
module MODULE_VAR_EXPORT [module_name]_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>
<
ul style="list-style:none">
<
li>/* dir config creater */ ==> /* create per-directory
config structures */</
li>
<
li>/* server config */ ==> /* create per-server config
<
li>/* dir merger */ ==> /* merge per-directory config
<
li>/* merge server config */ ==> /* merge per-server
config structures */</
li>
<
li>/* command table */ ==> /* command apr_table_t */</
li>
<
li>/* handlers */ ==> /* handlers */</
li>
<
p>The remainder of the old functions should be registered as
hooks. There are the following hook stages defined so
<
ul style="list-style:none">
<
li>ap_hook_post_config <
em>(this is where the old _init
routines get registered)</
em></
li>
<
li>ap_hook_http_method <
em>(retrieve the http method from a
request. (legacy))</
em></
li>
<
li>ap_hook_open_logs <
em>(open any specified logs)</
em></
li>
<
li>ap_hook_auth_checker <
em>(check if the resource requires
<
li>ap_hook_access_checker <
em>(check for module-specific
<
li>ap_hook_check_user_id <
em>(check the user-id and
<
li>ap_hook_default_port <
em>(retrieve the default port for
<
li>ap_hook_pre_connection <
em>(do any setup required just
before processing, but after accepting)</
em></
li>
<
li>ap_hook_process_connection <
em>(run the correct
<
li>ap_hook_child_init <
em>(call as soon as the child is
<
li>ap_hook_create_request <
em>(??)</
em></
li>
<
li>ap_hook_fixups <
em>(last chance to modify things before
generating content)</
em></
li>
<
li>ap_hook_handler <
em>(generate the content)</
em></
li>
<
li>ap_hook_header_parser <
em>(let's modules look at the
headers, not used by most modules, because they use
post_read_request for this.)</
em></
li>
<
li>ap_hook_insert_filter <
em>(to insert filters into the
<
li>ap_hook_log_transaction <
em>(log information about the
<
li>ap_hook_optional_fn_retrieve <
em>(retrieve any functions
registered as optional)</
em></
li>
<
li>ap_hook_post_read_request <
em>(called after reading the
request, before any other phase)</
em></
li>
<
li>ap_hook_quick_handler <
em>(??)</
em></
li>
<
li>ap_hook_translate_name <
em>(translate the URI into a
<
li>ap_hook_type_checker <
em>(determine
and/
or set the doc