Related books

Document Index




Introduction

There appears to be a lack of documentation written for new developers regarding creation of Apache http modules. The documentation that I have found so far assumes the a new developer will automatically know how to perform certain tasks such as compiling their modules into the httpd binary or compiling their modules as DSO modules. I didn't know these procedures, and I assume that there are other people out there who could also use a quick ramp up into this fascinating world. This page and the associated module source will hopefully give you a jump start.

Document Index


Document Status

For the moment, please accept this document as a work in progress. I'm only a beginning C programmer, as I'm teaching myself in the evenings. I'm also just getting started with Apache modules. So please bear with me for any grody code and bad examples. I'm putting this together because I couldn't find anything to get myself started. More importantly than bearing with me, please jump in and correct / advise me if I get something wrong here. Also, answers to sections where I've stated I couldn't work out how to achieve something would be much appreciated and will be added to the document.

Document Index


What we do and don't cover

I'm not going to cover modules for the 1.3.x versions of the Apache httpd server, as there is already an excellent book out there that does this. The book you want is named Writing Apache Modules with Perl and C: Customizing Your Web ServerWriting Apache modules with Perl and C and the ISBN is 156592567X For the purposes of this text, we will be working with a very simple module that prints Hello World in a browser window when set as the handler for a location. All examples will assume that we are discussing this module.

Document Index


Build choices

Before we get into creating a module, we'll cover what to do with the module once you've written it. Firstly, you need to compile your module. You can either compile your module into the httpd binary or as a DSO module. The DSO route is preferable especially during the development phase, because you don't want to have to compile and install a new binary every time you want to test your module. If you want to read more about DSO modules, then look here. As I still haven't worked out how to add a module to the source tree. I will only cover building your module as a DSO here. Under Apache 1.3.x, you would add a command like

--activate-module=src/modules/work/mod_hello.c 
This no longer appears to work in 2.0.x To build a DSO module without going through the rig-morale of rebuilding the httpd binary, you can use the APache eXtenSion tool. If you already have Apache httpd installed on your machine, man apxs should give you loads of information about the use of this command. For our simple hello world module, the following apxs command should work fine:
apxs -c -i -a mod_hello.c 

The apxs command should be run from the directory that contains the source for the hello world module. If all goes well, it should install the module into your modules directory.

Document Index


The module

Well, if you're still with me at this point (i.e. you haven't been bored to tears), then we'll get to the meaty bit. A sample module. The module that we will be developing and testing here is a simple module that merely implements a content handler. This is a handler that generates or modifies content by my understanding. If modifying content is your primary objective, then I advise you to look at filters as well. I found 2 articles by Ryan Bloom at http://www.onlamp.com/pub/a/apache/2001/08/23/apache_2.html and http://www.onlamp.com/pub/a/apache/2001/09/13/apache_2.html

These will probably be a good place to start if you're looking at writing a filter as opposed to a general purpose module.

Our source is stored in a file named mod_hello.c which you may have gathered from the apxs command earlier. The reason for this is that the source file name is one resource that apxs can use to work out the module name. The source is as follows with comments interspersed.

/* The following module borrows from mod_example.c but 
* is much simplified. Please see http://www.apache.org/LICENSE.txt 
* for the licence that mod_example.c and this module are licenced 
* under. All commentary on the module is included as 
* standard C style comments below */ 

/* All of these include files can be found in the Apache http source 
* tree in include/ . If you've got the Apache http server already 
* installed, then there will be an include directory either under the 
* directory that was specified with --prefix or somewhere in your 
* standard 
* include paths. All the functions that you can make use of can be 
* found 
* in the include files. */ 

#include "httpd.h" 
#include "http_config.h" 
#include "http_core.h" 
#include "http_log.h" 
#include "http_main.h" 
#include "http_protocol.h" 
#include "http_request.h" 
#include "util_script.h" 
#include "http_connection.h" 

/* This example just takes a pointer to the request record as its only 
* argument */ 
static int hello_handler(request_rec *r) 
{ 

        /* We decline to handle a request if hello-handler is not the value 
         * of r->handler */ 
        if (strcmp(r->handler, "hello-handler")) { 
                return DECLINED; 
        } 

        /* The following line just prints a message to the errorlog */ 
        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, r->server, 
        "mod_hello: %s", "Before content is output"); 

        /* We set the content type before doing anything else */ 
        ap_set_content_type(r, "text/html"); 

        /* If the request is for a header only, and not a request for 
         * the whole content, then return OK now. We don't have to do 
         * anything else. */ 
        if (r->header_only) { 
                return OK; 
        } 

        /* Now we just print the contents of the document using the 
         * ap_rputs and ap_rprintf functions. More information about 
         * the use of these can be found in http_protocol.h */ 
        ap_rputs("<HTML>\n", r);
	ap_rputs("\t<HEAD>\n", r);
	ap_rputs("\t\t<TITLE>\n\t\t\tHello There\n\t\t</TITLE>\n", r);
	ap_rputs("\t</HEAD>\n\n", r);
	ap_rputs("<BODY BGCOLOR=\"#FFFFFF\>"\n" ,r);
	ap_rputs("<H1>Hello </H1>\n", r);
	ap_rputs("Hello world\n", r);
	ap_rprintf(r, "<br>A sample line generated by ap_rprintf<br>\n");
	ap_rputs("</BODY></HTML>\n" ,r); 

        /* We can either return OK or DECLINED at this point. If we return 
        * OK, then no other modules will attempt to process this request */ 
        return OK; 
} 


/* Each function our module provides to handle a particular hook is 
* specified here. See mod_example.c for more information about this 
* step. Suffice to say that we need to list all of our handlers in 
* here. */ 
static void x_register_hooks(apr_pool_t *p) 
{ 
        ap_hook_handler(hello_handler, NULL, NULL, APR_HOOK_MIDDLE); 
} 


/* Module definition for configuration. We list all callback routines 
* that we provide the static hooks into our module from the other parts 
* of the server. This list tells the server what function will handle a 
* particular type or stage of request. If we don't provide a function 
* to handle a particular stage / callback, use NULL as a placeholder as 
* illustrated below. */ 
module AP_MODULE_DECLARE_DATA hello_module = 
{ 
        STANDARD20_MODULE_STUFF, 
        NULL, /* per-directory config creator */ 
        NULL, /* directory config merger */ 
        NULL, /* server config creator */ 
        NULL, /* server config merger */ 
        NULL, /* command table */ 
        x_register_hooks, /* other request processing hooks */ 
}; 
Document Index


So I wrote a module - Now what ?

I guess after all of this effort, you'd like to see the results of your module. To receive your quota of gratification, you'll need to edit your Apache config (normally http.conf) and restart your webserver.

This module merely prints Hello World to your browser when you make a request that this handler handles.

If your apxs command that we showed earlier for building the module worked as advertised, you should find a line similar to the following in your httpd.conf

LoadModule hello_module modules/mod_hello.so 

modules/ may be libexec/ on many systems. This is the line that tells the server to load this module into memory at startup. This way the http server can provide functionality as and when required without bloating the main codebase.

Now you need to tell a location to use this handler. A simple way to do this is to add the following to your httpd.conf:

Once you've done this, test your server config by running httpd -t and then restart the server. Now point your browser at and you should get a page saying Hello World. If you don't either you did something wrong following these instructions, or (more likely) I did something wrong writing these instructions. If you do run into problems at this stage, please let me know so that I can update this document.

Document Index


Concussion

This would have been a conclusion, but by the time I had got my head around all of this stuff, I felt a bit concussed. I hope that the above text proves useful to someone out there. It pretty much covers the things that I was not able to understand when I started this.

If you have any questions or suggestions for improvements, then please feel free to e-mail me by clicking this link and filling out the form that you are presented with.

Document Index