apache so module guide.

ITWeb/개발일반 2013. 3. 19. 15:14

[Reference URL]

http://www.penguinpowered.org/documentation/apache2_modules.html

http://threebit.net/tutorials/apache2_modules/tut1/tutorial1.html

http://threebit.net/tutorials/apache2_modules/tut2/tutorial2.html



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 athttp://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



This tutorial guides the reader through the minimal tasks involved in writing a module for Apache 2. The module developed here has almost no functionality - it's only impact is the generation of a static message to logs/errorlog for each HTTP request.

This tutorial is not intended to showcase Apache's module API. Instead, it guides the reader through the other tasks that must be done to properly develop, compile and install a custom module - namely autoconf and automake.

Further tutorials will build from this one and explore the advanced module API. Drop a message to kevino at threebit.net if you feel the need.

# Throughout the tutorial, look for links to Apache's
# LXR website http://lxr.webperf.org/
# For example, clink on AP_MODULE_DECLARE_DATA below.
module AP_MODULE_DECLARE_DATA tut2_module;

Preparation

If you don't actually want to run or test the code in this tutorial, then feel free to skip this step. Otherwise, you'll want to perform the following actions so your work area prepared for compiling and running the tutorial.

I have assumed in this tutorial that you have an account on a Linux (or Unix) machine and you have installed the GNU build tools (autoconf, automake, etc). If you haven't then you're not going to get very far - consult your OS documentation.

# Prepare the temporary directory
cd $HOME
mkdir threebit-tutorials
cd threebit-tutorials

# Remember the tutorial home directory for later.
export TUTORIAL_HOME=`pwd`
Download via HTTP
cd $TUTORIAL_HOME
wget "http://threebit.net/tutorials/tutorials.tar.gz"
tar zxvf tutorials.tar.gz
Download via Anonymous CVS
cd $TUTORIAL_HOME
CVSROOT=:pserver:anonymous@threebit.net:/usr/local/cvs

# use "anonymous" as the password.
cvs login

cvs co tutorials/apache2_modules
mv tutorials/* .
rm -rf tutorials
Apache Note: You will get a "404 - Not Found" error if 2.0.43 is no longer the newest version of Apache. Just substitute the current version tag if that is the case.
cd $TUTORIAL_HOME

wget http://www.apache.org/dist/httpd/httpd-2.0.43.tar.gz
tar zxf httpd-2.0.43.tar.gz

cd httpd-2.0.43
./configure --prefix=$TUTORIAL_HOME/apache2 --enable-so
make
make install
Now we will fix the ServerName and Listen configuration directives so that we can run this installation as an unpriviledged user.
# store the location of the apache configuration file.
HTTPCONF=$TUTORIAL_HOME/apache2/conf/httpd.conf

# replace the ServerName directive
cat $HTTPCONF | \
  sed 's/#ServerName new.host.name:80/ServerName localhost/' \
  > $HTTPCONF.new
mv $HTTPCONF.new $HTTPCONF

# replace the Listen directive.
cat $HTTPCONF | sed 's/^Listen 80/Listen 21000/' > $HTTPCONF.new
mv $HTTPCONF.new $HTTPCONF
And test the configuration:
$TUTORIAL_HOME/apache2/bin/apachectl configtest
Syntax OK

mod_tut1.c

As stated above, the purpose of this module is to write data to the error log for each HTTP request. We are obviously building a useless module - but by limiting what the module does it becomes easier to explain what everything is doing.

The source code to the module is pretty much self documenting but let us examine each block independently.

/*
 * Include the core server components.
 */
#include "httpd.h"
#include "http_config.h"
Obviously an Apache module will require information about structures, macros and functions from Apache's core. These two header files are all that is required for this module, but real modules will need to include other header files relating to request handling, logging, protocols, etc.
/*
 * Declare and populate the module's data structure.  The
 * name of this structure ('tut1_module') is important - it
 * must match the name of the module.  This structure is the
 * only "glue" between the httpd core and the module.
 */
module AP_MODULE_DECLARE_DATA tut1_module =
{
  // Only one callback function is provided.  Real
  // modules will need to declare callback functions for
  // server/directory configuration, configuration merging
  // and other tasks.
  STANDARD20_MODULE_STUFF,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  mod_tut1_register_hooks,      /* callback for registering hooks */
};
Every module must declare it's data structure as shown above. Since this module does not require any configuration most of the callback locations have been left blank, except for the last one - that one is invoked by the HTTPD core so that the module can declare other functions that should be invoked to handle various events (like an HTTP request).
/*
 * This function is a callback and it declares what
 * other functions should be called for request
 * processing and configuration requests. This
 * callback function declares the Handlers for
 * other events.
 */
static void mod_tut1_register_hooks (apr_pool_t *p)
{
  // I think this is the call to make to register a
  // handler for method calls (GET PUT et. al.).
  // We will ask to be last so that the comment
  // has a higher tendency to go at the end.
  ap_hook_handler(mod_tut1_method_handler, NULL, NULL, APR_HOOK_LAST);
}
When this function is called by the HTTPD core, it registers a handler that should be invoked for all HTTP requests.
/*
 * This function is registered as a handler for HTTP methods and will
 * therefore be invoked for all GET requests (and others).  Regardless
 * of the request type, this function simply sends a message to
 * STDERR (which httpd redirects to logs/error_log).  A real module
 * would do *alot* more at this point.
 */
static int mod_tut1_method_handler (request_rec *r)
{
  // Send a message to stderr (apache redirects this to the error log)
  fprintf(stderr,"apache2_mod_tut1: A request was made.\n");

  // We need to flush the stream for messages to appear right away.
  // Performing an fflush() in a production system is not good for
  // performance - don't do this for real.
  fflush(stderr);

  // Return DECLINED so that the Apache core will keep looking for
  // other modules to handle this request.  This effectively makes
  // this module completely transparent.
  return DECLINED;
}
This is the function that will be invoked for every HTTP request. This is where the meat of an Apache module should go.

GNU Build Tools

Looking in TODO $TUTORIAL_HOME/tut1, you will find some familiar files that are included with most GNU applications.

Makefile.amAn input file for automake
configure.inAn inputfile to autoconf.
mod_tut1.cThe source code to the tutorial module.
tutorial1.htmlThis file.
The remaining files can safely be ignored.
AUTHORSautomake will produce warnings if this file is not present.
COPYINGThe GPL license. automake will complain if this file is not present.
CVS/CVS state directory. Ignore it. If you downloaded the tutorial using the tar ball then it won't even exist.
ChangeLogAnother automake file.
INSTALLStandard install instructions. In this case, it points the reader to this file.
NEWSAnother automake file.
READMEAnother automake file.

This tutorial does not aim to be a complete reference for the GNU build tools. See the following references for information.

Aside from the module source code itself, the only files of interest to the reader are configure.in and Makefile.am. To briefly discuss these files without duplicating documetation contained in the above references:

configure.in is an input file to autoconf and is used to configure the module source code and dependencies for each target platform. Running autoconf creates the configure script we are all so familiar with.

Makefile.am is an input file to automake and is used to create a Makefile.in file. The Makefile.in file is then used by configure to create real Makefile's.

If you're confused - have no fear because I still am! You probably don't need to understand everything - just plug away through the tutorial. If you want to understand what's going on, I suggest you read the references cited above.

configure.in

I would be lying to you if I told you that I understand everything in this file. However, it seems to work so I'll tell you what I know. :) See configure.in for raw file.
AC_INIT
The mandatory autoconf initialization macro.
# Automake initialization
AM_INIT_AUTOMAKE(mod_tut1, 1.0)
This macro is provided by automake and is required when automake is used. The arguments are the package name and version number. I have provided reasonable values for the parameters but still haven't figured out what their impact is.
AC_PROG_CC
AM_PROG_LIBTOOL
These two macros add checks for suitable cc and libtool programs.
AC_DEFUN([APACHE_DIR],[

  AC_ARG_WITH(
    apache,
    [  --with-apache[=DIR]     Apache server directory],
    ,
    [with_apache="no"]
  )

  AC_MSG_CHECKING(for Apache directory)

  if test "$with_apache" = "no"; then
    AC_MSG_ERROR( Specify the apache using --with-apache)
  else
    # make sure that a well known include file exists
    if test -e $with_apache/include/httpd.h; then
      apache_dir=$with_apache
      AC_MSG_RESULT(APACHE found!)
    else
      AC_MSG_ERROR( $with_apache not found. )
    fi
  fi

])
This declares a new autoconf macro named APACHE_DIR. It is used to handle the --with-apache=/usr/local/apache2 argument to configure.
APACHE_DIR
This runs the APACHE_DIR macro that was just defined. When successfull, the directory location is stored in apache_dir.
AC_SUBST(apache_dir) 
Not all variables that are set in shell snippets are persisted to the configuration status file (config.status). This call to AC_SUBST persists the value of apache_dir.
AC_OUTPUT(Makefile)
Finally, AC_OUTPUT() saves the results of the configuration and causes a real Makefile to be generated.

