modules.html revision bf8889c98dd1b7b4daf701cdf96652d5c9afb837
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<HTML>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<HEAD>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<TITLE>Converting Modules from Apache 1.3 to Apache 2.0</TITLE>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding</HEAD>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<!-- Background white, links blue (unvisited), navy (visited), red (active) -->
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<BODY
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding BGCOLOR="#FFFFFF"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding TEXT="#000000"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding LINK="#0000FF"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding VLINK="#000080"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ALINK="#FF0000"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<!--#include virtual="header.html" -->
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<H1 ALIGN="CENTER">From Apache 1.3 to Apache 2.0<br>Modules</H1>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<p>
f3091cedd4abeda1026d9117c34e8f625754e8aefieldingThis is a first attempt at writing the lessons I learned when trying to convert the mod_mmap_static module to Apache 2.0. It's by no means definitive and probably won't even be correct in some ways, but it's a start.
f3091cedd4abeda1026d9117c34e8f625754e8aefielding</p>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<hr>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<h2>The easier changes...
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</h2>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<h3>Cleanup Routines</h3>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<p>
f3091cedd4abeda1026d9117c34e8f625754e8aefieldingThese now need to be of type ap_status_t and return a value of that type. Normally the return value will be APR_SUCCESS unless there is some need to signal an error in the cleanup. Be aware that even though you signal an error not all code yet checks and acts upon the error.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</p>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<h3>Initialisation Routines</h3>
64185f9824e42f21ca7b9ae6c004484215c031a7rbb
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<p>
f3091cedd4abeda1026d9117c34e8f625754e8aefieldingThese should now be renamed to better signify where they sit in the overall process. So the name gets a small change from mmap_init to mmap_post_config. The arguments passed have undergone a radical change and now look like
f3091cedd4abeda1026d9117c34e8f625754e8aefielding</p>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<ul style="list-style:none">
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<li>ap_context_t *p,</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<li>ap_context_t *plog,</li>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<li>ap_context_t *ptemp,</li>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<li>server_rec *s</li>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding</ul>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<p>
f3091cedd4abeda1026d9117c34e8f625754e8aefieldingThroughout Apache the old pools have been replced by the ap_context_t, though their use remains remarkably similar.
f3091cedd4abeda1026d9117c34e8f625754e8aefielding</p>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<h3>Data Types</h3>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingA 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.
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<ul style="list-style:none">
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<li>pool becomes ap_context_t</li>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<li>table becomes ap_table_t</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</ul>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<hr>
f3091cedd4abeda1026d9117c34e8f625754e8aefielding
f3091cedd4abeda1026d9117c34e8f625754e8aefielding<h2>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingThe <em>messier</em> changes...
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</h2>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<h3>Register Hooks</h3>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingThe 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 will be called in.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingThis is the code that was added to mod_mmap_static
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<pre>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void register_hooks(void)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding static const char * const aszPre[]={ "http_core.c",NULL };
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_hook_post_config(mmap_post_config,NULL,NULL,HOOK_MIDDLE);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_hook_translate_name(mmap_static_xlat,aszPre,NULL,HOOK_LAST);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding};
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</pre>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingThis 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?
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<p><strong>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingap_hook_[phase_name](function_name, predecessors, successors, position);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</strong></p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingThere are 3 hook positions defined...
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<ul style="list-style:none">
d0a46853bff16e9598a3298f262b0d3fd58d6c53martin<li>HOOK_FIRST</li>
c53a68af52e2428d833746388b412fb4793759b2trawick<li>HOOK_MIDDLE</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<li>HOOK_LAST</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</ul>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingTo 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 run (successors).
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingIn 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 HOOK_LAST.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<h3>Module Definition</h3>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingThere are now a lot fewer stages to worry about when creating your module definition. The old defintion looked like
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</p>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<pre>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingmodule MODULE_VAR_EXPORT [module_name]_module =
878c5eb6d9ffca5069d9f140184a133723000f0cwrowe{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding STANDARD_MODULE_STUFF,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* initializer */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* dir config creater */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* dir merger --- default is to override */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* server config */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* merge server config */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* command handlers */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* handlers */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* filename translation */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* check_user_id */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* check auth */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* check access */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* type_checker */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* fixups */
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein /* logger */
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein /* header parser */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* child_init */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* child_exit */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* post read-request */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb};
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein</pre>
314ad8e9005a0266a2e7f61a44834c58893293b4rbb<p>
cccd31fa4a72fe23cc3249c06db181b274a55a69gsteinThe new structure is a great deal simpler...
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein</p>
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein<pre>
cccd31fa4a72fe23cc3249c06db181b274a55a69gsteinmodule MODULE_VAR_EXPORT [module_name]_module =
1860b2b5f1de31f8cf9d95f1b394fe98c8dbfab7rbb{
1860b2b5f1de31f8cf9d95f1b394fe98c8dbfab7rbb STANDARD20_MODULE_STUFF,
1860b2b5f1de31f8cf9d95f1b394fe98c8dbfab7rbb /* create per-directory config structures */
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein /* merge per-directory config structures */
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe /* create per-server config structures */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* merge per-server config structures */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb /* command handlers */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* handlers */
bb65aeae7af1d33b64252bbc1b966942d757ac60wrowe /* register hooks */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb };
48d7c43629323c8d5ee9f7bd0d194de0a376b391rbb</pre>
bb65aeae7af1d33b64252bbc1b966942d757ac60wrowe<p>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbSome of these read directly across, some don't. I'll try to summarise what should be done below.
48d7c43629323c8d5ee9f7bd0d194de0a376b391rbb</p>
bb65aeae7af1d33b64252bbc1b966942d757ac60wrowe<p>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbThe stages that read directly across :
48d7c43629323c8d5ee9f7bd0d194de0a376b391rbb</p>
bb65aeae7af1d33b64252bbc1b966942d757ac60wrowe<ul style="list-style:none">
cf721750997514b9cbed94bf3672ff6b3e2c2132trawick<li>
48d7c43629323c8d5ee9f7bd0d194de0a376b391rbb/* dir config creater */ ==> /* create per-directory config structures */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* server config */ ==> /* create per-server config structures */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* dir merger */ ==> /* merge per-directory config structures */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* merge server config */ ==> /* merge per-server config structures */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<li>
c53a68af52e2428d833746388b412fb4793759b2trawick/* command table */ ==> /* command ap_table_t */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<li>
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm/* handlers */ ==> /* handlers */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</li>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb</ul>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb<P>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbThe remainder of the old functions should be registered as hooks. There are the following hook stages defined so far...
c53a68af52e2428d833746388b412fb4793759b2trawick</P>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb<ul style="list-style:none">
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb<li>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbap_hook_post_config <em>(this is where the old _init routines get registered)</em>
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm</li>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb<li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingap_hook_http_method
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<li>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbap_hook_open_logs
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb</li>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb<li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingap_hook_auth_checker
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingap_hook_default_port
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding</li>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding<li>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbap_hook_access_checker
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb</li>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb<li>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbap_hook_process_connection
06e2d72d72d35442e1ba8cfe9f343ac0fb2b8cffdreid</li>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb<li>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbap_hook_child_init_hook
06e2d72d72d35442e1ba8cfe9f343ac0fb2b8cffdreid</li>
b7faa60a6790e84452c16e5dfb3bde2c52a1030dtrawick
c330df4777ee0ff23f104003559a5c4c9e0e5070trawick<!--#include virtual="footer.html" -->
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb
06e2d72d72d35442e1ba8cfe9f343ac0fb2b8cffdreid</body>
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb</html>
446b877d2ab69d9bbcd9152a2d54814f05f1c00brbb
06e2d72d72d35442e1ba8cfe9f343ac0fb2b8cffdreid
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb
06e2d72d72d35442e1ba8cfe9f343ac0fb2b8cffdreid
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb