modguide.xml revision 57e8d28eb19a247139c0bd494a3be57dbac7ceed
97a9a944b5887e91042b019776c41d5dd74557aferikabele<?xml version='1.0' encoding='UTF-8' ?>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<!DOCTYPE manualpage SYSTEM "/style/manualpage.dtd">
97a9a944b5887e91042b019776c41d5dd74557aferikabele<?xml-stylesheet type="text/xsl" href="/style/manual.en.xsl"?>
b1ced323143ade589985456a78f3f64d6a6580c5yoshiki
b1ced323143ade589985456a78f3f64d6a6580c5yoshiki<!-- $LastChangedRevision$ -->
b1ced323143ade589985456a78f3f64d6a6580c5yoshiki
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<!--
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd Licensed to the Apache Software Foundation (ASF) under one or more
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd contributor license agreements. See the NOTICE file distributed with
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd this work for additional information regarding copyright ownership.
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd The ASF licenses this file to You under the Apache License, Version 2.0
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd (the "License"); you may not use this file except in compliance with
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd the License. You may obtain a copy of the License at
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd http://www.apache.org/licenses/LICENSE-2.0
52fff662005b1866a3ff09bb6c902800c5cc6dedjerenkrantz
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd Unless required by applicable law or agreed to in writing, software
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd distributed under the License is distributed on an "AS IS" BASIS,
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4b5981e276e93df97c34e4da05ca5cf8bbd937dand See the License for the specific language governing permissions and
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd limitations under the License.
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd-->
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd
7dc5a2d4a0c77f5bf5a95de92d68e43de7d8117anilgun<manualpage metafile="modguide.xml.meta">
7dc5a2d4a0c77f5bf5a95de92d68e43de7d8117anilgun<parentdocument href="./">Developer</parentdocument>
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd <title>Developing modules for the Apache HTTP Server 2.4</title>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<summary>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<p>This document explains how you can develop modules for the Apache HTTP
cea021a7fc2657b091df4d3b031c4254ec371dd7rbowenServer 2.4</p>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</summary>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirin<seealso><a href="request.html">Request Processing in Apache 2.4</a></seealso>
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirin<seealso><a href="hooks.html">Apache 2.x Hook Functions</a></seealso>
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirin
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirin<section id="introduction"><title>Introduction</title>
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirin<section id="what"><title>What we will be discussing in this document</title>
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirin<p>
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirinThis document will discuss how you can create modules for the Apache
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirinHTTP Server 2.4, by exploring an example module called
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirin<code>mod_example</code>. In the first part of this document, the purpose
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirinof this module will be to calculate and print out various digest values for
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirinexisting files on your web server, whenever we access the URL <code>
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirinhttp://hostname/filename.sum</code>. For instance, if we want to know the
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirinMD5 digest value of the file located at <code>
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirinhttp://www.example.com/index.html</code>, we would visit <code>
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirinhttp://www.example.com/index.html.sum</code>.
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirin</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
f0a393c5c2d7de58f447855369ad2fbfa254e544rbowen<p>
f0a393c5c2d7de58f447855369ad2fbfa254e544rbowenIn the second part of this document, which deals with configuration
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nddirective and context awareness, we will be looking at a module that simply
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndwrites out its own configuration to the client.
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</p>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</section>
117c1f888a14e73cdd821dc6c23eb0411144a41cnd
117c1f888a14e73cdd821dc6c23eb0411144a41cnd<section id="prerequisites"><title>Prerequisites</title>
117c1f888a14e73cdd821dc6c23eb0411144a41cnd<p>
117c1f888a14e73cdd821dc6c23eb0411144a41cndFirst and foremost, you are expected to have a basic knowledge of how the C
117c1f888a14e73cdd821dc6c23eb0411144a41cndprogramming language works. In most cases, we will try to be as pedagogical
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndas possible and link to documents describing the functions used in the
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sfexamples, but there are also many cases where it is necessary to either
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sfjust assume that "it works" or do some digging yourself into what the hows
7571ea383299910bead3e93e66246cb212a28d0figalicand whys of various function calls.
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sf</p>
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sf<p>
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sfLastly, you will need to have a basic understanding of how modules are
7571ea383299910bead3e93e66246cb212a28d0figalicloaded and configured in the Apache HTTP Server, as well as how to get the headers for
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sfApache if you do not have them already, as these are needed for compiling
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sfnew modules.
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sf</p>
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sf</section>
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sf<section id="compiling"><title>Compiling your module</title>
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sf<p>
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sfTo compile the source code we are building in this document, we will be
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sfusing <a href="/programs/apxs.html">APXS</a>. Assuming your source file
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sfis called mod_example.c, compiling, installing and activating the module is
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sfas simple as:
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sf</p>
1f0a28764a0520e43ce3a9130e56236fd67cd568igalic<example><pre>
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sfapxs -i -a -c mod_example.c
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sf</pre></example>
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sf
1e6708ac9aebbbd0ff63c2b93e6b97d50263a8bbrbowen</section>
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sf</section>
f6445f3ad1c82f9398dc8edd77093cd3e20b806cnoirin
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen<section id="basics"><title>Defining a module</title>
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen<p>
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen<img src="/images/build_a_mod_3.png" alt="Module name tags"/><br/>
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowenEvery module starts with the same declaration, or name tag if you will,
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowenthat defines a module as <em>a separate entity within Apache</em>:</p>
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen<!-- BEGIN EXAMPLE CODE -->
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen<highlight language="c">
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowenmodule AP_MODULE_DECLARE_DATA example_module =
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen{
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen STANDARD20_MODULE_STUFF,
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen create_dir_conf, /* Per-directory configuration handler */
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen merge_dir_conf, /* Merge handler for per-directory configurations */
9b3696c7ad70387ecd46e0f061b99d381dc392f9rbowen create_svr_conf, /* Per-server configuration handler */
b41a0dbe6310c576e96b7ea6910051fd84fb06f5sf merge_svr_conf, /* Merge handler for per-server configurations */
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd directives, /* Any directives we may have for httpd */
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd register_hooks /* Our hook registering function */
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd};
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</highlight>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<!-- END EXAMPLE CODE -->
635de20c16ef862bfc5b0d5f9ceb40ebeaddfdf3noirin
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<p>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndThis bit of code lets the server know that we have now registered a new module
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndin the system, and that its name is <code>example_module</code>. The name
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndof the module is used primarily for two things:<br/>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<ul>
9dd0b961340554104e5b6e837ddb3101f843cc3fcovener<li>Letting the server know how to load the module using the LoadModule</li>
9dd0b961340554104e5b6e837ddb3101f843cc3fcovener<li>Setting up a namespace for the module to use in configurations</li>
635de20c16ef862bfc5b0d5f9ceb40ebeaddfdf3noirin</ul>
635de20c16ef862bfc5b0d5f9ceb40ebeaddfdf3noirin<p>
635de20c16ef862bfc5b0d5f9ceb40ebeaddfdf3noirinFor now, we're only concerned with the first purpose of the module name,
635de20c16ef862bfc5b0d5f9ceb40ebeaddfdf3noirinwhich comes into play when we need to load the module:
9dd0b961340554104e5b6e837ddb3101f843cc3fcovener</p>
9dd0b961340554104e5b6e837ddb3101f843cc3fcovener<highlight language="config">
9dd0b961340554104e5b6e837ddb3101f843cc3fcovenerLoadModule example_module modules/mod_example.so
9dd0b961340554104e5b6e837ddb3101f843cc3fcovener</highlight>
635de20c16ef862bfc5b0d5f9ceb40ebeaddfdf3noirin<p>
25d988d92af8cf0d997aa1ebbc7cb11daa14d0becovenerIn essence, this tells the server to open up <code>mod_example.so</code> and look for a module
25d988d92af8cf0d997aa1ebbc7cb11daa14d0becovenercalled <code>example_module</code>.
9dd0b961340554104e5b6e837ddb3101f843cc3fcovener</p>
25d988d92af8cf0d997aa1ebbc7cb11daa14d0becovener<p>
25d988d92af8cf0d997aa1ebbc7cb11daa14d0becovenerWithin this name tag of ours is also a bunch of references to how we would
25d988d92af8cf0d997aa1ebbc7cb11daa14d0becovenerlike to handle things: Which directives do we respond to in a configuration
635de20c16ef862bfc5b0d5f9ceb40ebeaddfdf3noirinfile or .htaccess, how do we operate within specific contexts, and what
25d988d92af8cf0d997aa1ebbc7cb11daa14d0becovenerhandlers are we interested in registering with the Apache HTTP service. We'll
635de20c16ef862bfc5b0d5f9ceb40ebeaddfdf3noirinreturn to all these elements later in this document.
635de20c16ef862bfc5b0d5f9ceb40ebeaddfdf3noirin</p>
fa0f379e3845907d7c1087d885169e302239bdbbnd</section>
fa0f379e3845907d7c1087d885169e302239bdbbnd<section id="hooking"><title>Getting started: Hooking into the server</title>
fa0f379e3845907d7c1087d885169e302239bdbbnd<section id="hook_intro"><title>An introduction to hooks</title>
fa0f379e3845907d7c1087d885169e302239bdbbnd<p>
97a9a944b5887e91042b019776c41d5dd74557aferikabeleWhen handling requests in Apache HTTP Server 2.4, the first thing you will need to do is
06ba4a61654b3763ad65f52283832ebf058fdf1cslivecreate a hook into the request handling process. A hook is essentially a
25d988d92af8cf0d997aa1ebbc7cb11daa14d0becovenermessage telling the server that you are willing to either serve or at least
25d988d92af8cf0d997aa1ebbc7cb11daa14d0becovenertake a glance at certain requests given by clients. All handlers, whether
635de20c16ef862bfc5b0d5f9ceb40ebeaddfdf3noirinit's mod_rewrite, mod_authn_*, mod_proxy and so on, are hooked into
97a9a944b5887e91042b019776c41d5dd74557aferikabelespecific parts of the request process. As you are probably aware, modules
06ba4a61654b3763ad65f52283832ebf058fdf1csliveserve different purposes; Some are authentication/authorization handlers,
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndothers are file or script handlers while some third modules rewrite URIs or
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndproxies content. Furthermore, in the end, it is up to the user of the server
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndhow and when each module will come into place. Thus, the server itself does not
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndpresume to know which module is responsible for handling a specific
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndrequest, and will ask each module whether they have an interest in a given
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndrequest or not. It is then up to each module to either gently decline
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndserving a request, accept serving it or flat out deny the request from
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndbeing served, as authentication/authorization modules do: <br/>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<img src="/images/build_a_mod_2.png" alt="Hook handling in httpd"/><br/>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndTo make it a bit easier for handlers such as our mod_example to know
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndwhether the client is requesting content we should handle or not, the server
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndhas directives for hinting to modules whether their assistance is needed or
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndnot. Two of these are <directive module="mod_mime">AddHandler</directive>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndand <directive module="core">SetHandler</directive>. Let's take a look at
fa0f379e3845907d7c1087d885169e302239bdbbndan example using <directive module="mod_mime">AddHandler</directive>. In
fa0f379e3845907d7c1087d885169e302239bdbbndour example case, we want every request ending with .sum to be served by
fa0f379e3845907d7c1087d885169e302239bdbbnd<code>mod_example</code>, so we'll add a configuration directive that tells
fa0f379e3845907d7c1087d885169e302239bdbbndthe server to do just that:
fa0f379e3845907d7c1087d885169e302239bdbbnd</p>
fa0f379e3845907d7c1087d885169e302239bdbbnd<highlight language="config">
fa0f379e3845907d7c1087d885169e302239bdbbndAddHandler example-handler .sum
fa0f379e3845907d7c1087d885169e302239bdbbnd</highlight>
fa0f379e3845907d7c1087d885169e302239bdbbnd<p>
06ba4a61654b3763ad65f52283832ebf058fdf1csliveWhat this tells the server is the following: <em>Whenever we receive a request
06ba4a61654b3763ad65f52283832ebf058fdf1cslivefor a URI ending in .sum, we are to let all modules know that we are
06ba4a61654b3763ad65f52283832ebf058fdf1cslivelooking for whoever goes by the name of &quot;example-handler&quot; </em>.
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemThus, when a request is being served that ends in .sum, the server will let all
b115299831a7b4bbec58a88d708d8536e1ecd50csfmodules know, that this request should be served by &quot;example-handler
fa0f379e3845907d7c1087d885169e302239bdbbnd&quot;. As you will see later, when we start building mod_example, we will
fa0f379e3845907d7c1087d885169e302239bdbbndcheck for this handler tag relayed by <code>AddHandler</code> and reply to
b115299831a7b4bbec58a88d708d8536e1ecd50csfthe server based on the value of this tag.
b115299831a7b4bbec58a88d708d8536e1ecd50csf</p>
fa0f379e3845907d7c1087d885169e302239bdbbnd</section>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<section id="hook_declaration"><title>Hooking into httpd</title>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<p>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemTo begin with, we only want to create a simple handler, that replies to the
b115299831a7b4bbec58a88d708d8536e1ecd50csfclient browser when a specific URL is requested, so we won't bother setting
fa0f379e3845907d7c1087d885169e302239bdbbndup configuration handlers and directives just yet. Our initial module
fa0f379e3845907d7c1087d885169e302239bdbbnddefinition will look like this:</p>
b115299831a7b4bbec58a88d708d8536e1ecd50csf
b115299831a7b4bbec58a88d708d8536e1ecd50csf
fa0f379e3845907d7c1087d885169e302239bdbbnd<!-- BEGIN EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<highlight language="c">
06ba4a61654b3763ad65f52283832ebf058fdf1cslivemodule AP_MODULE_DECLARE_DATA example_module =
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem{
fa0f379e3845907d7c1087d885169e302239bdbbnd STANDARD20_MODULE_STUFF,
fa0f379e3845907d7c1087d885169e302239bdbbnd NULL,
06ba4a61654b3763ad65f52283832ebf058fdf1cslive NULL,
06ba4a61654b3763ad65f52283832ebf058fdf1cslive NULL,
fa0f379e3845907d7c1087d885169e302239bdbbnd NULL,
81785f72c9d133aef57ad6b02f248345d90239aapoirier NULL,
fa0f379e3845907d7c1087d885169e302239bdbbnd register_hooks /* Our hook registering function */
fa0f379e3845907d7c1087d885169e302239bdbbnd};
fa0f379e3845907d7c1087d885169e302239bdbbnd</highlight>
fa0f379e3845907d7c1087d885169e302239bdbbnd<!-- END EXAMPLE CODE -->
fa0f379e3845907d7c1087d885169e302239bdbbnd
fa0f379e3845907d7c1087d885169e302239bdbbnd
c6a2d6fa44f8698851dec5051ee3782c2913605fnd<p>This lets the server know that we are not interesting in anything fancy, we
06ba4a61654b3763ad65f52283832ebf058fdf1cslivejust want to hook onto the requests and possibly handle some of them. </p>
97a9a944b5887e91042b019776c41d5dd74557aferikabele
5ae30adbe59946de742ab0cd6be3b7457471a698takashi<p> The reference in our example declaration, <code>register_hooks</code>
97a9a944b5887e91042b019776c41d5dd74557aferikabeleis the name of a function we will create to manage how we hook onto the
97a9a944b5887e91042b019776c41d5dd74557aferikabelerequest process. In this example module, the function has just one purpose;
5ae30adbe59946de742ab0cd6be3b7457471a698takashiTo create a simple hook that gets called after all the rewrites, access
5ae30adbe59946de742ab0cd6be3b7457471a698takashicontrol etc has been handled. Thus, we will let the server know, that we want
97a9a944b5887e91042b019776c41d5dd74557aferikabeleto hook into its process as one of the last modules:
97a9a944b5887e91042b019776c41d5dd74557aferikabele</p>
97a9a944b5887e91042b019776c41d5dd74557aferikabele
97a9a944b5887e91042b019776c41d5dd74557aferikabele<!-- BEGIN EXAMPLE CODE -->
97a9a944b5887e91042b019776c41d5dd74557aferikabele<highlight language="c">
97a9a944b5887e91042b019776c41d5dd74557aferikabelestatic void register_hooks(apr_pool_t *pool)
06ba4a61654b3763ad65f52283832ebf058fdf1cslive{
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* Create a hook in the request handler, so we get called when a request arrives */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
97a9a944b5887e91042b019776c41d5dd74557aferikabele}
97a9a944b5887e91042b019776c41d5dd74557aferikabele</highlight>
74a6de79356cd15d2e47065087785e36dd65aa41nd<!-- END EXAMPLE CODE -->
97a9a944b5887e91042b019776c41d5dd74557aferikabele
97a9a944b5887e91042b019776c41d5dd74557aferikabele<p>
97a9a944b5887e91042b019776c41d5dd74557aferikabeleThe <code>example_handler</code> reference is the function that will handle
97a9a944b5887e91042b019776c41d5dd74557aferikabelethe request. We will discuss how to create a handler in the next chapter.
97a9a944b5887e91042b019776c41d5dd74557aferikabele</p>
97a9a944b5887e91042b019776c41d5dd74557aferikabele</section>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<section id="hook_others"><title>Other useful hooks</title>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<p>
5ae30adbe59946de742ab0cd6be3b7457471a698takashiHooking into the request handling phase is but one of many hooks that you
5ae30adbe59946de742ab0cd6be3b7457471a698takashican create. Some other ways of hooking are:
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<ul>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<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>
53d2fd50ff45e7c568f0588c742a5ef9edf8e275rbowen<li><code>ap_hook_pre_config</code>: Place a hook that executes before any configuration data has been read (very early hook)</li>
5ae30adbe59946de742ab0cd6be3b7457471a698takashi<li><code>ap_hook_post_config</code>: Place a hook that executes after configuration has been parsed, but before the server has forked</li>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<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>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<li><code>ap_hook_quick_handler</code>: Similar to <code>ap_hook_handler</code>, except it is run before any other request hooks (translation, auth, fixups etc)</li>
5ae30adbe59946de742ab0cd6be3b7457471a698takashi<li><code>ap_hook_log_transaction</code>: Place a hook that executes when the server is about to add a log entry of the current request</li>
5ae30adbe59946de742ab0cd6be3b7457471a698takashi</ul>
97a9a944b5887e91042b019776c41d5dd74557aferikabele
97a9a944b5887e91042b019776c41d5dd74557aferikabele</section>
97a9a944b5887e91042b019776c41d5dd74557aferikabele</section>
97a9a944b5887e91042b019776c41d5dd74557aferikabele
97a9a944b5887e91042b019776c41d5dd74557aferikabele<section id="handling"><title>Building a handler</title>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<p>
06ba4a61654b3763ad65f52283832ebf058fdf1csliveA handler is essentially a function that receives a callback when a request
06ba4a61654b3763ad65f52283832ebf058fdf1csliveto the server is made. It is passed a record of the current request (how it was
06ba4a61654b3763ad65f52283832ebf058fdf1cslivemade, which headers and requests were passed along, who's giving the
97a9a944b5887e91042b019776c41d5dd74557aferikabelerequest and so on), and is put in charge of either telling the server that it's
97a9a944b5887e91042b019776c41d5dd74557aferikabelenot interested in the request or handle the request with the tools provided.
97a9a944b5887e91042b019776c41d5dd74557aferikabele</p>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<section id="simple_handler"><title>A simple &quot;Hello, world!&quot;
97a9a944b5887e91042b019776c41d5dd74557aferikabelehandler</title>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<p>Let's start off by making a very simple request handler
97a9a944b5887e91042b019776c41d5dd74557aferikabelethat does the following:
97a9a944b5887e91042b019776c41d5dd74557aferikabele</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<ol>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<li>Check that this is a request that should be served by &quot;example-handler&quot;</li>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<li>Set the content type of our output to <code>text/html</code></li>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<li>Write &quot;Hello, world!&quot; back to the client browser</li>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<li>Let the server know that we took care of this request and everything went fine</li>
97a9a944b5887e91042b019776c41d5dd74557aferikabele</ol>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<p>
97a9a944b5887e91042b019776c41d5dd74557aferikabeleIn C code, our example handler will now look like this:
fb82af0f0cd7b58eef19c54b086131b7e1e1e749madhum</p>
4203a35c28d7c60adb7e9ef3be87aad34951c79asf
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<!-- BEGIN EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<highlight language="c">
06ba4a61654b3763ad65f52283832ebf058fdf1cslivestatic int example_handler(request_rec *r)
fa0f379e3845907d7c1087d885169e302239bdbbnd{
fa0f379e3845907d7c1087d885169e302239bdbbnd /* First off, we need to check if this is a call for the "example-handler" handler.
fa0f379e3845907d7c1087d885169e302239bdbbnd * If it is, we accept it and do our things, if not, we simply return DECLINED,
cea021a7fc2657b091df4d3b031c4254ec371dd7rbowen * and the server will try somewhere else.
fa0f379e3845907d7c1087d885169e302239bdbbnd */
fa0f379e3845907d7c1087d885169e302239bdbbnd if (!r->handler || strcmp(r->handler, "example-handler")) return (DECLINED);
37ef4b86270a8e58f87aa5fe558e3e65af97991ccovener
37ef4b86270a8e58f87aa5fe558e3e65af97991ccovener /* Now that we are handling this request, we'll write out "Hello, world!" to the client.
37ef4b86270a8e58f87aa5fe558e3e65af97991ccovener * To do so, we must first set the appropriate content type, followed by our output.
37ef4b86270a8e58f87aa5fe558e3e65af97991ccovener */
37ef4b86270a8e58f87aa5fe558e3e65af97991ccovener ap_set_content_type(r, "text/html");
37ef4b86270a8e58f87aa5fe558e3e65af97991ccovener ap_rprintf(r, "Hello, world!");
37ef4b86270a8e58f87aa5fe558e3e65af97991ccovener
37ef4b86270a8e58f87aa5fe558e3e65af97991ccovener /* Lastly, we must tell the server that we took care of this request and everything went fine.
fa0f379e3845907d7c1087d885169e302239bdbbnd * We do so by simply returning the value OK to the server.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive return OK;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive}
fa0f379e3845907d7c1087d885169e302239bdbbnd</highlight>
fa0f379e3845907d7c1087d885169e302239bdbbnd<!-- END EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<p>
06ba4a61654b3763ad65f52283832ebf058fdf1csliveNow, we put all we have learned together and end up with a program that
06ba4a61654b3763ad65f52283832ebf058fdf1cslivelooks like
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<a href="http://people.apache.org/~humbedooh/mods/examples/mod_example_1.c">mod_example_1.c</a>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive. The functions used in this example will be explained later in the section
cea021a7fc2657b091df4d3b031c4254ec371dd7rbowen<a href= "#functions">&quot;Some useful functions you should know&quot;</a>.
fa0f379e3845907d7c1087d885169e302239bdbbnd</p>
fa0f379e3845907d7c1087d885169e302239bdbbnd</section>
fa0f379e3845907d7c1087d885169e302239bdbbnd<section id="request_rec"><title>The request_rec structure</title>
cea021a7fc2657b091df4d3b031c4254ec371dd7rbowen<p>The most essential part of any request is the <em>request record
cea021a7fc2657b091df4d3b031c4254ec371dd7rbowen</em>. In a call to a handler function, this is represented by the <code>
fa0f379e3845907d7c1087d885169e302239bdbbndrequest_rec* </code> structure passed along with every call that is made.
fa0f379e3845907d7c1087d885169e302239bdbbndThis struct, typically just referred to as <code>r</code> in modules,
06ba4a61654b3763ad65f52283832ebf058fdf1cslivecontains all the information you need for your module to fully process any
06ba4a61654b3763ad65f52283832ebf058fdf1csliveHTTP request and respond accordingly.</p> <p>Some key elements of the <code>
06ba4a61654b3763ad65f52283832ebf058fdf1csliverequest_rec </code> structure are:
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<ul>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<li><code>r-&gt;handler (char*):</code> Contains the name of the handler the server is currently asking to do the handling of this request</li>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<li><code>r-&gt;method (char*):</code> Contains the HTTP method being used, f.x. GET or POST</li>
777c17c11c2b1638f191241364e034779851d186covener<li><code>r-&gt;filename (char*):</code> Contains the translated filename the client is requesting</li>
777c17c11c2b1638f191241364e034779851d186covener<li><code>r-&gt;args (char*):</code> Contains the query string of the request, if any</li>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<li><code>r-&gt;headers_in (apr_table_t*):</code> Contains all the headers sent by the client</li>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<li><code>r-&gt;connection (conn_rec*):</code> A record containing information about the current connection</li>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<li><code>r-&gt;user (char*):</code> If the URI requires authentication, this is set to the username provided</li>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<li><code>r-&gt;useragent_ip (char*):</code> The IP address of the client connecting to us</li>
fa0f379e3845907d7c1087d885169e302239bdbbnd<li><code>r-&gt;pool (apr_pool_t*)</code>: The memory pool of this request. We'll discuss this in the
fa0f379e3845907d7c1087d885169e302239bdbbnd&quot;<a href="#memory">Memory management</a>&quot; chapter.</li>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</ul>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<p>
06ba4a61654b3763ad65f52283832ebf058fdf1csliveA complete list of all the values contained within the <code>request_rec</code> structure can be found in
fa0f379e3845907d7c1087d885169e302239bdbbndthe <a href="http://svn.apache.org/repos/asf/httpd/httpd/trunk/include/httpd.h"><code>httpd.h</code></a> header
c0a201f9f0cda37f4e5829462c7e489f85bf327ccovenerfile 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>.
c0a201f9f0cda37f4e5829462c7e489f85bf327ccovener</p>
c0a201f9f0cda37f4e5829462c7e489f85bf327ccovener
c0a201f9f0cda37f4e5829462c7e489f85bf327ccovener
c0a201f9f0cda37f4e5829462c7e489f85bf327ccovener<p>
eaaa852423e42d6d86bcada80ed781a205fc3e5fndLet's try out some of these variables in another example handler:<br/>
eaaa852423e42d6d86bcada80ed781a205fc3e5fnd</p>
eaaa852423e42d6d86bcada80ed781a205fc3e5fnd
fa0f379e3845907d7c1087d885169e302239bdbbnd<!-- BEGIN EXAMPLE CODE -->
fa0f379e3845907d7c1087d885169e302239bdbbnd<highlight language="c">
fa0f379e3845907d7c1087d885169e302239bdbbndstatic int example_handler(request_rec *r)
fa0f379e3845907d7c1087d885169e302239bdbbnd{
eaaa852423e42d6d86bcada80ed781a205fc3e5fnd /* Set the appropriate content type */
4203a35c28d7c60adb7e9ef3be87aad34951c79asf ap_set_content_type(r, &quot;text/html&quot;);
4203a35c28d7c60adb7e9ef3be87aad34951c79asf
4203a35c28d7c60adb7e9ef3be87aad34951c79asf /* Print out the IP address of the client connecting to us: */
4203a35c28d7c60adb7e9ef3be87aad34951c79asf ap_rprintf(r, &quot;&lt;h2&gt;Hello, %s!&lt;/h2&gt;&quot;, r-&gt;useragent_ip);
4203a35c28d7c60adb7e9ef3be87aad34951c79asf
4203a35c28d7c60adb7e9ef3be87aad34951c79asf /* If we were reached through a GET or a POST request, be happy, else sad. */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive if ( !strcmp(r-&gt;method, &quot;POST&quot;) || !strcmp(r-&gt;method, &quot;GET&quot;) ) {
97a9a944b5887e91042b019776c41d5dd74557aferikabele ap_rputs(&quot;You used a GET or a POST method, that makes us happy!&lt;br/&gt;&quot;, r);
fa0f379e3845907d7c1087d885169e302239bdbbnd }
fa0f379e3845907d7c1087d885169e302239bdbbnd else {
fa0f379e3845907d7c1087d885169e302239bdbbnd ap_rputs(&quot;You did not use POST or GET, that makes us sad :(&lt;br/&gt;&quot;, r);
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf }
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf /* Lastly, if there was a query string, let's print that too! */
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf if (r-&gt;args) {
fa0f379e3845907d7c1087d885169e302239bdbbnd ap_rprintf(r, &quot;Your query string was: %s&quot;, r-&gt;args);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive }
fa0f379e3845907d7c1087d885169e302239bdbbnd return OK;
fa0f379e3845907d7c1087d885169e302239bdbbnd}
fa0f379e3845907d7c1087d885169e302239bdbbnd</highlight>
fa0f379e3845907d7c1087d885169e302239bdbbnd<!-- END EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
cea021a7fc2657b091df4d3b031c4254ec371dd7rbowen</section>
fa0f379e3845907d7c1087d885169e302239bdbbnd
fa0f379e3845907d7c1087d885169e302239bdbbnd<section id="return_value"><title>Return values</title>
fa0f379e3845907d7c1087d885169e302239bdbbnd<p>
fa0f379e3845907d7c1087d885169e302239bdbbndApache relies on return values from handlers to signify whether a request
fa0f379e3845907d7c1087d885169e302239bdbbndwas handled or not, and if so, whether the request went well or not. If a
fa0f379e3845907d7c1087d885169e302239bdbbndmodule is not interested in handling a specific request, it should always
fa0f379e3845907d7c1087d885169e302239bdbbndreturn the value <code>DECLINED</code>. If it is handling a request, it
fa0f379e3845907d7c1087d885169e302239bdbbndshould either return the generic value <code>OK</code>, or a specific HTTP
fa0f379e3845907d7c1087d885169e302239bdbbndstatus code, for example:
fa0f379e3845907d7c1087d885169e302239bdbbnd</p>
fa0f379e3845907d7c1087d885169e302239bdbbnd
fa0f379e3845907d7c1087d885169e302239bdbbnd<!-- BEGIN EXAMPLE CODE -->
fa0f379e3845907d7c1087d885169e302239bdbbnd<highlight language="c">
a4d04b8c74044c58bd4182028a1408d936c95951covenerstatic int example_handler(request_rec *r)
fa0f379e3845907d7c1087d885169e302239bdbbnd{
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* Return 404: Not found */
fa0f379e3845907d7c1087d885169e302239bdbbnd return HTTP_NOT_FOUND;
fa0f379e3845907d7c1087d885169e302239bdbbnd}
fa0f379e3845907d7c1087d885169e302239bdbbnd</highlight>
fa0f379e3845907d7c1087d885169e302239bdbbnd<!-- END EXAMPLE CODE -->
cea021a7fc2657b091df4d3b031c4254ec371dd7rbowen
cea021a7fc2657b091df4d3b031c4254ec371dd7rbowen<p>
06ba4a61654b3763ad65f52283832ebf058fdf1csliveReturning <code>OK</code> or a HTTP status code does not necessarily mean
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemthat the request will end. The server may still have other handlers that are
fa0f379e3845907d7c1087d885169e302239bdbbndinterested in this request, for instance the logging modules which, upon a
eaaa852423e42d6d86bcada80ed781a205fc3e5fndsuccessful request, will write down a summary of what was requested and how
fa0f379e3845907d7c1087d885169e302239bdbbndit went. To do a full stop and prevent any further processing after your
fa0f379e3845907d7c1087d885169e302239bdbbndmodule is done, you can return the value <code>DONE</code> to let the server
fa0f379e3845907d7c1087d885169e302239bdbbndknow that it should cease all activity on this request and carry on with
fa0f379e3845907d7c1087d885169e302239bdbbndthe next, without informing other handlers.
fa0f379e3845907d7c1087d885169e302239bdbbnd<br/>
fa0f379e3845907d7c1087d885169e302239bdbbnd<strong>General response codes:</strong>
fa0f379e3845907d7c1087d885169e302239bdbbnd</p>
fa0f379e3845907d7c1087d885169e302239bdbbnd<ul>
fa0f379e3845907d7c1087d885169e302239bdbbnd<li><code>DECLINED</code>: We are not handling this request</li>
fa0f379e3845907d7c1087d885169e302239bdbbnd<li><code>OK</code>: We handled this request and it went well</li>
fa0f379e3845907d7c1087d885169e302239bdbbnd<li><code>DONE</code>: We handled this request and the server should just close this thread without further processing</li>
fa0f379e3845907d7c1087d885169e302239bdbbnd</ul>
fa0f379e3845907d7c1087d885169e302239bdbbnd<p>
fa0f379e3845907d7c1087d885169e302239bdbbnd<strong>HTTP specific return codes (excerpt):</strong>
fa0f379e3845907d7c1087d885169e302239bdbbnd</p>
fa0f379e3845907d7c1087d885169e302239bdbbnd<ul>
fa0f379e3845907d7c1087d885169e302239bdbbnd<li><code>HTTP_OK (200)</code>: Request was okay</li>
fa0f379e3845907d7c1087d885169e302239bdbbnd<li><code>HTTP_MOVED_PERMANENTLY (301)</code>: The resource has moved to a new URL</li>
fa0f379e3845907d7c1087d885169e302239bdbbnd<li><code>HTTP_UNAUTHORIZED (401)</code>: Client is not authorized to visit this page</li>
fa0f379e3845907d7c1087d885169e302239bdbbnd<li><code>HTTP_FORBIDDEN (403)</code>: Permission denied</li>
fa0f379e3845907d7c1087d885169e302239bdbbnd<li><code>HTTP_NOT_FOUND (404)</code>: File not found</li>
fa0f379e3845907d7c1087d885169e302239bdbbnd<li><code>HTTP_INTERNAL_SERVER_ERROR (500)</code>: Internal server error (self explanatory)</li>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem</ul>
fa0f379e3845907d7c1087d885169e302239bdbbnd</section>
fa0f379e3845907d7c1087d885169e302239bdbbnd
fa0f379e3845907d7c1087d885169e302239bdbbnd<section id="functions"><title>Some useful functions you should know</title>
fa0f379e3845907d7c1087d885169e302239bdbbnd
fa0f379e3845907d7c1087d885169e302239bdbbnd<ul>
fa0f379e3845907d7c1087d885169e302239bdbbnd<li>
fa0f379e3845907d7c1087d885169e302239bdbbnd <code>ap_rputs(const char *string, request_rec *r)</code>: <br/>
fa0f379e3845907d7c1087d885169e302239bdbbnd Sends a string of text to the client. This is a shorthand version of <a
fa0f379e3845907d7c1087d885169e302239bdbbnd href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__PROTO.html#gac827cd0537d2b6213a7c06d7c26cc36e">
fa0f379e3845907d7c1087d885169e302239bdbbnd ap_rwrite</a>.
fa0f379e3845907d7c1087d885169e302239bdbbnd
fa0f379e3845907d7c1087d885169e302239bdbbnd
fa0f379e3845907d7c1087d885169e302239bdbbnd<!-- BEGIN EXAMPLE CODE -->
fa0f379e3845907d7c1087d885169e302239bdbbnd<highlight language="c">ap_rputs("Hello, world!", r);</highlight>
fa0f379e3845907d7c1087d885169e302239bdbbnd<!-- END EXAMPLE CODE -->
fa0f379e3845907d7c1087d885169e302239bdbbnd
fa0f379e3845907d7c1087d885169e302239bdbbnd
fa0f379e3845907d7c1087d885169e302239bdbbnd</li>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem<li>
fa0f379e3845907d7c1087d885169e302239bdbbnd <code>
fa0f379e3845907d7c1087d885169e302239bdbbnd <a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__PROTO.html#ga5e91eb6ca777c9a427b2e82bf1eeb81d">ap_rprintf</a></code>: <br/>
fa0f379e3845907d7c1087d885169e302239bdbbnd This function works just like <code>printf</code>, except it sends the result to the client.
fa0f379e3845907d7c1087d885169e302239bdbbnd
fa0f379e3845907d7c1087d885169e302239bdbbnd
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<!-- BEGIN EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<highlight language="c">ap_rprintf(r, "Hello, %s!", r->useragent_ip);</highlight>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem<!-- END EXAMPLE CODE -->
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem</li>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<li>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive <code>
88f586e767b7b224bdb1a178455668a2475cfc75rbowen <a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__PROTO.html#gaa2f8412c400197338ec509f4a45e4579">ap_set_content_type</a>(request_rec *r, const char *type)</code>: <br/>
88f586e767b7b224bdb1a178455668a2475cfc75rbowen Sets the content type of the output you are sending.
88f586e767b7b224bdb1a178455668a2475cfc75rbowen
88f586e767b7b224bdb1a178455668a2475cfc75rbowen
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<!-- BEGIN EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<highlight language="c">ap_set_content_type(r, "text/plain"); /* force a raw text output */</highlight>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<!-- END EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</li>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
88f586e767b7b224bdb1a178455668a2475cfc75rbowen</ul>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</section>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
81785f72c9d133aef57ad6b02f248345d90239aapoirier<section id="memory"><title>Memory management</title>
5ae30adbe59946de742ab0cd6be3b7457471a698takashi<p>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemManaging your resources in Apache HTTP Server 2.4 is quite easy, thanks to the memory pool
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemsystem. In essence, each server, connection and request have their own
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemmemory pool that gets cleaned up when its scope ends, e.g. when a request
06ba4a61654b3763ad65f52283832ebf058fdf1csliveis done or when a server process shuts down. All your module needs to do is
06ba4a61654b3763ad65f52283832ebf058fdf1cslivelatch onto this memory pool, and you won't have to worry about having to
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemclean up after yourself - pretty neat, huh?
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem</p>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem<p>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemIn our module, we will primarily be allocating memory for each request, so
06ba4a61654b3763ad65f52283832ebf058fdf1csliveit's appropriate to use the <code>r-&gt;pool</code>
06ba4a61654b3763ad65f52283832ebf058fdf1cslivereference when creating new objects. A few of the functions for allocating
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemmemory within a pool are:
97a9a944b5887e91042b019776c41d5dd74557aferikabele</p>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem<ul>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem<li><code>void* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__pools.html#ga85f1e193c31d109affda72f9a92c6915">apr_palloc</a>(
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemapr_pool_t *p, apr_size_t size)</code>: Allocates <code>size</code> number of bytes in the pool for you</li>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem<li><code>void* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__pools.html#gaf61c098ad258069d64cdf8c0a9369f9e">apr_pcalloc</a>(
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemapr_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>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem<li><code>char* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__strings.html#gabc79e99ff19abbd7cfd18308c5f85d47">apr_pstrdup</a>(
06ba4a61654b3763ad65f52283832ebf058fdf1csliveapr_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>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<li><code>char* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__strings.html#ga3eca76b8d293c5c3f8021e45eda813d8">apr_psprintf</a>(
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowenapr_pool_t *p, const char *fmt, ...)</code>: Similar to <code>sprintf</code>, except the server supplies you with an appropriately allocated target variable</li>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen</ul>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen<p>Let's put these functions into an example handler:</p>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen<!-- BEGIN EXAMPLE CODE -->
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen<highlight language="c">
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowenstatic int example_handler(request_rec *r)
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen{
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen const char* original = "You can't edit this!";
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen char* copy;
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen int* integers;
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen /* Allocate space for 10 integer values and set them all to zero. */
88f586e767b7b224bdb1a178455668a2475cfc75rbowen integers = apr_pcalloc(r->pool, sizeof(int)*10);
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
88f586e767b7b224bdb1a178455668a2475cfc75rbowen /* Create a copy of the 'original' variable that we can edit. */
88f586e767b7b224bdb1a178455668a2475cfc75rbowen copy = apr_pstrdup(r->pool, original);
88f586e767b7b224bdb1a178455668a2475cfc75rbowen return OK;
88f586e767b7b224bdb1a178455668a2475cfc75rbowen}
88f586e767b7b224bdb1a178455668a2475cfc75rbowen</highlight>
88f586e767b7b224bdb1a178455668a2475cfc75rbowen<!-- END EXAMPLE CODE -->
88f586e767b7b224bdb1a178455668a2475cfc75rbowen
88f586e767b7b224bdb1a178455668a2475cfc75rbowen<p>
88f586e767b7b224bdb1a178455668a2475cfc75rbowenThis is all well and good for our module, which won't need any
88f586e767b7b224bdb1a178455668a2475cfc75rbowenpre-initialized variables or structures. However, if we wanted to
88f586e767b7b224bdb1a178455668a2475cfc75rboweninitialize something early on, before the requests come rolling in, we
88f586e767b7b224bdb1a178455668a2475cfc75rbowencould simply add a call to a function in our <code>register_hooks</code>
88f586e767b7b224bdb1a178455668a2475cfc75rbowenfunction to sort it out:
88f586e767b7b224bdb1a178455668a2475cfc75rbowen</p>
88f586e767b7b224bdb1a178455668a2475cfc75rbowen
88f586e767b7b224bdb1a178455668a2475cfc75rbowen<!-- BEGIN EXAMPLE CODE -->
88f586e767b7b224bdb1a178455668a2475cfc75rbowen<highlight language="c">
88f586e767b7b224bdb1a178455668a2475cfc75rbowenstatic void register_hooks(apr_pool_t *pool)
88f586e767b7b224bdb1a178455668a2475cfc75rbowen{
88f586e767b7b224bdb1a178455668a2475cfc75rbowen /* Call a function that initializes some stuff */
88f586e767b7b224bdb1a178455668a2475cfc75rbowen example_init_function(pool);
88f586e767b7b224bdb1a178455668a2475cfc75rbowen /* Create a hook in the request handler, so we get called when a request arrives */
88f586e767b7b224bdb1a178455668a2475cfc75rbowen ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
88f586e767b7b224bdb1a178455668a2475cfc75rbowen}
88f586e767b7b224bdb1a178455668a2475cfc75rbowen</highlight>
88f586e767b7b224bdb1a178455668a2475cfc75rbowen<!-- END EXAMPLE CODE -->
88f586e767b7b224bdb1a178455668a2475cfc75rbowen
88f586e767b7b224bdb1a178455668a2475cfc75rbowen<p>
88f586e767b7b224bdb1a178455668a2475cfc75rbowenIn this pre-request initialization function we would not be using the
88f586e767b7b224bdb1a178455668a2475cfc75rbowensame pool as we did when allocating resources for request-based functions.
88f586e767b7b224bdb1a178455668a2475cfc75rbowenInstead, we would use the pool given to us by the server for allocating memory
88f586e767b7b224bdb1a178455668a2475cfc75rbowenon a per-process based level.
88f586e767b7b224bdb1a178455668a2475cfc75rbowen</p>
88f586e767b7b224bdb1a178455668a2475cfc75rbowen</section>
88f586e767b7b224bdb1a178455668a2475cfc75rbowen
88f586e767b7b224bdb1a178455668a2475cfc75rbowen<section id="parsing"><title>Parsing request data</title>
88f586e767b7b224bdb1a178455668a2475cfc75rbowen<p>
88f586e767b7b224bdb1a178455668a2475cfc75rbowenIn our example module, we would like to add a feature, that checks which
88f586e767b7b224bdb1a178455668a2475cfc75rbowentype of digest, MD5 or SHA1 the client would like to see. This could be
88f586e767b7b224bdb1a178455668a2475cfc75rbowensolved by adding a query string to the request. A query string is typically
88f586e767b7b224bdb1a178455668a2475cfc75rbowencomprised of several keys and values put together in a string, for instance
88f586e767b7b224bdb1a178455668a2475cfc75rbowen<code>valueA=yes&amp;valueB=no&amp;valueC=maybe</code>. It is up to the
88f586e767b7b224bdb1a178455668a2475cfc75rbowenmodule itself to parse these and get the data it requires. In our example,
88f586e767b7b224bdb1a178455668a2475cfc75rbowenwe'll be looking for a key called <code>digest</code>, and if set to <code>
88f586e767b7b224bdb1a178455668a2475cfc75rbowenmd5</code>, we'll produce an MD5 digest, otherwise we'll produce a SHA1
88f586e767b7b224bdb1a178455668a2475cfc75rbowendigest.
88f586e767b7b224bdb1a178455668a2475cfc75rbowen</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<p>
97a9a944b5887e91042b019776c41d5dd74557aferikabeleSince the introduction of Apache HTTP Server 2.4, parsing request data from GET and
06ba4a61654b3763ad65f52283832ebf058fdf1cslivePOST requests have never been easier. All we require to parse both GET and
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemPOST data is four simple lines:
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
97a9a944b5887e91042b019776c41d5dd74557aferikabele
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<!-- BEGIN EXAMPLE CODE -->
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem<highlight language="c">
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__apr__tables.html#gad7ea82d6608a4a633fc3775694ab71e4">apr_table_t</a> *GET; <em>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem</em><a href="http://ci.apache.org/projects/httpd/trunk/doxygen/structapr__array__header__t.html">apr_array_header_t</a>*POST;
97a9a944b5887e91042b019776c41d5dd74557aferikabele<em>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem</em>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__SCRIPT.html#gaed25877b529623a4d8f99f819ba1b7bd">
06ba4a61654b3763ad65f52283832ebf058fdf1csliveap_args_to_table</a>(r, &amp;GET); <em>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem</em><a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__DAEMON.html#ga9d426b6382b49754d4f87c55f65af202">
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemap_parse_form_data</a>(r, NULL, &amp;POST, -1, 8192);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</highlight>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen<!-- END EXAMPLE CODE -->
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen<p>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowenIn our specific example module, we're looking for the <code>digest</code>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowenvalue from the query string, which now resides inside a table called <code>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowenGET</code>. To extract this value, we need only perform a simple operation:
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen</p>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
88f586e767b7b224bdb1a178455668a2475cfc75rbowen<!-- BEGIN EXAMPLE CODE -->
88f586e767b7b224bdb1a178455668a2475cfc75rbowen<highlight language="c">
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen/* Get the "digest" key from the query string, if any. */
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowenconst char *digestType = apr_table_get(GET, "digest");
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen/* If no key was returned, we will set a default value instead. */
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowenif (!digestType) digestType = "sha1";
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen</highlight>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen<!-- END EXAMPLE CODE -->
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen<p>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowenThe structures used for the POST and GET data are not exactly the same, so
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemif we were to fetch a value from POST data instead of the query string, we
97a9a944b5887e91042b019776c41d5dd74557aferikabelewould have to resort to a few more lines, as outlined in <a href="#get_post"
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem>this example</a> in the last chapter of this document.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</section>
81785f72c9d133aef57ad6b02f248345d90239aapoirier
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem<section id="advanced_handler"><title>Making an advanced handler</title>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen<p>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowenNow that we have learned how to parse form data and manage our resources,
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowenwe can move on to creating an advanced version of our module, that spits
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowenout the MD5 or SHA1 digest of files:
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen</p>
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen
3b1807171c3f06d8951da1bf23c5f51961c274bbrbowen<!-- BEGIN EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<highlight language="c">
06ba4a61654b3763ad65f52283832ebf058fdf1cslivestatic int example_handler(request_rec *r)
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem{
06ba4a61654b3763ad65f52283832ebf058fdf1cslive int rc, exists;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive apr_finfo_t finfo;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive apr_file_t *file;
97a9a944b5887e91042b019776c41d5dd74557aferikabele char *filename;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive char buffer[256];
06ba4a61654b3763ad65f52283832ebf058fdf1cslive apr_size_t readBytes;
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf int n;
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf apr_table_t *GET;
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf apr_array_header_t *POST;
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf const char *digestType;
fa1092e17f0b85a610379ac564334ad879ed7dbarbowen
fa1092e17f0b85a610379ac564334ad879ed7dbarbowen
fa1092e17f0b85a610379ac564334ad879ed7dbarbowen /* Check that the &quot;example-handler&quot; handler is being called. */
fa1092e17f0b85a610379ac564334ad879ed7dbarbowen if (!r-&gt;handler || strcmp(r-&gt;handler, &quot;example-handler&quot;)) return (DECLINED);
fa1092e17f0b85a610379ac564334ad879ed7dbarbowen
fa1092e17f0b85a610379ac564334ad879ed7dbarbowen /* Figure out which file is being requested by removing the .sum from it */
fa1092e17f0b85a610379ac564334ad879ed7dbarbowen filename = apr_pstrdup(r-&gt;pool, r-&gt;filename);
fa1092e17f0b85a610379ac564334ad879ed7dbarbowen filename[strlen(filename)-4] = 0; /* Cut off the last 4 characters. */
fa1092e17f0b85a610379ac564334ad879ed7dbarbowen
fa1092e17f0b85a610379ac564334ad879ed7dbarbowen /* Figure out if the file we request a sum on exists and isn't a directory */
fa1092e17f0b85a610379ac564334ad879ed7dbarbowen rc = apr_stat(&amp;finfo, filename, APR_FINFO_MIN, r-&gt;pool);
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf if (rc == APR_SUCCESS) {
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf exists =
5ae30adbe59946de742ab0cd6be3b7457471a698takashi (
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem (finfo.filetype != APR_NOFILE)
06ba4a61654b3763ad65f52283832ebf058fdf1cslive &amp;&amp; !(finfo.filetype &amp; APR_DIR)
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem );
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem if (!exists) return HTTP_NOT_FOUND; /* Return a 404 if not found. */
22d5d84393d960a2027f472036f3fee15d7dbce9nd }
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* If apr_stat failed, we're probably not allowed to check this file. */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive else return HTTP_FORBIDDEN;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
97a9a944b5887e91042b019776c41d5dd74557aferikabele /* Parse the GET and, optionally, the POST data sent to us */
81785f72c9d133aef57ad6b02f248345d90239aapoirier
5ae30adbe59946de742ab0cd6be3b7457471a698takashi ap_args_to_table(r, &amp;GET);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_parse_form_data(r, NULL, &amp;POST, -1, 8192);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* Set the appropriate content type */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_set_content_type(r, &quot;text/html&quot;);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* Print a title and some general information */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_rprintf(r, &quot;&lt;h2&gt;Information on %s:&lt;/h2&gt;&quot;, filename);
97a9a944b5887e91042b019776c41d5dd74557aferikabele ap_rprintf(r, &quot;&lt;b&gt;Size:&lt;/b&gt; %u bytes&lt;br/&gt;&quot;, finfo.size);
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem
81785f72c9d133aef57ad6b02f248345d90239aapoirier /* Get the digest type the client wants to see */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive digestType = apr_table_get(GET, &quot;digest&quot;);
97a9a944b5887e91042b019776c41d5dd74557aferikabele if (!digestType) digestType = &quot;MD5&quot;;
025069f3f8c6b59e730a72c229329dfad5a28424rbowen
025069f3f8c6b59e730a72c229329dfad5a28424rbowen
025069f3f8c6b59e730a72c229329dfad5a28424rbowen rc = apr_file_open(&amp;file, filename, APR_READ, APR_OS_DEFAULT, r-&gt;pool);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive if (rc == APR_SUCCESS) {
97a9a944b5887e91042b019776c41d5dd74557aferikabele
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* Are we trying to calculate the MD5 or the SHA1 digest? */
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem if (!strcasecmp(digestType, &quot;md5&quot;)) {
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem /* Calculate the MD5 sum of the file */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive union {
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl char chr[16];
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl uint32_t num[4];
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl } digest;
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl apr_md5_ctx_t md5;
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl apr_md5_init(&amp;md5);
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl readBytes = 256;
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl while ( apr_file_read(file, buffer, &amp;readBytes) == APR_SUCCESS ) {
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl apr_md5_update(&amp;md5, buffer, readBytes);
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl }
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl apr_md5_final(digest.chr, &amp;md5);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
22d5d84393d960a2027f472036f3fee15d7dbce9nd /* Print out the MD5 digest */
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem ap_rputs(&quot;&lt;b&gt;MD5: &lt;/b&gt;&lt;code&gt;&quot;, r);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive for (n = 0; n &lt; APR_MD5_DIGESTSIZE/4; n++) {
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_rprintf(r, &quot;%08x&quot;, digest.num[n]);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive }
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_rputs(&quot;&lt;/code&gt;&quot;, r);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* Print a link to the SHA1 version */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_rputs(&quot;&lt;br/&gt;&lt;a href='?digest=sha1'&gt;View the SHA1 hash instead&lt;/a&gt;&quot;, r);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive }
97a9a944b5887e91042b019776c41d5dd74557aferikabele else {
7171511e7e2c17e9b54cc34dc247266b70138d6crbowen /* Calculate the SHA1 sum of the file */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive union {
06ba4a61654b3763ad65f52283832ebf058fdf1cslive char chr[20];
7171511e7e2c17e9b54cc34dc247266b70138d6crbowen uint32_t num[5];
06ba4a61654b3763ad65f52283832ebf058fdf1cslive } digest;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive apr_sha1_ctx_t sha1;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive apr_sha1_init(&amp;sha1);
97a9a944b5887e91042b019776c41d5dd74557aferikabele readBytes = 256;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive while ( apr_file_read(file, buffer, &amp;readBytes) == APR_SUCCESS ) {
81785f72c9d133aef57ad6b02f248345d90239aapoirier apr_sha1_update(&amp;sha1, buffer, readBytes);
5ae30adbe59946de742ab0cd6be3b7457471a698takashi }
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem apr_sha1_final(digest.chr, &amp;sha1);
5ae30adbe59946de742ab0cd6be3b7457471a698takashi
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem /* Print out the SHA1 digest */
81785f72c9d133aef57ad6b02f248345d90239aapoirier ap_rputs(&quot;&lt;b&gt;SHA1: &lt;/b&gt;&lt;code&gt;&quot;, r);
5ae30adbe59946de742ab0cd6be3b7457471a698takashi for (n = 0; n &lt; APR_SHA1_DIGESTSIZE/4; n++) {
5ae30adbe59946de742ab0cd6be3b7457471a698takashi ap_rprintf(r, &quot;%08x&quot;, digest.num[n]);
5ae30adbe59946de742ab0cd6be3b7457471a698takashi }
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem ap_rputs(&quot;&lt;/code&gt;&quot;, r);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* Print a link to the MD5 version */
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd ap_rputs(&quot;&lt;br/&gt;&lt;a href='?digest=md5'&gt;View the MD5 hash instead&lt;/a&gt;&quot;, r);
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd }
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd apr_file_close(file);
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd }
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* Let the server know that we responded to this request. */
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd return OK;
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd}
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</highlight>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<!-- END EXAMPLE CODE -->
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd
81785f72c9d133aef57ad6b02f248345d90239aapoirier<p>
06ba4a61654b3763ad65f52283832ebf058fdf1csliveThis version in its entirety can be found here:
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<a href="http://people.apache.org/~humbedooh/mods/examples/mod_example_2.c">mod_example_2.c</a>.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</section>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</section>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<section id="configuration"><title>Adding configuration options</title>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<p>
06ba4a61654b3763ad65f52283832ebf058fdf1csliveIn this next segment of this document, we will turn our eyes away from the
4c36c711036219c80d5517d35be68a4769c15291slivedigest module and create a new example module, whose only function is to
4c36c711036219c80d5517d35be68a4769c15291slivewrite out its own configuration. The purpose of this is to examine how
06ba4a61654b3763ad65f52283832ebf058fdf1cslivethe server works with configuration, and what happens when you start writing
4c36c711036219c80d5517d35be68a4769c15291sliveadvanced configurations
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndfor your modules.
fc9f416faa11879811f17d6efadedbf81cfd52a1covener</p>
fc9f416faa11879811f17d6efadedbf81cfd52a1covener<section id="config_intro"><title>An introduction to configuration
fc9f416faa11879811f17d6efadedbf81cfd52a1covenerdirectives</title>
fc9f416faa11879811f17d6efadedbf81cfd52a1covener<p>
fc9f416faa11879811f17d6efadedbf81cfd52a1covenerIf you are reading this, then you probably already know
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndwhat a configuration directive is. Simply put, a directive is a way of
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndtelling an individual module (or a set of modules) how to behave, such as
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndthese directives control how <code>mod_rewrite</code> works:
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</p>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<highlight language="config">
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndRewriteEngine On
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndRewriteCond %{REQUEST_URI} ^/foo/bar
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndRewriteRule ^/foo/bar/(.*)$ /foobar?page=$1
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</highlight>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<p>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndEach of these configuration directives are handled by a separate function,
cea021a7fc2657b091df4d3b031c4254ec371dd7rbowenthat parses the parameters given and sets up a configuration accordingly.
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</section>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<section id="config_simple"><title>Making an example configuration</title>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<p>To begin with, we'll create a basic configuration in C-space:</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<!-- BEGIN EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<highlight language="c">
06ba4a61654b3763ad65f52283832ebf058fdf1cslivetypedef struct {
06ba4a61654b3763ad65f52283832ebf058fdf1cslive int enabled; /* Enable or disable our module */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive const char *path; /* Some path to...something */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive int typeOfAction; /* 1 means action A, 2 means action B and so on */
97a9a944b5887e91042b019776c41d5dd74557aferikabele} example_config;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</highlight>
97a9a944b5887e91042b019776c41d5dd74557aferikabele<!-- END EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<p>
06ba4a61654b3763ad65f52283832ebf058fdf1csliveNow, let's put this into perspective by creating a very small module that
97a9a944b5887e91042b019776c41d5dd74557aferikabelejust prints out a hard-coded configuration. You'll notice that we use the
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<code>register_hooks</code> function for initializing the configuration
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemvalues to their defaults:
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<!-- BEGIN EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<highlight language="c">
7992de7f9e82ab86effe3dcc5279fb959f6c398dcovenertypedef struct {
7992de7f9e82ab86effe3dcc5279fb959f6c398dcovener int enabled; /* Enable or disable our module */
7992de7f9e82ab86effe3dcc5279fb959f6c398dcovener const char *path; /* Some path to...something */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive int typeOfAction; /* 1 means action A, 2 means action B and so on */
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowen} example_config;
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowen
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowenstatic example_config config;
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowen
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowenstatic int example_handler(request_rec *r)
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowen{
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowen if (!r-&gt;handler || strcmp(r-&gt;handler, &quot;example-handler&quot;)) return(DECLINED);
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowen ap_set_content_type(r, &quot;text/plain&quot;);
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowen ap_rprintf(r, &quot;Enabled: %u\n&quot;, config.enabled);
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowen ap_rprintf(r, &quot;Path: %s\n&quot;, config.path);
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowen ap_rprintf(r, &quot;TypeOfAction: %x\n&quot;, config.typeOfAction);
8ac3ff7008df949c096f9cd8f769c7893594f61fnd return OK;
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowen}
0ccb6ee166750359937ae35d59c0beb54f8fd228rbowen
06ba4a61654b3763ad65f52283832ebf058fdf1cslivestatic void register_hooks(apr_pool_t *pool)
06ba4a61654b3763ad65f52283832ebf058fdf1cslive{
06ba4a61654b3763ad65f52283832ebf058fdf1cslive config.enabled = 1;
790a477f6ce41161c4173c1e5080a1f569976a1erbowen config.path = &quot;/foo/bar&quot;;
790a477f6ce41161c4173c1e5080a1f569976a1erbowen config.typeOfAction = 0x00;
790a477f6ce41161c4173c1e5080a1f569976a1erbowen ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
790a477f6ce41161c4173c1e5080a1f569976a1erbowen}
790a477f6ce41161c4173c1e5080a1f569976a1erbowen
790a477f6ce41161c4173c1e5080a1f569976a1erbowen/* Define our module as an entity and assign a function for registering hooks */
790a477f6ce41161c4173c1e5080a1f569976a1erbowen
790a477f6ce41161c4173c1e5080a1f569976a1erbowenmodule AP_MODULE_DECLARE_DATA example_module =
790a477f6ce41161c4173c1e5080a1f569976a1erbowen{
790a477f6ce41161c4173c1e5080a1f569976a1erbowen STANDARD20_MODULE_STUFF,
790a477f6ce41161c4173c1e5080a1f569976a1erbowen NULL, /* Per-directory configuration handler */
0a3142725875ea286597e083547d34d98f8c1f2drbowen NULL, /* Merge handler for per-directory configurations */
0a3142725875ea286597e083547d34d98f8c1f2drbowen NULL, /* Per-server configuration handler */
790a477f6ce41161c4173c1e5080a1f569976a1erbowen NULL, /* Merge handler for per-server configurations */
0a3142725875ea286597e083547d34d98f8c1f2drbowen NULL, /* Any directives we may have for httpd */
790a477f6ce41161c4173c1e5080a1f569976a1erbowen register_hooks /* Our hook registering function */
790a477f6ce41161c4173c1e5080a1f569976a1erbowen};
0a3142725875ea286597e083547d34d98f8c1f2drbowen</highlight>
790a477f6ce41161c4173c1e5080a1f569976a1erbowen<!-- END EXAMPLE CODE -->
790a477f6ce41161c4173c1e5080a1f569976a1erbowen
790a477f6ce41161c4173c1e5080a1f569976a1erbowen<p>
790a477f6ce41161c4173c1e5080a1f569976a1erbowenSo far so good. To access our new handler, we could add the following to
790a477f6ce41161c4173c1e5080a1f569976a1erbowenour configuration:
790a477f6ce41161c4173c1e5080a1f569976a1erbowen</p>
790a477f6ce41161c4173c1e5080a1f569976a1erbowen<highlight language="config">
790a477f6ce41161c4173c1e5080a1f569976a1erbowen&lt;Location /example&gt;
790a477f6ce41161c4173c1e5080a1f569976a1erbowen SetHandler example-handler
790a477f6ce41161c4173c1e5080a1f569976a1erbowen&lt;/Location&gt;
0a3142725875ea286597e083547d34d98f8c1f2drbowen</highlight>
0a3142725875ea286597e083547d34d98f8c1f2drbowen<p>
06ba4a61654b3763ad65f52283832ebf058fdf1csliveWhen we visit, we'll see our current configuration being spit out by our
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndmodule.
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</p>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</section>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<section id="register_directive"><title>Registering directives with the server</title>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<p>
0203b896e484dfb877111aceffb812401d0f216andWhat if we want to change our configuration, not by hard-coding new values
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndinto the module, but by using either the httpd.conf file or possibly a
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd.htaccess file? It's time to let the server know that we want this to be
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndpossible. To do so, we must first change our <em>name tag</em> to include a
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndreference to the configuration directives we want to register with the server:
844def494f17cb1ab0983427d5c3939e1a03ff8cnd</p>
0203b896e484dfb877111aceffb812401d0f216and
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<!-- BEGIN EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<highlight language="c">
06ba4a61654b3763ad65f52283832ebf058fdf1cslivemodule AP_MODULE_DECLARE_DATA example_module =
06ba4a61654b3763ad65f52283832ebf058fdf1cslive{
81785f72c9d133aef57ad6b02f248345d90239aapoirier STANDARD20_MODULE_STUFF,
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem NULL, /* Per-directory configuration handler */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive NULL, /* Merge handler for per-directory configurations */
0203b896e484dfb877111aceffb812401d0f216and NULL, /* Per-server configuration handler */
8681ae721fdee17238ebfb7edaeb5c3edc9f1a33nd NULL, /* Merge handler for per-server configurations */
1437d609a6e92c3f32dfdb0d63fce4fd2243fa0frbowen example_directives, /* Any directives we may have for httpd */
1437d609a6e92c3f32dfdb0d63fce4fd2243fa0frbowen register_hooks /* Our hook registering function */
1437d609a6e92c3f32dfdb0d63fce4fd2243fa0frbowen};
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem</highlight>
0203b896e484dfb877111aceffb812401d0f216and<!-- END EXAMPLE CODE -->
0203b896e484dfb877111aceffb812401d0f216and
0203b896e484dfb877111aceffb812401d0f216and<p>
a4d04b8c74044c58bd4182028a1408d936c95951covenerThis will tell the server that we are now accepting directives from the
a4d04b8c74044c58bd4182028a1408d936c95951covenerconfiguration files, and that the structure called <code>example_directives
a4d04b8c74044c58bd4182028a1408d936c95951covener</code> holds information on what our directives are and how they work.
a4d04b8c74044c58bd4182028a1408d936c95951covenerSince we have three different variables in our module configuration, we
a4d04b8c74044c58bd4182028a1408d936c95951covenerwill add a structure with three directives and a NULL at the end:
a4d04b8c74044c58bd4182028a1408d936c95951covener</p>
a4d04b8c74044c58bd4182028a1408d936c95951covener
a4d04b8c74044c58bd4182028a1408d936c95951covener<!-- BEGIN EXAMPLE CODE -->
1437d609a6e92c3f32dfdb0d63fce4fd2243fa0frbowen<highlight language="c">
1437d609a6e92c3f32dfdb0d63fce4fd2243fa0frbowenstatic const command_rec example_directives[] =
1437d609a6e92c3f32dfdb0d63fce4fd2243fa0frbowen{
1437d609a6e92c3f32dfdb0d63fce4fd2243fa0frbowen AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
1437d609a6e92c3f32dfdb0d63fce4fd2243fa0frbowen AP_INIT_TAKE1("examplePath", example_set_path, NULL, RSRC_CONF, "The path to whatever"),
1437d609a6e92c3f32dfdb0d63fce4fd2243fa0frbowen AP_INIT_TAKE2("exampleAction", example_set_action, NULL, RSRC_CONF, "Special action value!"),
1437d609a6e92c3f32dfdb0d63fce4fd2243fa0frbowen { NULL }
8681ae721fdee17238ebfb7edaeb5c3edc9f1a33nd};
8681ae721fdee17238ebfb7edaeb5c3edc9f1a33nd</highlight>
8681ae721fdee17238ebfb7edaeb5c3edc9f1a33nd<!-- END EXAMPLE CODE -->
8681ae721fdee17238ebfb7edaeb5c3edc9f1a33nd
f039cf01b271a31e317d5b84f24cb135f1c1b6d7nd<p>
8681ae721fdee17238ebfb7edaeb5c3edc9f1a33nd<img src="/images/build_a_mod_4.png" alt="Directives structure"/><br />
8681ae721fdee17238ebfb7edaeb5c3edc9f1a33ndAs you can see, each directive needs at least 5 parameters set:
8681ae721fdee17238ebfb7edaeb5c3edc9f1a33nd</p>
0203b896e484dfb877111aceffb812401d0f216and<ol>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<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.
8681ae721fdee17238ebfb7edaeb5c3edc9f1a33ndIf 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
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndfor more macros).</li>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<li><code>exampleEnabled</code>: This is the name of our directive. More precisely, it is what the user must put in his/her
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndconfiguration in order to invoke a configuration change in our module.</li>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<li><code>example_set_enabled</code>: This is a reference to a C function that parses the directive and sets the configuration
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4ndaccordingly. We will discuss how to make this in the following paragraph.</li>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<li><code>RSRC_CONF</code>: This tells the server where the directive is permitted. We'll go into details on this value in the
96147932f199be4ad038778e702c13a2f79051c0slivelater chapters, but for now, <code>RSRC_CONF</code> means that the server will only accept these directives in a server context.</li>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<li><code>"Enable or disable...."</code>: This is simply a brief description of what the directive does.</li>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd</ol>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<p>
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd(<em>The "missing" parameter in our definition, which is usually set to
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd<code>NULL</code>, is an optional function that can be run after the
06ba4a61654b3763ad65f52283832ebf058fdf1csliveinitial function to parse the arguments have been run. This is usually
81785f72c9d133aef57ad6b02f248345d90239aapoirieromitted, as the function for verifying arguments might as well be used to
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemset them.</em>)
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem</p>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem</section>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<section id="directive_handler"><title>The directive handler function</title>
630c456b6461158be6cc5c5483735e27b13b4ad5nd<p>
630c456b6461158be6cc5c5483735e27b13b4ad5ndNow that we have told the server to expect some directives for our module, it's
37ef4b86270a8e58f87aa5fe558e3e65af97991ccovenertime to make a few functions for handling these. What the server reads in the
8c8c2e71c84babf0e8c4b35819c7c5b3be014cfenoodlconfiguration file(s) is text, and so naturally, what it passes along to
8c8c2e71c84babf0e8c4b35819c7c5b3be014cfenoodlour directive handler is one or more strings, that we ourselves need to
8c8c2e71c84babf0e8c4b35819c7c5b3be014cfenoodlrecognize and act upon. You'll notice, that since we set our <code>
06ba4a61654b3763ad65f52283832ebf058fdf1csliveexampleAction</code> directive to accept two arguments, its C function also
96147932f199be4ad038778e702c13a2f79051c0slivehas an additional parameter defined:</p>
9560125bd44b9d138cb67884b1884401edb1eb85covener
9560125bd44b9d138cb67884b1884401edb1eb85covener<!-- BEGIN EXAMPLE CODE -->
9560125bd44b9d138cb67884b1884401edb1eb85covener<highlight language="c">
9560125bd44b9d138cb67884b1884401edb1eb85covener/* Handler for the "exampleEnabled" directive */
9560125bd44b9d138cb67884b1884401edb1eb85covenerconst char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg)
9560125bd44b9d138cb67884b1884401edb1eb85covener{
9560125bd44b9d138cb67884b1884401edb1eb85covener if(!strcasecmp(arg, "on")) config.enabled = 1;
9560125bd44b9d138cb67884b1884401edb1eb85covener else config.enabled = 0;
9560125bd44b9d138cb67884b1884401edb1eb85covener return NULL;
9560125bd44b9d138cb67884b1884401edb1eb85covener}
e619b7228ac42d9c70d6a5f02d808b0d2880080ccovener
96147932f199be4ad038778e702c13a2f79051c0slive/* Handler for the "examplePath" directive */
96147932f199be4ad038778e702c13a2f79051c0sliveconst char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg)
9560125bd44b9d138cb67884b1884401edb1eb85covener{
e619b7228ac42d9c70d6a5f02d808b0d2880080ccovener config.path = arg;
9560125bd44b9d138cb67884b1884401edb1eb85covener return NULL;
9560125bd44b9d138cb67884b1884401edb1eb85covener}
9560125bd44b9d138cb67884b1884401edb1eb85covener
9560125bd44b9d138cb67884b1884401edb1eb85covener/* Handler for the "exampleAction" directive */
9dd0b961340554104e5b6e837ddb3101f843cc3fcovener/* Let's pretend this one takes one argument (file or db), and a second (deny or allow), */
9560125bd44b9d138cb67884b1884401edb1eb85covener/* and we store it in a bit-wise manner. */
9560125bd44b9d138cb67884b1884401edb1eb85covenerconst char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char* arg2)
9560125bd44b9d138cb67884b1884401edb1eb85covener{
9560125bd44b9d138cb67884b1884401edb1eb85covener if(!strcasecmp(arg1, "file")) config.typeOfAction = 0x01;
9560125bd44b9d138cb67884b1884401edb1eb85covener else config.typeOfAction = 0x02;
9560125bd44b9d138cb67884b1884401edb1eb85covener
9560125bd44b9d138cb67884b1884401edb1eb85covener if(!strcasecmp(arg2, "deny")) config.typeOfAction += 0x10;
9560125bd44b9d138cb67884b1884401edb1eb85covener else config.typeOfAction += 0x20;
9560125bd44b9d138cb67884b1884401edb1eb85covener return NULL;
9560125bd44b9d138cb67884b1884401edb1eb85covener}
9560125bd44b9d138cb67884b1884401edb1eb85covener</highlight>
9560125bd44b9d138cb67884b1884401edb1eb85covener<!-- END EXAMPLE CODE -->
9560125bd44b9d138cb67884b1884401edb1eb85covener
9560125bd44b9d138cb67884b1884401edb1eb85covener
9560125bd44b9d138cb67884b1884401edb1eb85covener</section>
9560125bd44b9d138cb67884b1884401edb1eb85covener<section id="directive_complete"><title>Putting it all together</title>
9560125bd44b9d138cb67884b1884401edb1eb85covener<p>
9560125bd44b9d138cb67884b1884401edb1eb85covenerNow that we have our directives set up, and handlers configured for them,
9560125bd44b9d138cb67884b1884401edb1eb85covenerwe can assemble our module into one big file:
9560125bd44b9d138cb67884b1884401edb1eb85covener</p>
9560125bd44b9d138cb67884b1884401edb1eb85covener
9560125bd44b9d138cb67884b1884401edb1eb85covener<!-- BEGIN EXAMPLE CODE -->
9560125bd44b9d138cb67884b1884401edb1eb85covener<highlight language="c">
9dd0b961340554104e5b6e837ddb3101f843cc3fcovener/* mod_example_config_simple.c: */
9560125bd44b9d138cb67884b1884401edb1eb85covener#include &lt;stdio.h&gt;
9560125bd44b9d138cb67884b1884401edb1eb85covener#include "apr_hash.h"
9560125bd44b9d138cb67884b1884401edb1eb85covener#include "ap_config.h"
9560125bd44b9d138cb67884b1884401edb1eb85covener#include "ap_provider.h"
9560125bd44b9d138cb67884b1884401edb1eb85covener#include "httpd.h"
96147932f199be4ad038778e702c13a2f79051c0slive#include "http_core.h"
96147932f199be4ad038778e702c13a2f79051c0slive#include "http_config.h"
70f2730533c8592263435354e66d9dbaf4d6361bslive#include "http_log.h"
70f2730533c8592263435354e66d9dbaf4d6361bslive#include "http_protocol.h"
1093a264c81aa1041581ab059905fb8f7cdfc5e2rbowen#include "http_request.h"
70f2730533c8592263435354e66d9dbaf4d6361bslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive/*
5ae30adbe59946de742ab0cd6be3b7457471a698takashi ==============================================================================
81785f72c9d133aef57ad6b02f248345d90239aapoirier Our configuration prototype and declaration:
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem ==============================================================================
06ba4a61654b3763ad65f52283832ebf058fdf1cslive */
06ba4a61654b3763ad65f52283832ebf058fdf1cslivetypedef struct {
06ba4a61654b3763ad65f52283832ebf058fdf1cslive int enabled; /* Enable or disable our module */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive const char *path; /* Some path to...something */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive int typeOfAction; /* 1 means action A, 2 means action B and so on */
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem} example_config;
81785f72c9d133aef57ad6b02f248345d90239aapoirier
81785f72c9d133aef57ad6b02f248345d90239aapoirierstatic example_config config;
81785f72c9d133aef57ad6b02f248345d90239aapoirier
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem/*
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem ==============================================================================
97a9a944b5887e91042b019776c41d5dd74557aferikabele Our directive handlers:
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ==============================================================================
96147932f199be4ad038778e702c13a2f79051c0slive */
96147932f199be4ad038778e702c13a2f79051c0slive/* Handler for the &quot;exampleEnabled&quot; directive */
96147932f199be4ad038778e702c13a2f79051c0sliveconst char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg)
96147932f199be4ad038778e702c13a2f79051c0slive{
96147932f199be4ad038778e702c13a2f79051c0slive if(!strcasecmp(arg, &quot;on&quot;)) config.enabled = 1;
96147932f199be4ad038778e702c13a2f79051c0slive else config.enabled = 0;
96147932f199be4ad038778e702c13a2f79051c0slive return NULL;
96147932f199be4ad038778e702c13a2f79051c0slive}
96147932f199be4ad038778e702c13a2f79051c0slive
96147932f199be4ad038778e702c13a2f79051c0slive/* Handler for the &quot;examplePath&quot; directive */
96147932f199be4ad038778e702c13a2f79051c0sliveconst char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg)
96147932f199be4ad038778e702c13a2f79051c0slive{
81785f72c9d133aef57ad6b02f248345d90239aapoirier config.path = arg;
96147932f199be4ad038778e702c13a2f79051c0slive return NULL;
96147932f199be4ad038778e702c13a2f79051c0slive}
96147932f199be4ad038778e702c13a2f79051c0slive
96147932f199be4ad038778e702c13a2f79051c0slive/* Handler for the &quot;exampleAction&quot; directive */
e00def5e805da9a73b72ad25dac664f0c8c36c2end/* Let's pretend this one takes one argument (file or db), and a second (deny or allow), */
96147932f199be4ad038778e702c13a2f79051c0slive/* and we store it in a bit-wise manner. */
96147932f199be4ad038778e702c13a2f79051c0sliveconst char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char* arg2)
96147932f199be4ad038778e702c13a2f79051c0slive{
96147932f199be4ad038778e702c13a2f79051c0slive if(!strcasecmp(arg1, &quot;file&quot;)) config.typeOfAction = 0x01;
96147932f199be4ad038778e702c13a2f79051c0slive else config.typeOfAction = 0x02;
96147932f199be4ad038778e702c13a2f79051c0slive
96147932f199be4ad038778e702c13a2f79051c0slive if(!strcasecmp(arg2, &quot;deny&quot;)) config.typeOfAction += 0x10;
96147932f199be4ad038778e702c13a2f79051c0slive else config.typeOfAction += 0x20;
96147932f199be4ad038778e702c13a2f79051c0slive return NULL;
96147932f199be4ad038778e702c13a2f79051c0slive}
96147932f199be4ad038778e702c13a2f79051c0slive
96147932f199be4ad038778e702c13a2f79051c0slive/*
96147932f199be4ad038778e702c13a2f79051c0slive ==============================================================================
96147932f199be4ad038778e702c13a2f79051c0slive The directive structure for our name tag:
96147932f199be4ad038778e702c13a2f79051c0slive ==============================================================================
96147932f199be4ad038778e702c13a2f79051c0slive */
96147932f199be4ad038778e702c13a2f79051c0slivestatic const command_rec example_directives[] =
96147932f199be4ad038778e702c13a2f79051c0slive{
96147932f199be4ad038778e702c13a2f79051c0slive AP_INIT_TAKE1(&quot;exampleEnabled&quot;, example_set_enabled, NULL, RSRC_CONF, &quot;Enable or disable mod_example&quot;),
96147932f199be4ad038778e702c13a2f79051c0slive AP_INIT_TAKE1(&quot;examplePath&quot;, example_set_path, NULL, RSRC_CONF, &quot;The path to whatever&quot;),
96147932f199be4ad038778e702c13a2f79051c0slive AP_INIT_TAKE2(&quot;exampleAction&quot;, example_set_action, NULL, RSRC_CONF, &quot;Special action value!&quot;),
96147932f199be4ad038778e702c13a2f79051c0slive { NULL }
96147932f199be4ad038778e702c13a2f79051c0slive};
96147932f199be4ad038778e702c13a2f79051c0slive/*
96147932f199be4ad038778e702c13a2f79051c0slive ==============================================================================
96147932f199be4ad038778e702c13a2f79051c0slive Our module handler:
96147932f199be4ad038778e702c13a2f79051c0slive ==============================================================================
96147932f199be4ad038778e702c13a2f79051c0slive */
96147932f199be4ad038778e702c13a2f79051c0slivestatic int example_handler(request_rec *r)
96147932f199be4ad038778e702c13a2f79051c0slive{
06ba4a61654b3763ad65f52283832ebf058fdf1cslive if(!r-&gt;handler || strcmp(r-&gt;handler, &quot;example-handler&quot;)) return(DECLINED);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_set_content_type(r, &quot;text/plain&quot;);
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem ap_rprintf(r, &quot;Enabled: %u\n&quot;, config.enabled);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_rprintf(r, &quot;Path: %s\n&quot;, config.path);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_rprintf(r, &quot;TypeOfAction: %x\n&quot;, config.typeOfAction);
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem return OK;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive}
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
06ba4a61654b3763ad65f52283832ebf058fdf1cslive/*
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ==============================================================================
06ba4a61654b3763ad65f52283832ebf058fdf1cslive The hook registration function (also initializes the default config values):
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ==============================================================================
06ba4a61654b3763ad65f52283832ebf058fdf1cslive */
06ba4a61654b3763ad65f52283832ebf058fdf1cslivestatic void register_hooks(apr_pool_t *pool)
96147932f199be4ad038778e702c13a2f79051c0slive{
81785f72c9d133aef57ad6b02f248345d90239aapoirier config.enabled = 1;
5ae30adbe59946de742ab0cd6be3b7457471a698takashi config.path = &quot;/foo/bar&quot;;
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem config.typeOfAction = 3;
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive}
06ba4a61654b3763ad65f52283832ebf058fdf1cslive/*
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ==============================================================================
06ba4a61654b3763ad65f52283832ebf058fdf1cslive Our module name tag:
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem ==============================================================================
06ba4a61654b3763ad65f52283832ebf058fdf1cslive */
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemmodule AP_MODULE_DECLARE_DATA example_module =
81785f72c9d133aef57ad6b02f248345d90239aapoirier{
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem STANDARD20_MODULE_STUFF,
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem NULL, /* Per-directory configuration handler */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive NULL, /* Merge handler for per-directory configurations */
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem NULL, /* Per-server configuration handler */
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem NULL, /* Merge handler for per-server configurations */
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem example_directives, /* Any directives we may have for httpd */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive register_hooks /* Our hook registering function */
96147932f199be4ad038778e702c13a2f79051c0slive};
96147932f199be4ad038778e702c13a2f79051c0slive</highlight>
96147932f199be4ad038778e702c13a2f79051c0slive<!-- END EXAMPLE CODE -->
96147932f199be4ad038778e702c13a2f79051c0slive
96147932f199be4ad038778e702c13a2f79051c0slive
96147932f199be4ad038778e702c13a2f79051c0slive<p>
96147932f199be4ad038778e702c13a2f79051c0sliveIn our httpd.conf file, we can now change the hard-coded configuration by
96147932f199be4ad038778e702c13a2f79051c0sliveadding a few lines:
81785f72c9d133aef57ad6b02f248345d90239aapoirier</p>
96147932f199be4ad038778e702c13a2f79051c0slive<highlight language="config">
70373b9ee042e7b3be82eee14b17f510fffdacc9sliveExampleEnabled On
81785f72c9d133aef57ad6b02f248345d90239aapoirierExamplePath "/usr/bin/foo"
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemExampleAction file allow
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</highlight>
81785f72c9d133aef57ad6b02f248345d90239aapoirier<p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenAnd thus we apply the configuration, visit <code>/example</code> on our
545fa9d9188f1ae00e785e784f23e1f0a62b7c25sfweb site, and we see the configuration has adapted to what we wrote in our
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenconfiguration file.
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</p>
545fa9d9188f1ae00e785e784f23e1f0a62b7c25sf</section>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</section>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<section id="context"><title>Context aware configurations</title>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<section id="context_intro"><title>Introduction to context aware configurations</title>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenIn Apache HTTP Server 2.4, different URLs, virtual hosts, directories etc can have very
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowendifferent meanings to the user of the server, and thus different contexts
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenwithin which modules must operate. For example, let's assume you have this
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenconfiguration set up for mod_rewrite:
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<highlight language="config">
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen&lt;Directory &quot;/var/www&quot;&gt;
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen RewriteCond %{HTTP_HOST} ^example.com$
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen RewriteRule (.*) http://www.example.com/$1
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen&lt;/Directory&gt;
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen&lt;Directory &quot;/var/www/sub&quot;&gt;
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen RewriteRule ^foobar$ index.php?foobar=true
590742c95db6e12a810030a36b295271f3228e31rbowen&lt;/Directory&gt;
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</highlight>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenIn this example, you will have set up two different contexts for
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenmod_rewrite:</p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<ol>
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf<li>Inside <code>/var/www</code>, all requests for <code>http://example.com</code> must go to <code>http://www.example.com</code></li>
39d67f66729a7008c1e73d65a81e778ce819a227rjung<li>Inside <code>/var/www/sub</code>, all requests for <code>foobar</code> must go to <code>index.php?foobar=true</code></li>
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf</ol>
4cb65c31bc681540ea623e1cb2bdd09749fb8d7esf<p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenIf mod_rewrite (or the entire server for that matter) wasn't context aware, then
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenthese rewrite rules would just apply to every and any request made,
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenregardless of where and how they were made, but since the module can pull
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenthe context specific configuration straight from the server, it does not need
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowento know itself, which of the directives are valid in this context, since
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenthe server takes care of this.</p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenSo how does a module get the specific configuration for the server,
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowendirectory or location in question? It does so by making one simple call:
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<!-- BEGIN EXAMPLE CODE -->
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<highlight language="c">
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenexample_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-&gt;per_dir_config, &amp;example_module);
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</highlight>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<!-- END EXAMPLE CODE -->
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<p>
1e6708ac9aebbbd0ff63c2b93e6b97d50263a8bbrbowenThat's it! Of course, a whole lot goes on behind the scenes, which we will
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowendiscuss in this chapter, starting with how the server came to know what our
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenconfiguration looks like, and how it came to be set up as it is in the
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenspecific context.
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</section>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<section id="context_base"><title>Our basic configuration setup</title>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<p>In this chapter, we will be working with a slightly modified version of
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenour previous context structure. We will set a <code>context</code>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenvariable that we can use to track which context configuration is being
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenused by the server in various places:
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<!-- BEGIN EXAMPLE CODE -->
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<highlight language="c">
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowentypedef struct {
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen char context[256];
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen char path[256];
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen int typeOfAction;
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen int enabled;
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen} example_config;
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</highlight>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<!-- END EXAMPLE CODE -->
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<p>Our handler for requests will also be modified, yet still very simple:</p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<!-- BEGIN EXAMPLE CODE -->
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<highlight language="c">
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenstatic int example_handler(request_rec *r)
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen{
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen if(!r->handler || strcmp(r->handler, "example-handler")) return(DECLINED);
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen example_config *config = (example_config*) ap_get_module_config(r->per_dir_config, &amp;example_module);
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen ap_set_content_type(r, "text/plain");
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen ap_rprintf("Enabled: %u\n", config->enabled);
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen ap_rprintf("Path: %s\n", config->path);
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen ap_rprintf("TypeOfAction: %x\n", config->typeOfAction);
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen ap_rprintf("Context: %s\n", config->context);
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen return OK;
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen}
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</highlight>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<!-- END EXAMPLE CODE -->
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</section>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<section id="context_which"><title>Choosing a context</title>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenBefore we can start making our module context aware, we must first define,
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenwhich contexts we will accept. As we saw in the previous chapter, defining
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowena directive required five elements be set:</p>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<!-- BEGIN EXAMPLE CODE -->
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<highlight language="c">
1e6708ac9aebbbd0ff63c2b93e6b97d50263a8bbrbowenAP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
1e6708ac9aebbbd0ff63c2b93e6b97d50263a8bbrbowen</highlight>
1e6708ac9aebbbd0ff63c2b93e6b97d50263a8bbrbowen<!-- END EXAMPLE CODE -->
1e6708ac9aebbbd0ff63c2b93e6b97d50263a8bbrbowen
1e6708ac9aebbbd0ff63c2b93e6b97d50263a8bbrbowen
1e6708ac9aebbbd0ff63c2b93e6b97d50263a8bbrbowen<p>The <code>RSRC_CONF</code> definition told the server that we would only allow
1e6708ac9aebbbd0ff63c2b93e6b97d50263a8bbrbowenthis directive in a global server context, but since we are now trying out
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowena context aware version of our module, we should set this to something
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenmore lenient, namely the value <code>ACCESS_CONF</code>, which lets us use
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenthe directive inside &lt;Directory&gt; and &lt;Location&gt; blocks. For more
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowencontrol over the placement of your directives, you can combine the following
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowenrestrictions together to form a specific rule:
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen</p>
3ad007d5c5f33f127acfb6cacffa7a63d6df1068rbowen<ul>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<li><code>RSRC_CONF</code>: Allow in .conf files (not .htaccess) outside &lt;Directory&gt; or &lt;Location&gt;</li>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<li><code>ACCESS_CONF</code>: Allow in .conf files (not .htaccess) inside &lt;Directory&gt; or &lt;Location&gt;</li>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<li><code>OR_OPTIONS</code>: Allow in .conf files and .htaccess when <code>AllowOverride Options</code> is set</li>
ee9cda8f648f99a0b889cb0831ba5b1efe6b3eb5rbowen<li><code>OR_FILEINFO</code>: Allow in .conf files and .htaccess when <code>AllowOverride FileInfo</code> is set</li>
ff21ab9f1cc3037fe58a2029432834581594b6c4pctony<li><code>OR_AUTHCFG</code>: Allow in .conf files and .htaccess when <code>AllowOverride AuthConfig</code> is set</li>
de68ca33425122cf4a880859013e08e84f8143a5covener<li><code>OR_INDEXES</code>: Allow in .conf files and .htaccess when <code>AllowOverride Indexes</code> is set</li>
de68ca33425122cf4a880859013e08e84f8143a5covener<li><code>OR_ALL</code>: Allow anywhere in .conf files and .htaccess</li>
de68ca33425122cf4a880859013e08e84f8143a5covener</ul>
81785f72c9d133aef57ad6b02f248345d90239aapoirier</section>
4e6d765a1b53690664877065e6b6c741c1b96937covener
de68ca33425122cf4a880859013e08e84f8143a5covener<section id="context_pool"><title>Using the server to allocate configuration slots</title>
de68ca33425122cf4a880859013e08e84f8143a5covener<p> A much smarter way to manage your configurations is by letting the server
de68ca33425122cf4a880859013e08e84f8143a5covenerhelp you create them. To do so, we must first start off by changing our
de68ca33425122cf4a880859013e08e84f8143a5covener<em>name tag</em> to let the server know, that it should assist us in creating
de68ca33425122cf4a880859013e08e84f8143a5covenerand managing our configurations. Since we have chosen the per-directory
de68ca33425122cf4a880859013e08e84f8143a5covener(or per-location) context for our module configurations, we'll add a
06ba4a61654b3763ad65f52283832ebf058fdf1csliveper-directory creator and merger function reference in our tag:</p>
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluem
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<!-- BEGIN EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<highlight language="c">
06ba4a61654b3763ad65f52283832ebf058fdf1cslivemodule AP_MODULE_DECLARE_DATA example_module =
97a9a944b5887e91042b019776c41d5dd74557aferikabele{
06ba4a61654b3763ad65f52283832ebf058fdf1cslive STANDARD20_MODULE_STUFF,
97a9a944b5887e91042b019776c41d5dd74557aferikabele create_dir_conf, /* Per-directory configuration handler */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive merge_dir_conf, /* Merge handler for per-directory configurations */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive NULL, /* Per-server configuration handler */
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen NULL, /* Merge handler for per-server configurations */
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen directives, /* Any directives we may have for httpd */
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen register_hooks /* Our hook registering function */
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen};
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</highlight>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<!-- END EXAMPLE CODE -->
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</section>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<section id="context_new"><title>Creating new context configurations</title>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<p>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenNow that we have told the server to help us create and manage configurations,
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenour first step is to make a function for creating new, blank
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenconfigurations. We do so by creating the function we just referenced in
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenour name tag as the Per-directory configuration handler:</p>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<!-- BEGIN EXAMPLE CODE -->
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<highlight language="c">
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenvoid* example_create_dir_conf(apr_pool_t* pool, char* context) {
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen context = context ? context : "(undefined context)";
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen example_config *cfg = apr_pcalloc(pool, sizeof(example_config));
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen if(cfg) {
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen /* Set some default values */
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen strcpy(cfg->context, x);
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen cfg->enabled = 0;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen cfg->path = "/foo/bar";
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen cfg->typeOfAction = 0x11;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen }
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen return cfg;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen}
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</highlight>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<!-- END EXAMPLE CODE -->
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</section>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<section id="context_merge"><title>Merging configurations</title>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<p>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenOur next step in creating a context aware configuration is merging
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenconfigurations. This part of the process particularly applies to scenarios
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenwhere you have a parent configuration and a child, such as the following:
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</p>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<highlight language="config">
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen&lt;Directory &quot;/var/www&quot;&gt;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExampleEnabled On
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExamplePath /foo/bar
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExampleAction file allow
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen&lt;/Directory&gt;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen&lt;Directory &quot;/var/www/subdir&quot;&gt;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExampleAction file deny
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen&lt;/Directory&gt;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</highlight>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<p>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenIn this example, it is natural to assume that the directory <code>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen/var/www/subdir</code> should inherit the values set for the <code>/var/www
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</code> directory, as we did not specify an <code>ExampleEnabled</code> nor
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenan <code>ExamplePath</code> for this directory. The server does not presume to
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenknow if this is true, but cleverly does the following:
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</p>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<ol>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<li>Creates a new configuration for <code>/var/www</code></li>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<li>Sets the configuration values according to the directives given for <code>/var/www</code></li>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<li>Creates a new configuration for <code>/var/www/subdir</code></li>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<li>Sets the configuration values according to the directives given for <code>/var/www/subdir</code></li>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<li><strong>Proposes a merge</strong> of the two configurations into a new configuration for <code>/var/www/subdir</code></li>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive</ol>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<p>
97a9a944b5887e91042b019776c41d5dd74557aferikabeleThis proposal is handled by the <code>merge_dir_conf</code> function we
bf380c59be3f235bde21f1c00098e09e3cf7e7aerpluemreferenced in our name tag. The purpose of this function is to assess the
97a9a944b5887e91042b019776c41d5dd74557aferikabeletwo configurations and decide how they are to be merged:</p>
06ba4a61654b3763ad65f52283832ebf058fdf1cslive
81785f72c9d133aef57ad6b02f248345d90239aapoirier
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<!-- BEGIN EXAMPLE CODE -->
06ba4a61654b3763ad65f52283832ebf058fdf1cslive<highlight language="c">
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenvoid* merge_dir_conf(apr_pool_t* pool, void* BASE, void* ADD) {
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen example_config* base = (example_config *) BASE ; /* This is what was set in the parent context */
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen example_config* add = (example_config *) ADD ; /* This is what is set in the new context */
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen example_config* conf = (example_config *) create_dir_conf(pool, "Merged configuration"); /* This will be the merged configuration */
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen /* Merge configurations */
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen conf->enabled = ( add->enabled == 0 ) ? base->enabled : add->enabled ;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen conf->typeOfAction = add->typeOfAction ? add->typeOfAction : base->typeOfAction;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen strcpy(conf->path, strlen(add->path) ? add->path : base->path);
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen return conf ;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen}
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</highlight>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<!-- END EXAMPLE CODE -->
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</section>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<section id="context_example"><title>Trying out our new context aware configurations</title>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<p>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenNow, let's try putting it all together to create a new module that is
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowencontext aware. First off, we'll create a configuration that lets us test
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenhow the module works:
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</p>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<highlight language="config">
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen&lt;Location &quot;/a&quot;&gt;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen SetHandler example-handler
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExampleEnabled on
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExamplePath &quot;/foo/bar&quot;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExampleAction file allow
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen&lt;/Location&gt;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen&lt;Location &quot;/a/b&quot;&gt;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExampleAction file deny
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExampleEnabled off
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen&lt;/Location&gt;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen&lt;Location &quot;/a/b/c&quot;&gt;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExampleAction db deny
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExamplePath &quot;/foo/bar/baz&quot;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen ExampleEnabled on
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen&lt;/Location&gt;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</highlight>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<p>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenThen we'll assemble our module code. Note, that since we are now using our
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenname tag as reference when fetching configurations in our handler, I have
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowenadded some prototypes to keep the compiler happy:
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen</p>
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<!-- BEGIN EXAMPLE CODE -->
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen<highlight language="c">
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen/*$6
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen * mod_example_config.c
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen */
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen#include &lt;stdio.h&gt;
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen#include "apr_hash.h"
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen#include "ap_config.h"
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen#include "ap_provider.h"
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen#include "httpd.h"
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen#include "http_core.h"
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen#include "http_config.h"
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen#include "http_log.h"
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen#include "http_protocol.h"
06ba4a61654b3763ad65f52283832ebf058fdf1cslive#include "http_request.h"
34212fdb21f03f4e180a3226f83e39af0371d7dbrbowen
06ba4a61654b3763ad65f52283832ebf058fdf1cslive/*$1
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd Configuration structure
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd */
7dc5a2d4a0c77f5bf5a95de92d68e43de7d8117anilgun
7dc5a2d4a0c77f5bf5a95de92d68e43de7d8117anilguntypedef struct
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd{
9c1260efa52c82c2a58e5b5f20cd6902563d95f5rbowen char context[256];
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd char path[256];
0c0b2cdbccd4ddc8f07574c36444bf9a795a3e1cjim int typeOfAction;
int enabled;
} example_config;
/*$1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Prototypes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
static int example_handler(request_rec *r);
const char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg);
const char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg);
const char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char *arg2);
void *create_dir_conf(apr_pool_t *pool, char *context);
void *merge_dir_conf(apr_pool_t *pool, void *BASE, void *ADD);
static void register_hooks(apr_pool_t *pool);
/*$1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Configuration directives
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
static const command_rec directives[] =
{
AP_INIT_TAKE1(&quot;exampleEnabled&quot;, example_set_enabled, NULL, ACCESS_CONF, &quot;Enable or disable mod_example&quot;),
AP_INIT_TAKE1(&quot;examplePath&quot;, example_set_path, NULL, ACCESS_CONF, &quot;The path to whatever&quot;),
AP_INIT_TAKE2(&quot;exampleAction&quot;, example_set_action, NULL, ACCESS_CONF, &quot;Special action value!&quot;),
{ NULL }
};
/*$1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Our name tag
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
module AP_MODULE_DECLARE_DATA example_module =
{
STANDARD20_MODULE_STUFF,
create_dir_conf, /* Per-directory configuration handler */
merge_dir_conf, /* Merge handler for per-directory configurations */
NULL, /* Per-server configuration handler */
NULL, /* Merge handler for per-server configurations */
directives, /* Any directives we may have for httpd */
register_hooks /* Our hook registering function */
};
/*
=======================================================================================================================
Hook registration function
=======================================================================================================================
*/
static void register_hooks(apr_pool_t *pool)
{
ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
}
/*
=======================================================================================================================
Our example web service handler
=======================================================================================================================
*/
static int example_handler(request_rec *r)
{
if(!r-&gt;handler || strcmp(r-&gt;handler, &quot;example-handler&quot;)) return(DECLINED);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
example_config *config = (example_config *) ap_get_module_config(r-&gt;per_dir_config, &amp;example_module);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
ap_set_content_type(r, &quot;text/plain&quot;);
ap_rprintf(r, &quot;Enabled: %u\n&quot;, config-&gt;enabled);
ap_rprintf(r, &quot;Path: %s\n&quot;, config-&gt;path);
ap_rprintf(r, &quot;TypeOfAction: %x\n&quot;, config-&gt;typeOfAction);
ap_rprintf(r, &quot;Context: %s\n&quot;, config-&gt;context);
return OK;
}
/*
=======================================================================================================================
Handler for the &quot;exampleEnabled&quot; directive
=======================================================================================================================
*/
const char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
example_config *conf = (example_config *) cfg;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if(conf)
{
if(!strcasecmp(arg, &quot;on&quot;))
conf-&gt;enabled = 1;
else
conf-&gt;enabled = 0;
}
return NULL;
}
/*
=======================================================================================================================
Handler for the &quot;examplePath&quot; directive
=======================================================================================================================
*/
const char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
example_config *conf = (example_config *) cfg;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if(conf)
{
strcpy(conf-&gt;path, arg);
}
return NULL;
}
/*
=======================================================================================================================
Handler for the &quot;exampleAction&quot; directive ;
Let's pretend this one takes one argument (file or db), and a second (deny or allow), ;
and we store it in a bit-wise manner.
=======================================================================================================================
*/
const char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char *arg2)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
example_config *conf = (example_config *) cfg;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if(conf)
{
{
if(!strcasecmp(arg1, &quot;file&quot;))
conf-&gt;typeOfAction = 0x01;
else
conf-&gt;typeOfAction = 0x02;
if(!strcasecmp(arg2, &quot;deny&quot;))
conf-&gt;typeOfAction += 0x10;
else
conf-&gt;typeOfAction += 0x20;
}
}
return NULL;
}
/*
=======================================================================================================================
Function for creating new configurations for per-directory contexts
=======================================================================================================================
*/
void *create_dir_conf(apr_pool_t *pool, char *context)
{
context = context ? context : &quot;Newly created configuration&quot;;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
example_config *cfg = apr_pcalloc(pool, sizeof(example_config));
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if(cfg)
{
{
/* Set some default values */
strcpy(cfg-&gt;context, context);
cfg-&gt;enabled = 0;
memset(cfg-&gt;path, 0, 256);
cfg-&gt;typeOfAction = 0x00;
}
}
return cfg;
}
/*
=======================================================================================================================
Merging function for configurations
=======================================================================================================================
*/
void *merge_dir_conf(apr_pool_t *pool, void *BASE, void *ADD)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
example_config *base = (example_config *) BASE;
example_config *add = (example_config *) ADD;
example_config *conf = (example_config *) create_dir_conf(pool, &quot;Merged configuration&quot;);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
conf-&gt;enabled = (add-&gt;enabled == 0) ? base-&gt;enabled : add-&gt;enabled;
conf-&gt;typeOfAction = add-&gt;typeOfAction ? add-&gt;typeOfAction : base-&gt;typeOfAction;
strcpy(conf-&gt;path, strlen(add-&gt;path) ? add-&gt;path : base-&gt;path);
return conf;
}
</highlight>
<!-- END EXAMPLE CODE -->
</section>
</section>
<section id="summary"><title>Summing up</title>
<p>
We have now looked at how to create simple modules for Apache HTTP Server 2.4 and
configuring them. What you do next is entirely up to you, but it is my
hope that something valuable has come out of reading this documentation.
If you have questions on how to further develop modules, you are welcome
to join our <a href="http://httpd.apache.org/lists.html">mailing lists</a>
or check out the rest of our documentation for further tips.
</p>
</section>
<section id="snippets"><title>Some useful snippets of code</title>
<section id="get_post"><title>Retrieve variables from POST form data</title>
<!-- BEGIN EXAMPLE CODE -->
<highlight language="c">
typedef struct {
const char* key;
const char* value;
} keyValuePair;
keyValuePair* readPost(request_rec* r) {
apr_array_header_t *pairs = NULL;
apr_off_t len;
apr_size_t size;
int res;
int i = 0;
char *buffer;
keyValuePair* kvp;
res = ap_parse_form_data(r, NULL, &amp;pairs, -1, HUGE_STRING_LEN);
if (res != OK || !pairs) return NULL; /* Return NULL if we failed or if there are is no POST data */
kvp = apr_pcalloc(r->pool, sizeof(keyValuePair) * (pairs->nelts + 1));
while (pairs &amp;&amp; !apr_is_empty_array(pairs)) {
ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs);
apr_brigade_length(pair->value, 1, &amp;len);
size = (apr_size_t) len;
buffer = apr_palloc(r->pool, size + 1);
apr_brigade_flatten(pair->value, buffer, &amp;size);
buffer[len] = 0;
kvp[i].key = apr_pstrdup(r->pool, pair->name);
kvp[i].value = buffer;
i++;
}
return kvp;
}
static int example_handler(request_rec *r)
{
/*~~~~~~~~~~~~~~~~~~~~~~*/
keyValuePair* formData;
/*~~~~~~~~~~~~~~~~~~~~~~*/
formData = readPost(r);
if (formData) {
int i;
for (i = 0; &amp;formData[i]; i++) {
if (formData[i].key &amp;&amp; formData[i].value) {
ap_rprintf(r, &quot;%s = %s\n&quot;, formData[i].key, formData[i].value);
} else if (formData[i].key) {
ap_rprintf(r, &quot;%s\n&quot;, formData[i].key);
} else if (formData[i].value) {
ap_rprintf(r, &quot;= %s\n&quot;, formData[i].value);
} else {
break;
}
}
}
return OK;
}
</highlight>
<!-- END EXAMPLE CODE -->
</section>
<section id="headers_out"><title>Printing out every HTTP header received</title>
<!-- BEGIN EXAMPLE CODE -->
<highlight language="c">
static int example_handler(request_rec *r)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
const apr_array_header_t *fields;
int i;
apr_table_entry_t *e = 0;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
fields = apr_table_elts(r-&gt;headers_in);
e = (apr_table_entry_t *) fields-&gt;elts;
for(i = 0; i &lt; fields-&gt;nelts; i++) {
ap_rprintf(r, &quot;%s: %s\n&quot;, e[i].key, e[i].val);
}
return OK;
}
</highlight>
<!-- END EXAMPLE CODE -->
</section>
<section id="request_body"><title>Reading the request body into memory</title>
<!-- BEGIN EXAMPLE CODE -->
<highlight language="c">
static int util_read(request_rec *r, const char **rbuf, apr_off_t *size)
{
/*~~~~~~~~*/
int rc = OK;
/*~~~~~~~~*/
if((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
return(rc);
}
if(ap_should_client_block(r)) {
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
char argsbuffer[HUGE_STRING_LEN];
apr_off_t rsize, len_read, rpos = 0;
apr_off_t length = r-&gt;remaining;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
*rbuf = (const char *) apr_pcalloc(r-&gt;pool, (apr_size_t) (length + 1));
*size = length;
while((len_read = ap_get_client_block(r, argsbuffer, sizeof(argsbuffer))) &gt; 0) {
if((rpos + len_read) &gt; length) {
rsize = length - rpos;
}
else {
rsize = len_read;
}
memcpy((char *) *rbuf + rpos, argsbuffer, (size_t) rsize);
rpos += rsize;
}
}
return(rc);
}
static int example_handler(request_rec* r)
{
/*~~~~~~~~~~~~~~~~*/
apr_off_t size;
const char *buffer;
/*~~~~~~~~~~~~~~~~*/
if(util_read(r, &amp;buffer, &amp;size) == OK) {
ap_rprintf(r, &quot;We read a request body that was %" APR_OFF_T_FMT " bytes long&quot;, size);
}
return OK;
}
</highlight>
<!-- END EXAMPLE CODE -->
</section>
</section>
</manualpage>