Makefile.am

This file is used by automake to generate a Makefile.in file. As stated earlier, Makefile.in is then parsed using an invocation of configure to create an actual Makefile.

Since writing an Apache module is the same as writing, compiling and linking any standard shared library, automake is well suited to the task.

Again, consult the full automake documentation for all the info. See the raw Makefile.am.

lib_LTLIBRARIES = libmodtut1.la
This tells automake that we are creating a shared library named libmottut1.la.
libmodtut1_la_SOURCES = mod_tut1.c
This tells automake what source files should be compiled as part of the library. In this case there is only one, but there could be serveral.
INCLUDES = -I@apache_dir@/include
Header files from the apache distribution are required when compiling the module. This directive provides a list of include directories to pass on to gcc. Does apache_dir look familiar? If you said yes, then step to the front of the class - configure will subsitute the value that was passed in with --with-apache when the Makefile is written.

aclocal, autoconf, automake

Now that you have some idea of what those files mean we can run the utilities that use them.

aclocal is used to import macros defined by automake so that autoconf can understand what's going on.

cd $TUTORIAL_HOME/apache2_modules/tut1

# import automake m4 macros.
aclocal

# create configure based on configure.in
autoconf

# create Makefile.in based on Makefile.am and configure.in
automake -a

configure

Now we can run configure to prepare the module's Makefile.
# The ubiquitous configure script
./configure --with-apache=$TUTORIAL_HOME/apache2

make

And now we can run make to compile the module. Note: don't run make install. We'll handle the module installation later.
make

apxs

** DO NOT RUN make install ** Ordinarially you would, but the install step for an Apache module is different. Instead, apxs is used to register the module in httpd.conf and move the shared object into the apache lib directory.
$TUTORIAL_HOME/apache2/bin/apxs -i -a -n tut1 libmodtut1.la
apxs also addes the following line to httpd.conf:
LoadModule tut1_module        modules/libmodtut1.so

Run Apache

Now we are ready to run Apache and test the module.
# Change to the apache directory
cd $TUTORIAL_HOME/apache2

# Start Apache
bin/apachectl start

# Use Lynx to hit the web server.
lynx --source http://localhost:21000 | grep success

# Look for the module's message in the error log
cat logs/error_log | grep tut1
apache2_mod_tut1: A request was made.

Success!

The tutorial one module has been successfully compiled and installed into the Apache 2 runtime.

Updates

2003.06.03: Dmitry Muntean was kind enough to send in a question and resolution for a problem he was having.

Dmitry: ... on the aclocal step it said that "macro AM_PROG_LIBTOOL not found in library", After some looking around I've discovered that AM_PROG_LIBTOOL is changed to AC_PROG_LIBTOOL, so I did and aclocal went fine. Then when I launched autoconf it said to me:

configure.in:9: error: possibly undefined macro: AC_PROG_LIBTOOL
    If this token and others are legitimate, please use m4_pattern_allow.
    See the Autoconf documentation.
As far as I see possibly you used another version of these utilites. I use automake 1.7.2 and autoconf 2.57. What version have you used? Or if this isn't the problem can you point me what it is?

Kevin: automake (GNU automake) 1.4-p4

Dmitry:The problem was that libtool.m4 must be included at the end of aclocal.m4, and ltmain.sh must be in that directory. Both files were taken from latest libtool package(for now it is 1.2.5).


