modguide.xml revision f8416dc84af095ff95eb80657ca62fed7ddf7e7c
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<?xml version='1.0' encoding='UTF-8' ?>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!DOCTYPE manualpage SYSTEM "/style/manualpage.dtd">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<?xml-stylesheet type="text/xsl" href="/style/manual.en.xsl"?>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- $LastChangedRevision$ -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!--
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Licensed to the Apache Software Foundation (ASF) under one or more
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster contributor license agreements. See the NOTICE file distributed with
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this work for additional information regarding copyright ownership.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster The ASF licenses this file to You under the Apache License, Version 2.0
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster (the "License"); you may not use this file except in compliance with
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster the License. You may obtain a copy of the License at
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster http://www.apache.org/licenses/LICENSE-2.0
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Unless required by applicable law or agreed to in writing, software
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster distributed under the License is distributed on an "AS IS" BASIS,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster See the License for the specific language governing permissions and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster-->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<manualpage metafile="modguide.xml.meta">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<parentdocument href="./">Developer</parentdocument>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunnington <title>Developing modules for the Apache HTTP Server 2.4</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<summary>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>This document explains how you can develop modules for the Apache HTTP
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterServer 2.4</p>
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden</summary>
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<seealso><a href="request.html">Request Processing in Apache 2.4</a></seealso>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<seealso><a href="hooks.html">Apache 2.x Hook Functions</a></seealso>
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott<section id="introduction"><title>Introduction</title>
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott<section id="what"><title>What we will be discussing in this document</title>
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott<p>
72450cb9c2ca854c6d3479832c2738196c1d3282Robert WapshottThis document will discuss how you can create modules for the Apache
01a939641aeb0a095851921879620c3fab295cb2Robert WapshottHTTP Server 2.4, by exploring an example module called
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<code>mod_example</code>. In the first part of this document, the purpose
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterof this module will be to calculate and print out various digest values for
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterexisting files on your web server, whenever we access the URL <code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterhttp://hostname/filename.sum</code>. For instance, if we want to know the
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterMD5 digest value of the file located at <code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterhttp://www.example.com/index.html</code>, we would visit <code>
01a939641aeb0a095851921879620c3fab295cb2Robert Wapshotthttp://www.example.com/index.html.sum</code>.
01a939641aeb0a095851921879620c3fab295cb2Robert Wapshott</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterIn the second part of this document, which deals with configuration
01a939641aeb0a095851921879620c3fab295cb2Robert Wapshottdirective and context awareness, we will be looking at a module that simply
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterwrites out its own configuration to the client.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
01a939641aeb0a095851921879620c3fab295cb2Robert Wapshott</section>
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<section id="prerequisites"><title>Prerequisites</title>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert WapshottFirst and foremost, you are expected to have a basic knowledge of how the C
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottprogramming language works. In most cases, we will try to be as pedagogical
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottas possible and link to documents describing the functions used in the
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottexamples, but there are also many cases where it is necessary to either
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottjust assume that "it works" or do some digging yourself into what the hows
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottand whys of various function calls.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterLastly, you will need to have a basic understanding of how modules are
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterloaded and configured in the Apache HTTP Server, as well as how to get the headers for
01a939641aeb0a095851921879620c3fab295cb2Robert WapshottApache if you do not have them already, as these are needed for compiling
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosternew modules.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
01a939641aeb0a095851921879620c3fab295cb2Robert Wapshott</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="compiling"><title>Compiling your module</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterTo compile the source code we are building in this document, we will be
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellusing <a href="/programs/apxs.html">APXS</a>. Assuming your source file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosteris called mod_example.c, compiling, installing and activating the module is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosteras simple as:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<example><pre>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterapxs -i -a -c mod_example.c
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</pre></example>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<section id="basics"><title>Defining a module</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<img src="/images/build_a_mod_3.png" alt="Module name tags"/><br/>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterEvery module starts with the same declaration, or name tag if you will,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterthat defines a module as <em>a separate entity within Apache</em>:</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermodule AP_MODULE_DECLARE_DATA example_module =
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster STANDARD20_MODULE_STUFF,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster create_dir_conf, /* Per-directory configuration handler */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster merge_dir_conf, /* Merge handler for per-directory configurations */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster create_svr_conf, /* Per-server configuration handler */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster merge_svr_conf, /* Merge handler for per-server configurations */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster directives, /* Any directives we may have for httpd */
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford register_hooks /* Our hook registering function */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster};
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford</highlight>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterThis bit of code lets the server know that we have now registered a new module
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterin the system, and that its name is <code>example_module</code>. The name
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterof the module is used primarily for two things:<br/>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li>Letting the server know how to load the module using the LoadModule</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li>Setting up a namespace for the module to use in configurations</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterFor now, we're only concerned with the first purpose of the module name,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterwhich comes into play when we need to load the module:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="config">
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterLoadModule example_module modules/mod_example.so
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterIn essence, this tells the server to open up <code>mod_example.so</code> and look for a module
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostercalled <code>example_module</code>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterWithin this name tag of ours is also a bunch of references to how we would
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterlike to handle things: Which directives do we respond to in a configuration
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterfile or .htaccess, how do we operate within specific contexts, and what
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterhandlers are we interested in registering with the Apache HTTP service. We'll
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterreturn to all these elements later in this document.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="hooking"><title>Getting started: Hooking into the server</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="hook_intro"><title>An introduction to hooks</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterWhen handling requests in Apache HTTP Server 2.4, the first thing you will need to do is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostercreate a hook into the request handling process. A hook is essentially a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermessage telling the server that you are willing to either serve or at least
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertake a glance at certain requests given by clients. All handlers, whether
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterit's mod_rewrite, mod_authn_*, mod_proxy and so on, are hooked into
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterspecific parts of the request process. As you are probably aware, modules
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterserve different purposes; Some are authentication/authorization handlers,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterothers are file or script handlers while some third modules rewrite URIs or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterproxies content. Furthermore, in the end, it is up to the user of the server
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterhow and when each module will come into place. Thus, the server itself does not
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpresume to know which module is responsible for handling a specific
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterrequest, and will ask each module whether they have an interest in a given
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterrequest or not. It is then up to each module to either gently decline
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterserving a request, accept serving it or flat out deny the request from
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterbeing served, as authentication/authorization modules do: <br/>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<img src="/images/build_a_mod_2.png" alt="Hook handling in httpd"/><br/>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterTo make it a bit easier for handlers such as our mod_example to know
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterwhether the client is requesting content we should handle or not, the server
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunningtonhas directives for hinting to modules whether their assistance is needed or
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunningtonnot. Two of these are <directive module="mod_mime">AddHandler</directive>
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunningtonand <directive module="core">SetHandler</directive>. Let's take a look at
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunningtonan example using <directive module="mod_mime">AddHandler</directive>. In
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunningtonour example case, we want every request ending with .sum to be served by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<code>mod_example</code>, so we'll add a configuration directive that tells
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterthe server to do just that:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="config">
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterAddHandler example-handler .sum
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellWhat this tells the server is the following: <em>Whenever we receive a request
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellfor a URI ending in .sum, we are to let all modules know that we are
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnelllooking for whoever goes by the name of &quot;example-handler&quot; </em>.
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellThus, when a request is being served that ends in .sum, the server will let all
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellmodules know, that this request should be served by &quot;example-handler
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell&quot;. As you will see later, when we start building mod_example, we will
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellcheck for this handler tag relayed by <code>AddHandler</code> and reply to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterthe server based on the value of this tag.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<section id="hook_declaration"><title>Hooking into httpd</title>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert WapshottTo begin with, we only want to create a simple handler, that replies to the
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellclient browser when a specific URL is requested, so we won't bother setting
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottup configuration handlers and directives just yet. Our initial module
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottdefinition will look like this:</p>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<!-- BEGIN EXAMPLE CODE -->
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<highlight language="c">
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellmodule AP_MODULE_DECLARE_DATA example_module =
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell{
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell STANDARD20_MODULE_STUFF,
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell NULL,
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell NULL,
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell NULL,
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell NULL,
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell NULL,
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott register_hooks /* Our hook registering function */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster};
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>This lets the server know that we are not interesting in anything fancy, we
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterjust want to hook onto the requests and possibly handle some of them. </p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p> The reference in our example declaration, <code>register_hooks</code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosteris the name of a function we will create to manage how we hook onto the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterrequest process. In this example module, the function has just one purpose;
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterTo create a simple hook that gets called after all the rewrites, access
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostercontrol etc has been handled. Thus, we will let the server know, that we want
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterto hook into its process as one of the last modules:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic void register_hooks(apr_pool_t *pool)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Create a hook in the request handler, so we get called when a request arrives */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert WapshottThe <code>example_handler</code> reference is the function that will handle
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottthe request. We will discuss how to create a handler in the next chapter.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="hook_others"><title>Other useful hooks</title>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterHooking into the request handling phase is but one of many hooks that you
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostercan create. Some other ways of hooking are:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<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>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>ap_hook_pre_config</code>: Place a hook that executes before any configuration data has been read (very early hook)</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>ap_hook_post_config</code>: Place a hook that executes after configuration has been parsed, but before the server has forked</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<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>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<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>
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott<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>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<section id="handling"><title>Building a handler</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert WapshottA handler is essentially a function that receives a callback when a request
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottto the server is made. It is passed a record of the current request (how it was
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermade, which headers and requests were passed along, who's giving the
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottrequest and so on), and is put in charge of either telling the server that it's
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosternot interested in the request or handle the request with the tools provided.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="simple_handler"><title>A simple &quot;Hello, world!&quot;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshotthandler</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>Let's start off by making a very simple request handler
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottthat does the following:
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<ol>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li>Check that this is a request that should be served by &quot;example-handler&quot;</li>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li>Set the content type of our output to <code>text/html</code></li>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li>Write &quot;Hello, world!&quot; back to the client browser</li>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li>Let the server know that we took care of this request and everything went fine</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</ol>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterIn C code, our example handler will now look like this:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<!-- BEGIN EXAMPLE CODE -->
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<highlight language="c">
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottstatic int example_handler(request_rec *r)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /* First off, we need to check if this is a call for the "example-handler" handler.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * If it is, we accept it and do our things, if not, we simply return DECLINED,
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * and the server will try somewhere else.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott if (!r->handler || strcmp(r->handler, "example-handler")) return (DECLINED);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /* Now that we are handling this request, we'll write out "Hello, world!" to the client.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * To do so, we must first set the appropriate content type, followed by our output.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott ap_set_content_type(r, "text/html");
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott ap_rprintf(r, "Hello, world!");
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /* Lastly, we must tell the server that we took care of this request and everything went fine.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * We do so by simply returning the value OK to the server.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott return OK;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott}
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</highlight>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<!-- END EXAMPLE CODE -->
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert WapshottNow, we put all we have learned together and end up with a program that
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottlooks like
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<a href="http://people.apache.org/~humbedooh/mods/examples/mod_example_1.c">mod_example_1.c</a>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster. The functions used in this example will be explained later in the section
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<a href= "#functions">&quot;Some useful functions you should know&quot;</a>.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</section>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<section id="request_rec"><title>The request_rec structure</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>The most essential part of any request is the <em>request record
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford</em>. In a call to a handler function, this is represented by the <code>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottrequest_rec* </code> structure passed along with every call that is made.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert WapshottThis struct, typically just referred to as <code>r</code> in modules,
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottcontains all the information you need for your module to fully process any
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterHTTP request and respond accordingly.</p> <p>Some key elements of the <code>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottrequest_rec </code> structure are:
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</p>
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott<ul>
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott<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>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li><code>r-&gt;method (char*):</code> Contains the HTTP method being used, f.x. GET or POST</li>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li><code>r-&gt;filename (char*):</code> Contains the translated filename the client is requesting</li>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li><code>r-&gt;args (char*):</code> Contains the query string of the request, if any</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>r-&gt;headers_in (apr_table_t*):</code> Contains all the headers sent by the client</li>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li><code>r-&gt;connection (conn_rec*):</code> A record containing information about the current connection</li>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li><code>r-&gt;user (char*):</code> If the URI requires authentication, this is set to the username provided</li>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li><code>r-&gt;useragent_ip (char*):</code> The IP address of the client connecting to us</li>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<li><code>r-&gt;pool (apr_pool_t*)</code>: The memory pool of this request. We'll discuss this in the
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott&quot;<a href="#memory">Memory management</a>&quot; chapter.</li>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</ul>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert WapshottA complete list of all the values contained within the <code>request_rec</code> structure can be found in
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottthe <a href="http://svn.apache.org/repos/asf/httpd/httpd/trunk/include/httpd.h"><code>httpd.h</code></a> header
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottfile 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>.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert WapshottLet's try out some of these variables in another example handler:<br/>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell</p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<!-- BEGIN EXAMPLE CODE -->
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int example_handler(request_rec *r)
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Set the appropriate content type */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_set_content_type(r, &quot;text/html&quot;);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Print out the IP address of the client connecting to us: */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott ap_rprintf(r, &quot;&lt;h2&gt;Hello, %s!&lt;/h2&gt;&quot;, r-&gt;useragent_ip);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* If we were reached through a GET or a POST request, be happy, else sad. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( !strcmp(r-&gt;method, &quot;POST&quot;) || !strcmp(r-&gt;method, &quot;GET&quot;) ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rputs(&quot;You used a GET or a POST method, that makes us happy!&lt;br/&gt;&quot;, r);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rputs(&quot;You did not use POST or GET, that makes us sad :(&lt;br/&gt;&quot;, r);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Lastly, if there was a query string, let's print that too! */
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford if (r-&gt;args) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf(r, &quot;Your query string was: %s&quot;, r-&gt;args);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return OK;
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="return_value"><title>Return values</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony BamfordApache relies on return values from handlers to signify whether a request
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterwas handled or not, and if so, whether the request went well or not. If a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermodule is not interested in handling a specific request, it should always
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterreturn the value <code>DECLINED</code>. If it is handling a request, it
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamfordshould either return the generic value <code>OK</code>, or a specific HTTP
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatus code, for example:
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<highlight language="c">
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellstatic int example_handler(request_rec *r)
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell{
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /* Return 404: Not found */
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell return HTTP_NOT_FOUND;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
bcb85423bc6855cb1c7accc69fa051e1771c000aMark de ReeperReturning <code>OK</code> or a HTTP status code does not necessarily mean
bcb85423bc6855cb1c7accc69fa051e1771c000aMark de Reeperthat the request will end. The server may still have other handlers that are
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterinterested in this request, for instance the logging modules which, upon a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostersuccessful request, will write down a summary of what was requested and how
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterit went. To do a full stop and prevent any further processing after your
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottmodule is done, you can return the value <code>DONE</code> to let the server
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterknow that it should cease all activity on this request and carry on with
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterthe next, without informing other handlers.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<br/>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<strong>General response codes:</strong>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<ul>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li><code>DECLINED</code>: We are not handling this request</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>OK</code>: We handled this request and it went well</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>DONE</code>: We handled this request and the server should just close this thread without further processing</li>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell</ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<strong>HTTP specific return codes (excerpt):</strong>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>HTTP_OK (200)</code>: Request was okay</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>HTTP_MOVED_PERMANENTLY (301)</code>: The resource has moved to a new URL</li>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li><code>HTTP_UNAUTHORIZED (401)</code>: Client is not authorized to visit this page</li>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<li><code>HTTP_FORBIDDEN (403)</code>: Permission denied</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>HTTP_NOT_FOUND (404)</code>: File not found</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>HTTP_INTERNAL_SERVER_ERROR (500)</code>: Internal server error (self explanatory)</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<section id="functions"><title>Some useful functions you should know</title>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<ul>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<li>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell <code>ap_rputs(const char *string, request_rec *r)</code>: <br/>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell Sends a string of text to the client. This is a shorthand version of <a
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__PROTO.html#gac827cd0537d2b6213a7c06d7c26cc36e">
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell ap_rwrite</a>.
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<!-- BEGIN EXAMPLE CODE -->
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<highlight language="c">ap_rputs("Hello, world!", r);</highlight>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<!-- END EXAMPLE CODE -->
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell</li>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<li>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell <code>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell <a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__PROTO.html#ga5e91eb6ca777c9a427b2e82bf1eeb81d">ap_rprintf</a></code>: <br/>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell This function works just like <code>printf</code>, except it sends the result to the client.
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<!-- BEGIN EXAMPLE CODE -->
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<highlight language="c">ap_rprintf(r, "Hello, %s!", r->useragent_ip);</highlight>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<!-- END EXAMPLE CODE -->
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell</li>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<li>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell <code>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell <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/>
d28c31c7d0cf9ac19eaf07942956e707222fb5ebPeter Major Sets the content type of the output you are sending.
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
d28c31c7d0cf9ac19eaf07942956e707222fb5ebPeter Major
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<!-- BEGIN EXAMPLE CODE -->
d28c31c7d0cf9ac19eaf07942956e707222fb5ebPeter Major<highlight language="c">ap_set_content_type(r, "text/plain"); /* force a raw text output */</highlight>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<!-- END EXAMPLE CODE -->
9709ff1b979ab7830f3e00b809f1157554566ed3Steve Ferris
d28c31c7d0cf9ac19eaf07942956e707222fb5ebPeter Major</li>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
9709ff1b979ab7830f3e00b809f1157554566ed3Steve Ferris
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="memory"><title>Memory management</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterManaging your resources in Apache HTTP Server 2.4 is quite easy, thanks to the memory pool
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostersystem. In essence, each server, connection and request have their own
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermemory pool that gets cleaned up when its scope ends, e.g. when a request
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosteris done or when a server process shuts down. All your module needs to do is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterlatch onto this memory pool, and you won't have to worry about having to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterclean up after yourself - pretty neat, huh?
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterIn our module, we will primarily be allocating memory for each request, so
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterit's appropriate to use the <code>r-&gt;pool</code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterreference when creating new objects. A few of the functions for allocating
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermemory within a pool are:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>void* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__pools.html#ga85f1e193c31d109affda72f9a92c6915">apr_palloc</a>(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterapr_pool_t *p, apr_size_t size)</code>: Allocates <code>size</code> number of bytes in the pool for you</li>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<li><code>void* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__pools.html#gaf61c098ad258069d64cdf8c0a9369f9e">apr_pcalloc</a>(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterapr_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>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>char* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__strings.html#gabc79e99ff19abbd7cfd18308c5f85d47">apr_pstrdup</a>(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterapr_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>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>char* <a href="http://apr.apache.org/docs/apr/1.4/group__apr__strings.html#ga3eca76b8d293c5c3f8021e45eda813d8">apr_psprintf</a>(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterapr_pool_t *p, const char *fmt, ...)</code>: Similar to <code>sprintf</code>, except the server supplies you with an appropriately allocated target variable</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>Let's put these functions into an example handler:</p>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int example_handler(request_rec *r)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster const char* original = "You can't edit this!";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char* copy;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int* integers;
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Allocate space for 10 integer values and set them all to zero. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster integers = apr_pcalloc(r->pool, sizeof(int)*10);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Create a copy of the 'original' variable that we can edit. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster copy = apr_pstrdup(r->pool, original);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return OK;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterThis is all well and good for our module, which won't need any
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpre-initialized variables or structures. However, if we wanted to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterinitialize something early on, before the requests come rolling in, we
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostercould simply add a call to a function in our <code>register_hooks</code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterfunction to sort it out:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic void register_hooks(apr_pool_t *pool)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Call a function that initializes some stuff */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster example_init_function(pool);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Create a hook in the request handler, so we get called when a request arrives */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterIn this pre-request initialization function we would not be using the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostersame pool as we did when allocating resources for request-based functions.
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterInstead, we would use the pool given to us by the server for allocating memory
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosteron a per-process based level.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="parsing"><title>Parsing request data</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterIn our example module, we would like to add a feature, that checks which
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertype of digest, MD5 or SHA1 the client would like to see. This could be
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostersolved by adding a query string to the request. A query string is typically
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostercomprised of several keys and values put together in a string, for instance
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<code>valueA=yes&amp;valueB=no&amp;valueC=maybe</code>. It is up to the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermodule itself to parse these and get the data it requires. In our example,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterwe'll be looking for a key called <code>digest</code>, and if set to <code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermd5</code>, we'll produce an MD5 digest, otherwise we'll produce a SHA1
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterdigest.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterSince the introduction of Apache HTTP Server 2.4, parsing request data from GET and
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterPOST requests have never been easier. All we require to parse both GET and
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterPOST data is four simple lines:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__apr__tables.html#gad7ea82d6608a4a633fc3775694ab71e4">apr_table_t</a> *GET; <em>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</em><a href="http://ci.apache.org/projects/httpd/trunk/doxygen/structapr__array__header__t.html">apr_array_header_t</a>*POST;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<em>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</em>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__SCRIPT.html#gaed25877b529623a4d8f99f819ba1b7bd">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterap_args_to_table</a>(r, &amp;GET); <em>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</em><a href="http://ci.apache.org/projects/httpd/trunk/doxygen/group__APACHE__CORE__DAEMON.html#ga9d426b6382b49754d4f87c55f65af202">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterap_parse_form_data</a>(r, NULL, &amp;POST, -1, 8192);
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterIn our specific example module, we're looking for the <code>digest</code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostervalue from the query string, which now resides inside a table called <code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterGET</code>. To extract this value, we need only perform a simple operation:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* Get the "digest" key from the query string, if any. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterconst char *digestType = apr_table_get(GET, "digest");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* If no key was returned, we will set a default value instead. */
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunningtonif (!digestType) digestType = "sha1";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterThe structures used for the POST and GET data are not exactly the same, so
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamfordif we were to fetch a value from POST data instead of the query string, we
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterwould have to resort to a few more lines, as outlined in <a href="#get_post"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster>this example</a> in the last chapter of this document.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="advanced_handler"><title>Making an advanced handler</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill CunningtonNow that we have learned how to parse form data and manage our resources,
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunningtonwe can move on to creating an advanced version of our module, that spits
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunningtonout the MD5 or SHA1 digest of files:
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunnington</p>
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunnington
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int example_handler(request_rec *r)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden int rc, exists;
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden apr_finfo_t finfo;
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden apr_file_t *file;
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden char *filename;
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden char buffer[256];
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden apr_size_t readBytes;
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden int n;
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden apr_table_t *GET;
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden apr_array_header_t *POST;
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunnington const char *digestType;
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunnington
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden /* Check that the &quot;example-handler&quot; handler is being called. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!r-&gt;handler || strcmp(r-&gt;handler, &quot;example-handler&quot;)) return (DECLINED);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford /* Figure out which file is being requested by removing the .sum from it */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster filename = apr_pstrdup(r-&gt;pool, r-&gt;filename);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster filename[strlen(filename)-4] = 0; /* Cut off the last 4 characters. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Figure out if the file we request a sum on exists and isn't a directory */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = apr_stat(&amp;finfo, filename, APR_FINFO_MIN, r-&gt;pool);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (rc == APR_SUCCESS) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster exists =
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster (
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster (finfo.filetype != APR_NOFILE)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster &amp;&amp; !(finfo.filetype &amp; APR_DIR)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster );
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott if (!exists) return HTTP_NOT_FOUND; /* Return a 404 if not found. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* If apr_stat failed, we're probably not allowed to check this file. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else return HTTP_FORBIDDEN;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Parse the GET and, optionally, the POST data sent to us */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_args_to_table(r, &amp;GET);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_parse_form_data(r, NULL, &amp;POST, -1, 8192);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /* Set the appropriate content type */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_set_content_type(r, &quot;text/html&quot;);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Print a title and some general information */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf(r, &quot;&lt;h2&gt;Information on %s:&lt;/h2&gt;&quot;, filename);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf(r, &quot;&lt;b&gt;Size:&lt;/b&gt; %u bytes&lt;br/&gt;&quot;, finfo.size);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford /* Get the digest type the client wants to see */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster digestType = apr_table_get(GET, &quot;digest&quot;);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!digestType) digestType = &quot;MD5&quot;;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = apr_file_open(&amp;file, filename, APR_READ, APR_OS_DEFAULT, r-&gt;pool);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (rc == APR_SUCCESS) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Are we trying to calculate the MD5 or the SHA1 digest? */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!strcasecmp(digestType, &quot;md5&quot;)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Calculate the MD5 sum of the file */
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford union {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char chr[16];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster uint32_t num[4];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } digest;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster apr_md5_ctx_t md5;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster apr_md5_init(&amp;md5);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster readBytes = 256;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while ( apr_file_read(file, buffer, &amp;readBytes) == APR_SUCCESS ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster apr_md5_update(&amp;md5, buffer, readBytes);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott apr_md5_final(digest.chr, &amp;md5);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Print out the MD5 digest */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rputs(&quot;&lt;b&gt;MD5: &lt;/b&gt;&lt;code&gt;&quot;, r);
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford for (n = 0; n &lt; APR_MD5_DIGESTSIZE/4; n++) {
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell ap_rprintf(r, &quot;%08x&quot;, digest.num[n]);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
e2c8a434054afd7228765bdfb72df3c6117be3b8David Luna ap_rputs(&quot;&lt;/code&gt;&quot;, r);
e2c8a434054afd7228765bdfb72df3c6117be3b8David Luna /* Print a link to the SHA1 version */
e2c8a434054afd7228765bdfb72df3c6117be3b8David Luna ap_rputs(&quot;&lt;br/&gt;&lt;a href='?digest=sha1'&gt;View the SHA1 hash instead&lt;/a&gt;&quot;, r);
e2c8a434054afd7228765bdfb72df3c6117be3b8David Luna }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Calculate the SHA1 sum of the file */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster union {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char chr[20];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster uint32_t num[5];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } digest;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster apr_sha1_ctx_t sha1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster apr_sha1_init(&amp;sha1);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster readBytes = 256;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while ( apr_file_read(file, buffer, &amp;readBytes) == APR_SUCCESS ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster apr_sha1_update(&amp;sha1, buffer, readBytes);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott apr_sha1_final(digest.chr, &amp;sha1);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Print out the SHA1 digest */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rputs(&quot;&lt;b&gt;SHA1: &lt;/b&gt;&lt;code&gt;&quot;, r);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (n = 0; n &lt; APR_SHA1_DIGESTSIZE/4; n++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf(r, &quot;%08x&quot;, digest.num[n]);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rputs(&quot;&lt;/code&gt;&quot;, r);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Print a link to the MD5 version */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rputs(&quot;&lt;br/&gt;&lt;a href='?digest=md5'&gt;View the MD5 hash instead&lt;/a&gt;&quot;, r);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster apr_file_close(file);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Let the server know that we responded to this request. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return OK;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterThis version in its entirety can be found here:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<a href="http://people.apache.org/~humbedooh/mods/examples/mod_example_2.c">mod_example_2.c</a>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="configuration"><title>Adding configuration options</title>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterIn this next segment of this document, we will turn our eyes away from the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterdigest module and create a new example module, whose only function is to
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottwrite out its own configuration. The purpose of this is to examine how
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellthe server works with configuration, and what happens when you start writing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosteradvanced configurations
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterfor your modules.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="config_intro"><title>An introduction to configuration
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterdirectives</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony BamfordIf you are reading this, then you probably already know
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterwhat a configuration directive is. Simply put, a directive is a way of
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertelling an individual module (or a set of modules) how to behave, such as
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterthese directives control how <code>mod_rewrite</code> works:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="config">
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterRewriteEngine On
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterRewriteCond %{REQUEST_URI} ^/foo/bar
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterRewriteRule ^/foo/bar/(.*)$ /foobar?page=$1
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterEach of these configuration directives are handled by a separate function,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterthat parses the parameters given and sets up a configuration accordingly.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</p>
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="config_simple"><title>Making an example configuration</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>To begin with, we'll create a basic configuration in C-space:</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertypedef struct {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int enabled; /* Enable or disable our module */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster const char *path; /* Some path to...something */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott int typeOfAction; /* 1 means action A, 2 means action B and so on */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott} example_config;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterNow, let's put this into perspective by creating a very small module that
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamfordjust prints out a hard-coded configuration. You'll notice that we use the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<code>register_hooks</code> function for initializing the configuration
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostervalues to their defaults:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<!-- BEGIN EXAMPLE CODE -->
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertypedef struct {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int enabled; /* Enable or disable our module */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster const char *path; /* Some path to...something */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int typeOfAction; /* 1 means action A, 2 means action B and so on */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster} example_config;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottstatic example_config config;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int example_handler(request_rec *r)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!r-&gt;handler || strcmp(r-&gt;handler, &quot;example-handler&quot;)) return(DECLINED);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_set_content_type(r, &quot;text/plain&quot;);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf(r, &quot;Enabled: %u\n&quot;, config.enabled);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf(r, &quot;Path: %s\n&quot;, config.path);
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford ap_rprintf(r, &quot;TypeOfAction: %x\n&quot;, config.typeOfAction);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return OK;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic void register_hooks(apr_pool_t *pool)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster config.enabled = 1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster config.path = &quot;/foo/bar&quot;;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster config.typeOfAction = 0x00;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
6b0b9411405932b5ada376bb06d6bc3d94980d7fPeter Major}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* Define our module as an entity and assign a function for registering hooks */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermodule AP_MODULE_DECLARE_DATA example_module =
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster STANDARD20_MODULE_STUFF,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster NULL, /* Per-directory configuration handler */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster NULL, /* Merge handler for per-directory configurations */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster NULL, /* Per-server configuration handler */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster NULL, /* Merge handler for per-server configurations */
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford NULL, /* Any directives we may have for httpd */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster register_hooks /* Our hook registering function */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster};
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert WapshottSo far so good. To access our new handler, we could add the following to
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshottour configuration:
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="config">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster&lt;Location /example&gt;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SetHandler example-handler
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster&lt;/Location&gt;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterWhen we visit, we'll see our current configuration being spit out by our
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermodule.
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="register_directive"><title>Registering directives with the server</title>
f79113ae65937c28690ec71f68f54f862b758baePhill Cunnington<p>
f79113ae65937c28690ec71f68f54f862b758baePhill CunningtonWhat if we want to change our configuration, not by hard-coding new values
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterinto the module, but by using either the httpd.conf file or possibly a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster.htaccess file? It's time to let the server know that we want this to be
f79113ae65937c28690ec71f68f54f862b758baePhill Cunningtonpossible. To do so, we must first change our <em>name tag</em> to include a
f79113ae65937c28690ec71f68f54f862b758baePhill Cunningtonreference to the configuration directives we want to register with the server:
f79113ae65937c28690ec71f68f54f862b758baePhill Cunnington</p>
f79113ae65937c28690ec71f68f54f862b758baePhill Cunnington
f79113ae65937c28690ec71f68f54f862b758baePhill Cunnington<!-- BEGIN EXAMPLE CODE -->
f79113ae65937c28690ec71f68f54f862b758baePhill Cunnington<highlight language="c">
f79113ae65937c28690ec71f68f54f862b758baePhill Cunningtonmodule AP_MODULE_DECLARE_DATA example_module =
f79113ae65937c28690ec71f68f54f862b758baePhill Cunnington{
f79113ae65937c28690ec71f68f54f862b758baePhill Cunnington STANDARD20_MODULE_STUFF,
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott NULL, /* Per-directory configuration handler */
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell NULL, /* Merge handler for per-directory configurations */
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell NULL, /* Per-server configuration handler */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott NULL, /* Merge handler for per-server configurations */
f79113ae65937c28690ec71f68f54f862b758baePhill Cunnington example_directives, /* Any directives we may have for httpd */
f79113ae65937c28690ec71f68f54f862b758baePhill Cunnington register_hooks /* Our hook registering function */
f79113ae65937c28690ec71f68f54f862b758baePhill Cunnington};
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</highlight>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<p>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellThis will tell the server that we are now accepting directives from the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterconfiguration files, and that the structure called <code>example_directives
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</code> holds information on what our directives are and how they work.
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterSince we have three different variables in our module configuration, we
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterwill add a structure with three directives and a NULL at the end:
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell</p>
bcb85423bc6855cb1c7accc69fa051e1771c000aMark de Reeper
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottstatic const command_rec example_directives[] =
d28c31c7d0cf9ac19eaf07942956e707222fb5ebPeter Major{
9709ff1b979ab7830f3e00b809f1157554566ed3Steve Ferris AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster AP_INIT_TAKE1("examplePath", example_set_path, NULL, RSRC_CONF, "The path to whatever"),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster AP_INIT_TAKE2("exampleAction", example_set_action, NULL, RSRC_CONF, "Special action value!"),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { NULL }
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell};
bcb85423bc6855cb1c7accc69fa051e1771c000aMark de Reeper</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<img src="/images/build_a_mod_4.png" alt="Directives structure"/><br />
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellAs you can see, each directive needs at least 5 parameters set:
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell</p>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<ol>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<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.
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellIf 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
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellfor more macros).</li>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<li><code>exampleEnabled</code>: This is the name of our directive. More precisely, it is what the user must put in his/her
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellconfiguration in order to invoke a configuration change in our module.</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>example_set_enabled</code>: This is a reference to a C function that parses the directive and sets the configuration
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosteraccordingly. We will discuss how to make this in the following paragraph.</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>RSRC_CONF</code>: This tells the server where the directive is permitted. We'll go into details on this value in the
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamfordlater chapters, but for now, <code>RSRC_CONF</code> means that the server will only accept these directives in a server context.</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>"Enable or disable...."</code>: This is simply a brief description of what the directive does.</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</ol>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster(<em>The "missing" parameter in our definition, which is usually set to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<code>NULL</code>, is an optional function that can be run after the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterinitial function to parse the arguments have been run. This is usually
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosteromitted, as the function for verifying arguments might as well be used to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterset them.</em>)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="directive_handler"><title>The directive handler function</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterNow that we have told the server to expect some directives for our module, it's
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertime to make a few functions for handling these. What the server reads in the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterconfiguration file(s) is text, and so naturally, what it passes along to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterour directive handler is one or more strings, that we ourselves need to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterrecognize and act upon. You'll notice, that since we set our <code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterexampleAction</code> directive to accept two arguments, its C function also
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterhas an additional parameter defined:</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* Handler for the "exambleEnabled" directive */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterconst char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(!strcasecmp(arg, "on")) config.enabled = 1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else config.enabled = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford/* Handler for the "examplePath" directive */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottconst char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster config.path = arg;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford/* Handler for the "exampleAction" directive */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* Let's pretend this one takes one argument (file or db), and a second (deny or allow), */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* and we store it in a bit-wise manner. */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottconst char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char* arg2)
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(!strcasecmp(arg1, "file")) config.typeOfAction = 0x01;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else config.typeOfAction = 0x02;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(!strcasecmp(arg2, "deny")) config.typeOfAction += 0x10;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else config.typeOfAction += 0x20;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return NULL;
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
56ed5bbb263838f338eb8afc978091c01a4f2a2bjeff.schenk<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="directive_complete"><title>Putting it all together</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterNow that we have our directives set up, and handlers configured for them,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterwe can assemble our module into one big file:
6f6d45938671719a3c22abd091398ec1cfcf7788Peter Major</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
6f6d45938671719a3c22abd091398ec1cfcf7788Peter Major<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* mod_example_config_simple.c: */
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford#include &lt;stdio.h&gt;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "apr_hash.h"
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford#include "ap_config.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "ap_provider.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "httpd.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "http_core.h"
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford#include "http_config.h"
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott#include "http_log.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "http_protocol.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "http_request.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ==============================================================================
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Our configuration prototype and declaration:
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford ==============================================================================
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshotttypedef struct {
6f6d45938671719a3c22abd091398ec1cfcf7788Peter Major int enabled; /* Enable or disable our module */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster const char *path; /* Some path to...something */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int typeOfAction; /* 1 means action A, 2 means action B and so on */
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott} example_config;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamfordstatic example_config config;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ==============================================================================
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Our directive handlers:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ==============================================================================
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* Handler for the &quot;exambleEnabled&quot; directive */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterconst char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(!strcasecmp(arg, &quot;on&quot;)) config.enabled = 1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else config.enabled = 0;
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford return NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* Handler for the &quot;examplePath&quot; directive */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottconst char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg)
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster config.path = arg;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* Handler for the &quot;exampleAction&quot; directive */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* Let's pretend this one takes one argument (file or db), and a second (deny or allow), */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* and we store it in a bit-wise manner. */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterconst char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char* arg2)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(!strcasecmp(arg1, &quot;file&quot;)) config.typeOfAction = 0x01;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else config.typeOfAction = 0x02;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford if(!strcasecmp(arg2, &quot;deny&quot;)) config.typeOfAction += 0x10;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott else config.typeOfAction += 0x20;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ==============================================================================
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford The directive structure for our name tag:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ==============================================================================
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic const command_rec example_directives[] =
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster AP_INIT_TAKE1(&quot;exampleEnabled&quot;, example_set_enabled, NULL, RSRC_CONF, &quot;Enable or disable mod_example&quot;),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster AP_INIT_TAKE1(&quot;examplePath&quot;, example_set_path, NULL, RSRC_CONF, &quot;The path to whatever&quot;),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster AP_INIT_TAKE2(&quot;exampleAction&quot;, example_set_action, NULL, RSRC_CONF, &quot;Special action value!&quot;),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster { NULL }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster};
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ==============================================================================
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Our module handler:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ==============================================================================
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int example_handler(request_rec *r)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(!r-&gt;handler || strcmp(r-&gt;handler, &quot;example-handler&quot;)) return(DECLINED);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_set_content_type(r, &quot;text/plain&quot;);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf(r, &quot;Enabled: %u\n&quot;, config.enabled);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf(r, &quot;Path: %s\n&quot;, config.path);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf(r, &quot;TypeOfAction: %x\n&quot;, config.typeOfAction);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return OK;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ==============================================================================
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster The hook registration function (also initializes the default config values):
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ==============================================================================
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic void register_hooks(apr_pool_t *pool)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster config.enabled = 1;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott config.path = &quot;/foo/bar&quot;;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster config.typeOfAction = 3;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ==============================================================================
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Our module name tag:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ==============================================================================
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermodule AP_MODULE_DECLARE_DATA example_module =
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster STANDARD20_MODULE_STUFF,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster NULL, /* Per-directory configuration handler */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster NULL, /* Merge handler for per-directory configurations */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster NULL, /* Per-server configuration handler */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster NULL, /* Merge handler for per-server configurations */
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott example_directives, /* Any directives we may have for httpd */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott register_hooks /* Our hook registering function */
efad633539be6ecb378fafe208b80b81739e28d1Neil Madden};
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnellIn our httpd.conf file, we can now change the hard-coded configuration by
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnelladding a few lines:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="config">
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterExampleEnabled On
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterExamplePath "/usr/bin/foo"
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterExampleAction file allow
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterAnd thus we apply the configuration, visit <code>/example</code> on our
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterweb site, and we see the configuration has adapted to what we wrote in our
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottconfiguration file.
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott</section>
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott<section id="context"><title>Context aware configurations</title>
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott<section id="context_intro"><title>Introduction to context aware configurations</title>
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott<p>
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert WapshottIn Apache HTTP Server 2.4, different URLs, virtual hosts, directories etc can have very
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshottdifferent meanings to the user of the server, and thus different contexts
fd21d481e26774c37a197c7cc8ab56096a21e7aaPhill Cunningtonwithin which modules must operate. For example, let's assume you have this
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshottconfiguration set up for mod_rewrite:
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="config">
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott&lt;Directory &quot;/var/www&quot;&gt;
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott RewriteCond %{HTTP_HOST} ^example.com$
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster RewriteRule (.*) http://www.example.com/$1
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott&lt;/Directory&gt;
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott&lt;Directory &quot;/var/www/sub&quot;&gt;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster RewriteRule ^foobar$ index.php?foobar=true
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott&lt;/Directory&gt;
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert WapshottIn this example, you will have set up two different contexts for
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshottmod_rewrite:</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<ol>
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell<li>Inside <code>/var/www</code>, all requests for <code>http://example.com</code> must go to <code>http://www.example.com</code></li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li>Inside <code>/var/www/sub</code>, all requests for <code>foobar</code> must go to <code>index.php?foobar=true</code></li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</ol>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterIf mod_rewrite (or the entire server for that matter) wasn't context aware, then
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterthese rewrite rules would just apply to every and any request made,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterregardless of where and how they were made, but since the module can pull
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterthe context specific configuration straight from the server, it does not need
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterto know itself, which of the directives are valid in this context, since
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterthe server takes care of this.</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterSo how does a module get the specific configuration for the server,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterdirectory or location in question? It does so by making one simple call:
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterexample_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);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterThat's it! Of course, a whole lot goes on behind the scenes, which we will
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshottdiscuss in this chapter, starting with how the server came to know what our
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshottconfiguration looks like, and how it came to be set up as it is in the
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshottspecific context.
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott</p>
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott</section>
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott<section id="context_base"><title>Our basic configuration setup</title>
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott<p>In this chapter, we will be working with a slightly modified version of
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshottour previous context structure. We will set a <code>context</code>
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshottvariable that we can use to track which context configuration is being
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshottused by the server in various places:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertypedef struct {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char context[256];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char path[256];
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott int typeOfAction;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int enabled;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster} example_config;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>Our handler for requests will also be modified, yet still very simple:</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int example_handler(request_rec *r)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(!r->handler || strcmp(r->handler, "example-handler")) return(DECLINED);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster example_config *config = (example_config*) ap_get_module_config(r->per_dir_config, &amp;example_module);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_set_content_type(r, "text/plain");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf("Enabled: %u\n", config->enabled);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf("Path: %s\n", config->path);
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott ap_rprintf("TypeOfAction: %x\n", config->typeOfAction);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ap_rprintf("Context: %s\n", config->context);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return OK;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="context_which"><title>Choosing a context</title>
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden<p>
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil MaddenBefore we can start making our module context aware, we must first define,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterwhich contexts we will accept. As we saw in the previous chapter, defining
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostera directive required five elements be set:</p>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterAP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>The <code>RSRC_CONF</code> definition told the server that we would only allow
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterthis directive in a global server context, but since we are now trying out
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostera context aware version of our module, we should set this to something
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermore lenient, namely the value <code>ACCESS_CONF</code>, which lets us use
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterthe directive inside &lt;Directory&gt; and &lt;Location&gt; blocks. For more
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostercontrol over the placement of your directives, you can combine the following
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterrestrictions together to form a specific rule:
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>RSRC_CONF</code>: Allow in .conf files (not .htaccess) outside &lt;Directory&gt; or &lt;Location&gt;</li>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<li><code>ACCESS_CONF</code>: Allow in .conf files (not .htaccess) inside &lt;Directory&gt; or &lt;Location&gt;</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>OR_OPTIONS</code>: Allow in .conf files and .htaccess when <code>AllowOverride Options</code> is set</li>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<li><code>OR_FILEINFO</code>: Allow in .conf files and .htaccess when <code>AllowOverride FileInfo</code> is set</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>OR_AUTHCFG</code>: Allow in .conf files and .htaccess when <code>AllowOverride AuthConfig</code> is set</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><code>OR_INDEXES</code>: Allow in .conf files and .htaccess when <code>AllowOverride Indexes</code> is set</li>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford<li><code>OR_ALL</code>: Allow anywhere in .conf files and .htaccess</li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</ul>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="context_pool"><title>Using the server to allocate configuration slots</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p> A much smarter way to manage your configurations is by letting the server
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterhelp you create them. To do so, we must first start off by changing our
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<em>name tag</em> to let the server know, that it should assist us in creating
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamfordand managing our configurations. Since we have chosen the per-directory
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster(or per-location) context for our module configurations, we'll add a
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshottper-directory creator and merger function reference in our tag:</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostermodule AP_MODULE_DECLARE_DATA example_module =
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster STANDARD20_MODULE_STUFF,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster create_dir_conf, /* Per-directory configuration handler */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster merge_dir_conf, /* Merge handler for per-directory configurations */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster NULL, /* Per-server configuration handler */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster NULL, /* Merge handler for per-server configurations */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster directives, /* Any directives we may have for httpd */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster register_hooks /* Our hook registering function */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster};
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="context_new"><title>Creating new context configurations</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterNow that we have told the server to help us create and manage configurations,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterour first step is to make a function for creating new, blank
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterconfigurations. We do so by creating the function we just referenced in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterour name tag as the Per-directory configuration handler:</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostervoid* example_create_dir_conf(apr_pool_t* pool, char* context) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster context = context ? context : "(undefined context)";
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell example_config *cfg = apr_pcalloc(pool, sizeof(example_config));
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott if(cfg) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Set some default values */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster strcpy(cfg->context, x);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cfg->enabled = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cfg->path = "/foo/bar";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cfg->typeOfAction = 0x11;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return cfg;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
72450cb9c2ca854c6d3479832c2738196c1d3282Robert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="context_merge"><title>Merging configurations</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterOur next step in creating a context aware configuration is merging
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterconfigurations. This part of the process particularly applies to scenarios
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterwhere you have a parent configuration and a child, such as the following:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="config">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster&lt;Directory &quot;/var/www&quot;&gt;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ExampleEnable On
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ExamplePath /foo/bar
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ExampleAction file allow
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster&lt;/Directory&gt;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott&lt;Directory &quot;/var/www/subdir&quot;&gt;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ExampleAction file deny
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster&lt;/Directory&gt;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterIn this example, it is natural to assume that the directory <code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/var/www/subdir</code> should inherit the values set for the <code>/var/www
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</code> directory, as we did not specify an <code>ExampleEnable</code> nor
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosteran <code>ExamplePath</code> for this directory. The server does not presume to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterknow if this is true, but cleverly does the following:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<ol>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li>Creates a new configuration for <code>/var/www</code></li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li>Sets the configuration values according to the directives given for <code>/var/www</code></li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li>Creates a new configuration for <code>/var/www/subdir</code></li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li>Sets the configuration values according to the directives given for <code>/var/www/subdir</code></li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<li><strong>Proposes a merge</strong> of the two configurations into a new configuration for <code>/var/www/subdir</code></li>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</ol>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterThis proposal is handled by the <code>merge_dir_conf</code> function we
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterreferenced in our name tag. The purpose of this function is to assess the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertwo configurations and decide how they are to be merged:</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- BEGIN EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="c">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostervoid* merge_dir_conf(apr_pool_t* pool, void* BASE, void* ADD) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster example_config* base = (example_config *) BASE ; /* This is what was set in the parent context */
cc7c18212481f5e9ee508afe2ffcaecb6b9330f5Craig McDonnell example_config* add = (example_config *) ADD ; /* This is what is set in the new context */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster example_config* conf = (example_config *) create_dir_conf(pool, "Merged configuration"); /* This will be the merged configuration */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* Merge configurations */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster conf->enabled = ( add->enabled == 0 ) ? base->enabled : add->enabled ;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster conf->typeOfAction = add->typeOfAction ? add->typeOfAction : base->typeOfAction;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster strcpy(conf->path, strlen(add->path) ? add->path : base->path);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return conf ;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<!-- END EXAMPLE CODE -->
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</section>
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<section id="context_example"><title>Trying out our new context aware configurations</title>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterNow, let's try putting it all together to create a new module that is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostercontext aware. First off, we'll create a configuration that lets us test
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterhow the module works:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<highlight language="config">
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster&lt;Location &quot;/a&quot;&gt;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott SetHandler example-handler
0c893a059f84246bf91e2f0fbf63e4c92f8e5165Tony Bamford ExampleEnabled on
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ExamplePath &quot;/foo/bar&quot;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ExampleAction file allow
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster&lt;/Location&gt;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster&lt;Location &quot;/a/b&quot;&gt;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ExampleAction file deny
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ExampleEnabled off
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster&lt;/Location&gt;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster&lt;Location &quot;/a/b/c&quot;&gt;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott ExampleAction db deny
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ExamplePath &quot;/foo/bar/baz&quot;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ExampleEnabled on
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster&lt;/Location&gt;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster</highlight>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster<p>
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterThen we'll assemble our module code. Note, that since we are now using our
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostername tag as reference when fetching configurations in our handler, I have
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Maddenadded some prototypes to keep the compiler happy:
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden</p>
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden<!-- BEGIN EXAMPLE CODE -->
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden<highlight language="c">
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden/*$6
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden * mod_example_config.c
87d68743726585ee101ba2e7be2cf06cd34ebb80Neil Madden +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
#include &lt;stdio.h&gt;
#include "apr_hash.h"
#include "ap_config.h"
#include "ap_provider.h"
#include "httpd.h"
#include "http_core.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "http_request.h"
/*$1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Configuration structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
typedef struct
{
char context[256];
char path[256];
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;exambleEnabled&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)) {
i++;
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;
}
return kvp;
}
static int example_handler(request_rec *r)
{
/*~~~~~~~~~~~~~~~~~~~~~~*/
keyValuePair* formData;
/*~~~~~~~~~~~~~~~~~~~~~~*/
formData = readPost(r);
if (formData) {
int i;
for (i = 0; formData[i]; i++) {
ap_rprintf(r, &quot;%s = %s\n&quot;, formData[i]->key, formData[i]->value);
}
}
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;&lt;b&gt;%s&lt;/b&gt;: %s&lt;br/&gt;&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;data, &amp;size) == OK) {
ap_rprintf(r, &quot;We read a request body that was %u bytes long&quot;, size);
}
return OK;
}
</highlight>
<!-- END EXAMPLE CODE -->
</section>
</section>
</manualpage>