modguide.xml revision 8d8ddf62616c32c6f7760d1e8112db8f9ce109ba
97a9a944b5887e91042b019776c41d5dd74557aferikabele<!DOCTYPE manualpage SYSTEM "/style/manualpage.dtd">
97a9a944b5887e91042b019776c41d5dd74557aferikabele<?xml-stylesheet type="text/xsl" href="/style/manual.en.xsl"?>
a945f35eff8b6a88009ce73de6d4c862ce58de3cslive<!-- $LastChangedRevision$ -->
b686b6a420bde7f78c416b90be11db94cb789979nd Licensed to the Apache Software Foundation (ASF) under one or more
b686b6a420bde7f78c416b90be11db94cb789979nd contributor license agreements. See the NOTICE file distributed with
b686b6a420bde7f78c416b90be11db94cb789979nd this work for additional information regarding copyright ownership.
b686b6a420bde7f78c416b90be11db94cb789979nd The ASF licenses this file to You under the Apache License, Version 2.0
b686b6a420bde7f78c416b90be11db94cb789979nd (the "License"); you may not use this file except in compliance with
b686b6a420bde7f78c416b90be11db94cb789979nd the License. You may obtain a copy of the License at
b686b6a420bde7f78c416b90be11db94cb789979nd Unless required by applicable law or agreed to in writing, software
b686b6a420bde7f78c416b90be11db94cb789979nd distributed under the License is distributed on an "AS IS" BASIS,
4b5981e276e93df97c34e4da05ca5cf8bbd937dand WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd See the License for the specific language governing permissions and
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd limitations under the License.
b686b6a420bde7f78c416b90be11db94cb789979nd <title>Developing modules for the Apache HTTP Server 2.4</title>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<p>This document explains how you can develop modules for the Apache HTTP
06ba4a61654b3763ad65f52283832ebf058fdf1csliveServer 2.4</p>
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42nd<seealso><a href="request.html">Request Processing in Apache 2.4</a></seealso>
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd<seealso><a href="hooks.html">Apache 2.x Hook Functions</a></seealso>
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd<section id="what"><title>What we will be discussing in this document</title>
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2ndThis document will discuss how you can easily create modules for the Apache
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2ndHTTP Server 2.4, by exploring an example module called
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd<code>mod_example</code>. In the first part of this document, the purpose
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2ndof this module will be to calculate and print out various digest values for
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndexisting files on your web server, whenever we access the URL <code>
5b10fd3977e6dfff19afe770e612e276962f7950ndhttp://hostname/filename.sum</code>. For instance, if we want to know the
5b10fd3977e6dfff19afe770e612e276962f7950ndMD5 digest value of the file located at <code>
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndhttp://www.example.com/index.html</code>, we would visit <code>
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2ndIn the second part of this document, which deals with configuration
7fa75a06a4fee19e995c069ee00310455d1452e1pquernadirective and context awareness, we will be looking at a module that simply
7fa75a06a4fee19e995c069ee00310455d1452e1pquernawrite out its own configuration to the client.
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2ndFirst and foremost, you are expected to have a basic knowledge of how the C
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2ndprogramming language works. In most cases, we will try to be as pedagogical
2aff288113d772cedca6add888eb643afffe9fb1ndas possible and link to documents describing the functions used in the
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2ndexamples, but there are also many cases where it is necessary to either
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2ndjust assume that "it works" or do some digging yourself into what the hows
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2ndand whys of various function calls.
2aff288113d772cedca6add888eb643afffe9fb1ndLastly, you will need to have a basic understanding of how modules are
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndloaded and configured in the Apache HTTP Server, as well as how to get the headers for
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndApache if you do not have them already, as these are needed for compiling
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndnew modules.
2aff288113d772cedca6add888eb643afffe9fb1nd<section id="compiling"><title>Compiling your module</title>
2aff288113d772cedca6add888eb643afffe9fb1ndTo compile the source code we are building in this document, we will be
2aff288113d772cedca6add888eb643afffe9fb1ndusing <a href="/programs/apxs.html">APXS</a>. Assuming your source file
2aff288113d772cedca6add888eb643afffe9fb1ndis called mod_example.c, compiling, installing and activating the module is
2aff288113d772cedca6add888eb643afffe9fb1ndas simple as:
bc525661d031758c0a4e771543372b4869ca86aandapxs -i -a -c mod_example.c
2aff288113d772cedca6add888eb643afffe9fb1nd<img src="/images/build_a_mod_3.png" alt="Module name tags"/><br/>
42af92a661a06b3cebc88d585aad75064a309d51ndEvery module starts with the same declaration, or name tag if you will,
42af92a661a06b3cebc88d585aad75064a309d51ndthat defines a module as <em>a separate entity within Apache</em>:</p>
2aff288113d772cedca6add888eb643afffe9fb1nd<!-- BEGIN EXAMPLE CODE -->
2aff288113d772cedca6add888eb643afffe9fb1ndmodule AP_MODULE_DECLARE_DATA example_module =
2aff288113d772cedca6add888eb643afffe9fb1nd STANDARD20_MODULE_STUFF,
64c02f1310b7747423957823ee09fb3608430f89nd create_dir_conf, /* Per-directory configuration handler */
aa0b2780958e9b1467c9d0153a05738e399811a5nd merge_dir_conf, /* Merge handler for per-directory configurations */
2aff288113d772cedca6add888eb643afffe9fb1nd create_svr_conf, /* Per-server configuration handler */
2aff288113d772cedca6add888eb643afffe9fb1nd merge_svr_conf, /* Merge handler for per-server configurations */
2aff288113d772cedca6add888eb643afffe9fb1nd directives, /* Any directives we may have for httpd */
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42nd register_hooks /* Our hook registering function */
2aff288113d772cedca6add888eb643afffe9fb1nd</highlight>
2aff288113d772cedca6add888eb643afffe9fb1nd<!-- END EXAMPLE CODE -->
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndThis bit of code lets the server know that we have now registered a new module
2aff288113d772cedca6add888eb643afffe9fb1ndin the system, and that its name is <code>example_module</code>. The name
e67fa8d3f161e595dd448fc24a591ee17ae59131ndof the module is used primarily for two things:<br/>
bf94bedcb62d7f0b926f4286069def5ee6b07b60nd<li>Letting the server know how to load the module using the LoadModule</li>
bf94bedcb62d7f0b926f4286069def5ee6b07b60nd<li>Setting up a namespace for the module to use in configurations</li>
bbcbf978a3074512c627c797fedcb30eeab7b39dsliveFor now, we're only concerned with the first purpose of the module name,
ee5db395bc3723609919edfa96af387eea37c491jimwhich comes into play when we need to load the module:
e55e60efce8a3e2139132c1d6ad9f6f0d2976614nd</highlight>
7f3fdc63be07f2ad39e01a44e68e9324998a5c03sliveIn essence, this tells the server to open up <code>mod_example.so</code> and look for a module
75585bd48fe0f30483dba4762e61edf39ea3e0f6ndWithin this name tag of ours is also a bunch of references to how we would
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndlike to handle things: Which directives do we respond to in a configuration
03a4ff9ac4c9b8009249010e7c53bb86ff05915andfile or .htaccess, how do we operate within specific contexts, and what
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndhandlers are we interested in registering with the Apache HTTP service. We'll
3b58542e01ec69422f3086db5825a12fc77b726endreturn to all these elements later in this document.
2aff288113d772cedca6add888eb643afffe9fb1nd<section id="hooking"><title>Getting started: Hooking into the server</title>
2aff288113d772cedca6add888eb643afffe9fb1nd<section id="hook_intro"><title>An introduction to hooks</title>
2aff288113d772cedca6add888eb643afffe9fb1ndWhen handling requests in Apache HTTP Server 2.4, the first thing you will need to do is
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndcreate a hook into the request handling process. A hook is essentially a
08842292d2f1550b40ae73e0dafc7641c5955c82ndmessage telling the server that you are willing to either serve or at least
2aff288113d772cedca6add888eb643afffe9fb1ndtake a glance at certain requests given by clients. All handlers, whether
d2b809e5d72658bff23819d8b77f20e4939af541ndit's mod_rewrite, mod_authn_*, mod_proxy and so on, are hooked into
2aff288113d772cedca6add888eb643afffe9fb1ndspecific parts of the request process. As you are probably aware, modules
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndserve different purposes; Some are authentication/authorization handlers,
2aff288113d772cedca6add888eb643afffe9fb1ndothers are file or script handlers while some third modules rewrite URIs or
2aff288113d772cedca6add888eb643afffe9fb1ndproxies content. Furthermore, in the end, it is up to the user of the server
2aff288113d772cedca6add888eb643afffe9fb1ndhow and when each module will come into place. Thus, the server itself does not
2aff288113d772cedca6add888eb643afffe9fb1ndpresume to know which module is responsible for handling a specific
2aff288113d772cedca6add888eb643afffe9fb1ndrequest, and will ask each module whether they have an interest in a given
2aff288113d772cedca6add888eb643afffe9fb1ndrequest or not. It is then up to each module to either gently decline
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndserving a request, accept serving it or flat out deny the request from
c023f60e35022146373e40249f0c8c8d623b6fcfndbeing served, as authentication/authorization modules do: <br/>
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42nd<img src="/images/build_a_mod_2.png" alt="Hook handling in httpd"/><br/>
a43bfa789f4e52dde53ae8e53fa0427b5c1cf977ndTo make it a bit easier for handlers such as our mod_example to know
a43bfa789f4e52dde53ae8e53fa0427b5c1cf977ndwhether the client is requesting content we should handle or not, the server
101bf3584c853027d9e51df6edfff5ff70c80238jimhas directives for hinting to modules whether their assistance is needed or
73ba54c33b4fcad0e13005e10ea8648c9fe4265bndnot. Two of these are <directive module="mod_mime">AddHandler</directive>
73ba54c33b4fcad0e13005e10ea8648c9fe4265bndand <directive module="core">SetHandler</directive>. Let's take a look at
73ba54c33b4fcad0e13005e10ea8648c9fe4265bndan example using <directive module="mod_mime">AddHandler</directive>. In
73ba54c33b4fcad0e13005e10ea8648c9fe4265bndour example case, we want every request ending with .sum to be served by
73ba54c33b4fcad0e13005e10ea8648c9fe4265bnd<code>mod_example</code>, so we'll add a configuration directive that tells
73ba54c33b4fcad0e13005e10ea8648c9fe4265bndthe server to do just that:
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42ndAddHandler example-handler .sum
2aff288113d772cedca6add888eb643afffe9fb1nd</highlight>
2aff288113d772cedca6add888eb643afffe9fb1ndWhat this tells the server is the following: <em>Whenever we receive a request
2aff288113d772cedca6add888eb643afffe9fb1ndfor a URI ending in .sum, we are to let all modules know that we are
2aff288113d772cedca6add888eb643afffe9fb1ndlooking for whoever goes by the name of "example-handler" </em>.
2aff288113d772cedca6add888eb643afffe9fb1ndThus, when a request is being served that ends in .sum, the server will let all
2aff288113d772cedca6add888eb643afffe9fb1ndmodules know, that this request should be served by "example-handler
2aff288113d772cedca6add888eb643afffe9fb1nd". As you will see later, when we start building mod_example, we will
2aff288113d772cedca6add888eb643afffe9fb1ndcheck for this handler tag relayed by <code>AddHandler</code> and reply to
2aff288113d772cedca6add888eb643afffe9fb1ndthe server based on the value of this tag.
80d3dc69b0e6ad772135f6a78af3d16bd6cccc42nd<section id="hook_declaration"><title>Hooking into httpd</title>
2aff288113d772cedca6add888eb643afffe9fb1ndTo begin with, we only want to create a simple handler, that replies to the
2aff288113d772cedca6add888eb643afffe9fb1ndclient browser when a specific URL is requested, so we won't bother setting
2aff288113d772cedca6add888eb643afffe9fb1ndup configuration handlers and directives just yet. Our initial module
2aff288113d772cedca6add888eb643afffe9fb1nddefinition will look like this:</p>
2aff288113d772cedca6add888eb643afffe9fb1nd<!-- BEGIN EXAMPLE CODE -->
3b3b7fc78d1f5bfc2769903375050048ff41ff26ndmodule AP_MODULE_DECLARE_DATA example_module =
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd STANDARD20_MODULE_STUFF,
b686b6a420bde7f78c416b90be11db94cb789979nd register_hooks /* Our hook registering function */
<li><code>ap_hook_child_init</code>: Place a hook that executes when a child process is spawned (commonly used for initializing modules after the server has forked)</li>
<li><code>ap_hook_pre_config</code>: Place a hook that executes before any configuration data has been read (very early hook)</li>
<li><code>ap_hook_post_config</code>: Place a hook that executes after configuration has been parsed, but before the server has forked</li>
<li><code>ap_hook_translate_name</code>: Place a hook that executes when a URI needs to be translated into a filename on the server (think <code>mod_rewrite</code>)</li>
<li><code>r->handler (char*):</code> Contains the name of the handler the server is currently asking to do the handling of this request</li>
<li><code>r->filename (char*):</code> Contains the translated filename the client is requesting</li>
<li><code>r->connection (conn_rec*):</code> A record containing information about the current connection</li>
<li><code>r->pool (apr_pool_t*)</code>: The memory pool of this request. We'll discuss this in the "
A complete list of all the values contained with in the <code>request_req</code> structure can be found in
the <a href="http://svn.apache.org/repos/asf/httpd/httpd/trunk/include/httpd.h"><code>httpd.h</code></a> header
file or at <a href="http://ci.apache.org/projects/httpd/trunk/doxygen/structrequest__rec.html">http://ci.apache.org/projects/httpd/trunk/doxygen/structrequest__rec.html</a>.
<li><code>DONE</code>: We handled this request and the server should just close this thread without further processing</li>
href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__PROTO.html#gac827cd0537d2b6213a7c06d7c26cc36e">
<a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__PROTO.html#ga5e91eb6ca777c9a427b2e82bf1eeb81d">ap_rprintf</a></code>: <br/>
<a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__PROTO.html#gaa2f8412c400197338ec509f4a45e4579">ap_set_content_type</a>(request_req *r, const char *type)</code>: <br/>
<highlight language="c">ap_set_content_type(r, "text/plain"); /* force a raw text output */</highlight>
memory pool that gets cleaned up when its scope ends, e.g. when a request
<li><code>void* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__pools.html#ga85f1e193c31d109affda72f9a92c6915">apr_palloc</a>(
apr_pool_t *p, apr_size_t size)</code>: Allocates <code>size</code> number of bytes in the pool for you</li>
<li><code>void* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__pools.html#gaf61c098ad258069d64cdf8c0a9369f9e">apr_pcalloc</a>(
apr_pool_t *p, apr_size_t size)</code>: Allocates <code>size</code> number of bytes in the pool for you and sets all bytes to 0</li>
<li><code>char* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__strings.html#gabc79e99ff19abbd7cfd18308c5f85d47">apr_pstrdup</a>(
apr_pool_t *p, const char *s)</code>: Creates a duplicate of the string <code>s</code>. This is useful for copying constant values so you can edit them</li>
<li><code>char* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__strings.html#ga3eca76b8d293c5c3f8021e45eda813d8">apr_psprintf</a>(
apr_pool_t *p, const char *fmt, ...)</code>: Similar to <code>sprintf</code>, except the server supplies you with an appropriately allocated target variable</li>
<a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__apr__tables.html#gad7ea82d6608a4a633fc3775694ab71e4">apr_table_t</a> *GET; <em>
</em><a href="http://ci.apache.org/projects/httpd/trunk/doxygen/structapr__array__header__t.html">apr_array_header_t</a>*POST;
<a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__SCRIPT.html#gaed25877b529623a4d8f99f819ba1b7bd">
</em><a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__DAEMON.html#ga9d426b6382b49754d4f87c55f65af202">
(finfo.filetype != APR_NOFILE)
&& !(finfo.filetype & APR_DIR)
ap_rprintf(r, "<b>Size:</b> %u bytes<br/>", finfo.size);
apr_md5_final(digest.chr, &md5);
ap_rprintf(r, "%08x", digest.num[n]);
ap_rputs("<br/><a href='?digest=sha1'>View the SHA1 hash instead</a>", r);
apr_sha1_final(digest.chr, &sha1);
ap_rprintf(r, "%08x", digest.num[n]);
ap_rputs("<br/><a href='?digest=md5'>View the MD5 hash instead</a>", r);
const char *path; /* Some path to...something */
const char *path; /* Some path to...something */
ap_rprintf(r, "Enabled: %u\n", config.enabled);
ap_rprintf(r, "Path: %s\n", config.path);
ap_rprintf(r, "TypeOfAction: %x\n", config.typeOfAction);
config.enabled = 1;
config.typeOfAction = 0x00;
into the module, but by using either the httpd.conf file or possibly a
AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
<li><code><a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__CONFIG.html#ga07c7d22ae17805e61204463326cf9c34">AP_INIT_TAKE1</a></code>: This is a macro that tells the server that this directive takes one and only one argument.
If we required two arguments, we could use the macro <code><a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__CONFIG.html#gafaec43534fcf200f37d9fecbf9247c21">AP_INIT_TAKE2</a></code> and so on (refer to httpd_conf.h
<li><code>exampleEnabled</code>: This is the name of our directive. More precisely, it is what the user must put in his/her
<li><code>example_set_enabled</code>: This is a reference to a C function that parses the directive and sets the configuration
<li><code>RSRC_CONF</code>: This tells the server where the directive is permitted. We'll go into details on this value in the
later chapters, but for now, <code>RSRC_CONF</code> means that the server will only accept these directives in a server context.</li>
<li><code>"Enable or disable...."</code>: This is simply a brief description of what the directive does.</li>
if(!strcasecmp(arg, "on")) config.enabled = 1;
else config.enabled = 0;
config.path = arg;
if(!strcasecmp(arg1, "file")) config.typeOfAction = 0x01;
else config.typeOfAction = 0x02;
if(!strcasecmp(arg2, "deny")) config.typeOfAction += 0x10;
else config.typeOfAction += 0x20;
/* mod_example_config_simple.c: */
#include <stdio.h>
#include "apr_hash.h"
#include "ap_config.h"
#include "ap_provider.h"
#include "httpd.h"
#include "http_core.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "http_request.h"
const char *path; /* Some path to...something */
if(!strcasecmp(arg, "on")) config.enabled = 1;
else config.enabled = 0;
config.path = arg;
if(!strcasecmp(arg1, "file")) config.typeOfAction = 0x01;
else config.typeOfAction = 0x02;
if(!strcasecmp(arg2, "deny")) config.typeOfAction += 0x10;
else config.typeOfAction += 0x20;
AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
AP_INIT_TAKE1("examplePath", example_set_path, NULL, RSRC_CONF, "The path to whatever"),
AP_INIT_TAKE2("exampleAction", example_set_action, NULL, RSRC_CONF, "Special action value!"),
ap_rprintf(r, "Enabled: %u\n", config.enabled);
ap_rprintf(r, "Path: %s\n", config.path);
ap_rprintf(r, "TypeOfAction: %x\n", config.typeOfAction);
config.enabled = 1;
config.typeOfAction = 3;
In our httpd.conf file, we can now change the hard-coded configuration by
RewriteCond %{HTTP_HOST} ^example.com$
RewriteRule (.*) http://www.example.com/$1
RewriteRule ^foobar$ index.php?foobar=true
<li>Inside <code>/var/www</code>, all requests for <code>http://example.com</code> must go to <code>http://www.example.com</code></li>
<li>Inside <code>/var/www/sub</code>, all requests for <code>foobar</code> must go to <code>index.php?foobar=true</code></li>
example_config *config = (example_config*) <a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__CONFIG.html#ga1093a5908a384eacc929b028c79f2a02">ap_get_module_config</a>(r->per_dir_config, &example_module);
example_config *config = (example_config*) ap_get_module_config(r->per_dir_config, &example_module);
AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
<li>Sets the configuration values according to the directives given for <code>/var/www/subdir</code></li>
<li><strong>Proposes a merge</strong> of the two configurations into a new configuration for <code>/var/www/subdir</code></li>
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <stdio.h>
#include "apr_hash.h"
#include "ap_config.h"
#include "ap_provider.h"
#include "httpd.h"
#include "http_core.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "http_request.h"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, ACCESS_CONF, "Enable or disable mod_example"),
AP_INIT_TAKE1("examplePath", example_set_path, NULL, ACCESS_CONF, "The path to whatever"),
AP_INIT_TAKE2("exampleAction", example_set_action, NULL, ACCESS_CONF, "Special action value!"),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=======================================================================================================================
=======================================================================================================================
=======================================================================================================================
=======================================================================================================================
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
example_config *config = (example_config *) ap_get_module_config(r->per_dir_config, &example_module);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
=======================================================================================================================
=======================================================================================================================
=======================================================================================================================
=======================================================================================================================
=======================================================================================================================
=======================================================================================================================
=======================================================================================================================
=======================================================================================================================
=======================================================================================================================
=======================================================================================================================