This tutorial guides the reader through the portions of the Apache API that are used by modules to control their configuration. For the moment, we will introduce the handling of a single server-wide configuration directive.

This module builds on Tutorial 1 by allowing the message that is written to the error log to be customized. Again, this is a trivial task, but I hope that is makes for a clear example of how to use the API to perform a task, without confusing the topic by doing something actually usefull (that's left to you! haa ha!).

# Throughout the tutorial, look for links to Apache's
# LXR website http://lxr.webperf.org/
# For example, clink on AP_MODULE_DECLARE_DATA below.
module AP_MODULE_DECLARE_DATA tut2_module;

Preparation

If you do not plan to compile and run the code presented here, you can skip this step. Otherwise, complete the preparation step from Tutorial One. After doing so the following should be true:

  • The $TUTORIAL_HOME environment variable should be set to $HOME/threebit-tutorials.
  • Apache2 is installed in $TUTORIAL_HOME/apache2.
  • The module source code is in $TUTORIAL_HOME/apache2_modules/tut2.

mod_tut2.c

The source code for this module is contained in one file (source code). The other files included with mod_tut2 were explained during Tutorial 1 and I will not duplicate their explanation here. Those portions of this module's source code that have not been changed since Tutorial 1 will also not be explained here.
#ifndef DEFAULT_MODTUT2_STRING
#define DEFAULT_MODTUT2_STRING "apache2_mod_tut2: A request was made."
#endif
Here we define the default string that will be written to the error log if the module has been loaded but the ModuleTutorialString configuration directive was not detected in httpd.conf.
module AP_MODULE_DECLARE_DATA tut2_module;
The AP_MODULE_DECLARE_DATA macro is used by a module to declare itself to the httpd core. The apache convention for naming the identifier is to use UNIQUE_NAME-module. That said, most people refer to a module by the reverse - hence, I call this module mod_tut2. I haven't been around long enough to know why this developed but somehow it did. In case you don't believe me, Auto Index is called mod_autoindex, but it's module identifier is autoindex_module.
typedef struct {
  char *string;
} modtut2_config;
We will need to store the customizable string somewhere - this struct will be used to do so. It is silly to use a struct to hold a single string but we may as well start of with a struct because it won't be long until our module needs a richer configuration.
static void *create_modtut2_config(apr_pool_t *p, server_rec *s)
{
  // This module's configuration structure.
  modtut2_config *newcfg;

  // Allocate memory from the provided pool.
  newcfg = (modtut2_config *) apr_pcalloc(p, sizeof(modtut2_config));

  // Set the string to a default value.
  newcfg->string = DEFAULT_MODTUT2_STRING;

  // Return the created configuration struct.
  return (void *) newcfg;
}
This function will be called once by the httpd core to create the initial module configuration. This is accomplished by allocating space for the struct from the provided apr_pool_t. A malloc function provided by APR is used so that it is impossible to leak memory during Apache's runtime - in other words, this module does not need to worry about freeing any memory in the future because when the pool is released, the memory allocated to this module's configuration is also automatically released. This pattern is used extensively throughout Apache.
static const command_rec mod_tut2_cmds[] =
{
  AP_INIT_TAKE1(
    "ModuleTutorialString",
    set_modtut2_string,
    NULL,
    RSRC_CONF,
    "ModTut2String (string) The error_log string."
  ),
  {NULL}
};
This httpd core is responsible for reading and parsing the httpd.conf configuration file. By default, Apache knows how to handle the default configuration directives. The array of command_rec structures above is passed to the httpd core by this module to declare a new configuration directive.

AP_INIT_TAKE1 - This macro declares a configuration directive that takes only one argument. The httpd core will take care of guaranteeing that the configuration is valid (a minimum and maximum of one argument) before bothering to call the provided function. This reduces alot of duplication within each module. There are several options here depending on the purpose of the configuration directive (AP_INIT_NO_ARGS, AP_INIT_RAW_ARGS, AP_INIT_TAKE2, etc etc).

"ModuleTutorialString" - The configuration directive that may now appear in httpd.conf. I haven't looked it up, but I imagine there is a best-practices guide for creating configuration directives.

set_modtut2_string - This is the function that will be called by the httpd core when the configuration directive is detected (assuming it is properly formatted. This function is covered in detail below.

NULL - I don't know what this is for yet. :)

Update (2003.10.26) Maurizio Codogno contributes via email:
In Tutorial 2 you write that you don't yet know the meaning of the fourth field in macro AP_INIT_TAKE1 and similar, which usually is set as NULL. If I read the source correctly, this is used as a structure to send further data to the initializing function - the second parameter, "void *mconfig", when it is called.

RSRC_CONF - This field is used to state where the configuration directive may appear. By using RSRC_CONF we have stated that it can only appear outside of a <Directive> or <Location> scope. I *think* that means it can only be used globally, but you should confirm that.

Usage Message - In case of syntax errors, the httpd core will return this message to the user.

{NULL} - This is just a null placeholder in the array of command_rec structs. It is used to signal the end of new configuration directives.

static const char *set_modtut2_string(cmd_parms *parms,
  void *mconfig, const char *arg)
{
  modtut2_config *s_cfg = ap_get_module_config(
    parms->server->module_config, &tut2_module);

  s_cfg->string = (char *) arg;

  return NULL;
}
This function will be called by the httpd core when the configuration directive we specify later on is encountered in httpd.conf. Notice that it does not malloc space to hold the new configuration. Instead, the ap_get_module_config function is used to obtain it - somehow the httpd core will end up calling create_modtut2_config for us if it hasn't already.

Once the configuration has been obtained, we set the value of the string member to that of the provided argument. We do not need to make a copy of the argument because it is safe to use as is (I read that in the source somewhere, but I have lost the reference to it.)

Finally, we return NULL for success. We could have returned a (char*) containing an error message; httpd will return the string to the user in such a case.

static int mod_tut2_method_handler (request_rec *r)
{
  // Get the module configuration
  modtut2_config *s_cfg = ap_get_module_config(
    r->server->module_config, &tut2_module);

  // Send a message to the log file.
  // [thanks to Min Xu for the security suggestion]
  fprintf(stderr,"%s",s_cfg->string);

  // [deleted - trying to be brief]
}
And finally, the real workhorse. This function is called for each HTTP request. Again, we use ap_get_module_config to obtain the module configuration, though this time we do so by referencing it from the request record. The configured string is written to the error_log stream.
module AP_MODULE_DECLARE_DATA tut2_module =
{
  STANDARD20_MODULE_STUFF,
  NULL,
  NULL,
  create_modtut2_config,
  NULL,
  mod_tut2_cmds,
  mod_tut2_register_hooks,
};
And now we make another call to AP_MODULE_DECLARE_DATA to re-declare the module along with more information. This time around we provide two more details:

create_modtut2_config - Here we tell the httpd core what function should be called when the module configuration data needs to be created/allocated.

mot_tut2_cmds - Here we pass in the list of new configuration directives.

mod_tut2_register_hooks and STANDARD20_MODULE_STUFF are unchanged from the previous module.

Compile, Install, Run

Now it is time to compile and install the module. See the previous tutorial for an explanation of what's going on here.
cd $TUTORIAL_HOME/apache2_modules/tut2
aclocal
autoconf
automake -a
./configure --with-apache=$TUTORIAL_HOME/apache2
make
$TUTORIAL_HOME/apache2/bin/apxs -i -a -n tut2 libmodtut2.la
This module has not been installed. You may want to confirm that only mod_tut2 is enabled if you ran mod_tut1 previously.
# LoadModule tut1_module        modules/libmodtut1.so
LoadModule tut2_module        modules/libmodtut2.so
Also, if you want to customize the string then add the ModuleTutorialString directive to httpd.conf too. The last line in httpd.conf should be okay for this.
ModuleTutorialString "You need to put quotes around multiple words."
Restart Apache so mod_tut2 get's loaded. It's always a good idea to check the configuration first too.
# check the configuration then restart apache
cd $TUTORIAL_HOME/apache2
bin/apachectl configtest
bin/apachectl stop
bin/apachectl start
# make a request to cause a message to be written
lynx --source http://localhost:21000 | grep success
# look for the message in the error log.
tail -100l logs/error_log 

$Id: tutorial2.html,v 1.12 2004/01/29 05:02:59 kevino Exp $


: