dgaudet 97/08/18 00:17:31
Modified: htdocs/manual new_features_1_3.html
src CHANGES Configuration.tmpl
src/core http_config.c http_config.h http_main.c
http_protocol.c http_request.c http_request.h
src/modules/standard mod_setenvif.c
Added: src/modules/standard mod_unique_id.c
Log:
- API: added post_read_request phase
- New module: mod_unique_id
- open_logs is now done before init_modules, and init_modules is not called
twice at initialization
Reviewed by: Ben Laurie, Jim Jagielski, Paul Sutton (well, they didn't
all give +1s but they didn't veto it either! :)
Revision Changes Path
1.17 +7 -0 apachen/htdocs/manual/new_features_1_3.html
Index: new_features_1_3.html
===================================================================
RCS file: /export/home/cvs/apachen/htdocs/manual/new_features_1_3.html,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- new_features_1_3.html 1997/08/17 11:40:10 1.16
+++ new_features_1_3.html 1997/08/18 07:17:19 1.17
@@ -212,6 +212,13 @@
and IRIX.
</ul>
+<li><strong>Unique Identifiers</strong><br>
+ mod_uniqid can be included to generate a unique identifier that
+ distinguishes a hit from every other hit. ("Unique" has
+ some restrictions on it.) Documentation to be written. The
+ identifier is available in the environment variable
+ <code>UNIQUE_ID</code>.
+
</ul>
<!--#include virtual="footer.html" -->
1.403 +17 -0 apachen/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /export/home/cvs/apachen/src/CHANGES,v
retrieving revision 1.402
retrieving revision 1.403
diff -u -r1.402 -r1.403
--- CHANGES 1997/08/18 07:09:16 1.402
+++ CHANGES 1997/08/18 07:17:21 1.403
@@ -1,5 +1,22 @@
Changes with Apache 1.3a2
+ *) API: Added post_read_request API phase which is run right after reading
+ the request from a client, or right after an internal redirect. It is
+ useful for modules setting environment variables that depend only on
+ the headers/contents of the request. It does not run during subrequests
+ because subrequests inherit pretty much everything from the main
+ request. [Dean Gaudet]
+
+ *) Added mod_unique_id which is used to generate a unique identifier for
+ each hit, available in the environment variable UNIQUE_ID.
+ [Dean Gaudet]
+
+ *) init_modules is now called after the error logs have been opened. This
+ allows modules to emit information messages into the error logs.
+ init_modules is only called once in standalone config now, previously
+ it was called twice (once after each config file reading).
+ [Dean Gaudet]
+
*) Fixed proxy-pass-through feature of mod_rewrite; Added error logging
information for case where proxy module is not available. [Marc Slemko]
1.72 +6 -0 apachen/src/Configuration.tmpl
Index: Configuration.tmpl
===================================================================
RCS file: /export/home/cvs/apachen/src/Configuration.tmpl,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -r1.71 -r1.72
--- Configuration.tmpl 1997/08/10 13:29:51 1.71
+++ Configuration.tmpl 1997/08/18 07:17:21 1.72
@@ -300,3 +300,9 @@
## should be the last (highest priority) module.
AddModule modules/standard/mod_setenvif.o
+
+## mod_unique_id generates unique identifiers for each hit, which are
+## available in the environment variable UNIQUE_ID. It may not work on all
+## systems, hence it is not included by default.
+
+# AddModule modules/standard/mod_unique_id.o
1.73 +7 -1 apachen/src/core/http_config.c
Index: http_config.c
===================================================================
RCS file: /export/home/cvs/apachen/src/core/http_config.c,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- http_config.c 1997/08/06 20:21:21 1.72
+++ http_config.c 1997/08/18 07:17:24 1.73
@@ -259,7 +259,8 @@
XtOffsetOf (module, type_checker),
XtOffsetOf (module, fixer_upper),
XtOffsetOf (module, logger),
- XtOffsetOf (module, header_parser)
+ XtOffsetOf (module, header_parser),
+ XtOffsetOf (module, post_read_request)
};
#define NMETHODS (sizeof (method_offsets)/sizeof (method_offsets[0]))
@@ -272,6 +273,7 @@
int fixer_upper;
int logger;
int header_parser;
+ int post_read_request;
} offsets_into_method_ptrs;
/*
@@ -370,6 +372,10 @@
int header_parse (request_rec *r) {
return run_method (r, offsets_into_method_ptrs.header_parser, 1);
+}
+
+int run_post_read_request (request_rec *r) {
+ return run_method (r, offsets_into_method_ptrs.post_read_request, 1);
}
/* Auth stuff --- anything that defines one of these will presumably
1.44 +7 -8 apachen/src/core/http_config.h
Index: http_config.h
===================================================================
RCS file: /export/home/cvs/apachen/src/core/http_config.h,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -r1.43 -r1.44
--- http_config.h 1997/08/06 20:21:23 1.43
+++ http_config.h 1997/08/18 07:17:24 1.44
@@ -205,8 +205,9 @@
* supposed to handle this was configured wrong).
* type_checker --- Determine MIME type of the requested entity;
* sets content_type, _encoding and _language fields.
- * logger --- log a transaction. Not supported yet out of sheer
- * laziness on my part.
+ * logger --- log a transaction.
+ * post_read_request --- run right after read_request or
internal_redirect,
+ * and not run during any subrequests.
*/
int (*translate_handler)(request_rec *);
@@ -230,15 +231,12 @@
*/
#ifdef ULTRIX_BRAIN_DEATH
void (*child_init)();
-#else
- void (*child_init)(server_rec *, pool *);
-#endif
-#ifdef ULTRIX_BRAIN_DEATH
void (*child_exit)();
#else
+ void (*child_init)(server_rec *, pool *);
void (*child_exit)(server_rec *, pool *);
#endif
-
+ int (*post_read_request)(request_rec *);
} module;
/* Initializer for the first few module slots, which are only
@@ -248,7 +246,7 @@
* handle it back-compatibly, or at least signal an error).
*/
-#define MODULE_MAGIC_NUMBER 19970728
+#define MODULE_MAGIC_NUMBER 19970818
#define STANDARD_MODULE_STUFF MODULE_MAGIC_NUMBER, -1, __FILE__, NULL
/* Generic accessors for other modules to get at their own module-specific
@@ -323,5 +321,6 @@
int invoke_handler (request_rec *);
int log_transaction (request_rec *r);
int header_parse (request_rec *);
+int run_post_read_request (request_rec *);
#endif
1.204 +2 -2 apachen/src/core/http_main.c
Index: http_main.c
===================================================================
RCS file: /export/home/cvs/apachen/src/core/http_main.c,v
retrieving revision 1.203
retrieving revision 1.204
diff -u -r1.203 -r1.204
--- http_main.c 1997/08/17 12:57:03 1.203
+++ http_main.c 1997/08/18 07:17:25 1.204
@@ -3082,8 +3082,8 @@
server_conf = read_config (pconf, ptrans, server_confname);
setup_listeners (pconf);
- init_modules (pconf, server_conf);
open_logs (server_conf, pconf);
+ init_modules (pconf, server_conf);
set_group_privs ();
SAFE_ACCEPT(accept_mutex_init (pconf));
if (!is_graceful) {
@@ -3305,7 +3305,6 @@
suexec_enabled = init_suexec();
server_conf = read_config (pconf, ptrans, server_confname);
- init_modules (pconf, server_conf);
if(standalone) {
clear_pool (pconf); /* standalone_main rereads... */
@@ -3319,6 +3318,7 @@
NET_SIZE_T l;
open_logs(server_conf, pconf);
+ init_modules (pconf, server_conf);
set_group_privs();
default_server_hostnames (server_conf);
1.154 +7 -0 apachen/src/core/http_protocol.c
Index: http_protocol.c
===================================================================
RCS file: /export/home/cvs/apachen/src/core/http_protocol.c,v
retrieving revision 1.153
retrieving revision 1.154
diff -u -r1.153 -r1.154
--- http_protocol.c 1997/08/17 13:42:25 1.153
+++ http_protocol.c 1997/08/18 07:17:26 1.154
@@ -63,6 +63,7 @@
#include "http_core.h"
#include "http_protocol.h"
#include "http_main.h"
+#include "http_request.h"
#include "http_log.h" /* For errors detected in basic auth
* common support code...
*/
@@ -797,6 +798,7 @@
request_rec *read_request (conn_rec *conn)
{
request_rec *r = (request_rec *)pcalloc (conn->pool,
sizeof(request_rec));
+ int access_status;
r->connection = conn;
conn->server = conn->base_server;
@@ -881,6 +883,11 @@
r->method_number = M_TRACE;
else
r->method_number = M_INVALID; /* Will eventually croak. */
+
+ if ((access_status = run_post_read_request (r))) {
+ die (access_status, r);
+ return NULL;
+ }
return r;
}
1.76 +11 -1 apachen/src/core/http_request.c
Index: http_request.c
===================================================================
RCS file: /export/home/cvs/apachen/src/core/http_request.c,v
retrieving revision 1.75
retrieving revision 1.76
diff -u -r1.75 -r1.76
--- http_request.c 1997/08/17 20:21:36 1.75
+++ http_request.c 1997/08/18 07:17:26 1.76
@@ -913,7 +913,7 @@
void process_request_internal (request_rec *r)
{
int access_status;
-
+
/* Kludge to be reading the assbackwards field outside of protocol.c,
* but we've got to check for this sort of nonsense somewhere...
*/
@@ -1102,6 +1102,7 @@
{
request_rec *new = (request_rec *)pcalloc(r->pool, sizeof(request_rec));
char t[256]; /* Long enough... */
+ int access_status;
new->connection = r->connection;
new->server = r->server;
@@ -1153,6 +1154,15 @@
ap_snprintf (t, sizeof(t), "%d", r->status);
table_set (new->subprocess_env, "REDIRECT_STATUS", pstrdup (r->pool, t));
+
+ /* XXX: hmm. This is because mod_setenvif and mod_unique_id really need
+ * to do their thing on internal redirects as well. Perhaps this is
+ * a misnamed function.
+ */
+ if ((access_status = run_post_read_request (new))) {
+ die (access_status, new);
+ return NULL;
+ }
return new;
}
1.14 +1 -0 apachen/src/core/http_request.h
Index: http_request.h
===================================================================
RCS file: /export/home/cvs/apachen/src/core/http_request.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- http_request.h 1997/07/15 21:39:57 1.13
+++ http_request.h 1997/08/18 07:17:27 1.14
@@ -92,4 +92,5 @@
/* Function called by main.c to handle first-level request */
void process_request (request_rec *);
int default_handler (request_rec *);
+void die(int type, request_rec *r);
#endif
1.5 +5 -4 apachen/src/modules/standard/mod_setenvif.c
Index: mod_setenvif.c
===================================================================
RCS file: /export/home/cvs/apachen/src/modules/standard/mod_setenvif.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- mod_setenvif.c 1997/08/02 08:10:28 1.4
+++ mod_setenvif.c 1997/08/18 07:17:30 1.5
@@ -269,7 +269,7 @@
{ NULL },
};
-static int fname_translate_setenvif(request_rec *r)
+static int match_headers(request_rec *r)
{
server_rec *s = r->server;
sei_cfg_rec *sconf = (sei_cfg_rec *)get_module_config(s->module_config,
@@ -342,7 +342,7 @@
merge_setenvif_config, /* merge server configs */
setenvif_module_cmds, /* command table */
NULL, /* handlers */
- fname_translate_setenvif, /* filename translation */
+ NULL, /* filename translation */
NULL, /* check_user_id */
NULL, /* check auth */
NULL, /* check access */
@@ -350,6 +350,7 @@
NULL, /* fixups */
NULL, /* logger */
NULL, /* browser parse */
- NULL, /* child (process) initializer */
- NULL /* child (process) rundown handler */
+ NULL, /* child_init */
+ NULL, /* child_exit */
+ match_headers /* post_read_request */
};
1.1 apachen/src/modules/standard/mod_unique_id.c
Index: mod_unique_id.c
===================================================================
/* ====================================================================
* Copyright (c) 1995-1997 The Apache Group. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* 4. The names "Apache Server" and "Apache Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 5. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Group and was originally based
* on public domain software written at the National Center for
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
* For more information on the Apache Group and the Apache HTTP server
* project, please see <http://www.apache.org/>.
*
*/
/*
* mod_uniqueid.c: generate a unique identifier for each request
*
* Original author: Dean Gaudet <[EMAIL PROTECTED]>
*/
#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
#include "multithread.h"
#include <unistd.h>
#include <netdb.h>
#ifdef MULTITHREAD
#error sorry this module does not support multithreaded servers yet
#endif
typedef struct {
time_t stamp;
unsigned int in_addr;
unsigned int pid;
unsigned short counter;
} unique_id_rec;
/* Comments:
*
* We want an identifier which is unique across all hits, everywhere.
* "everywhere" includes multiple httpd instances on the same machine, or on
* multiple machines. Essentially "everywhere" should include all possible
* httpds across all servers at a particular "site". We make some assumptions
* that if the site has a cluster of machines then their time is relatively
* synchronized. We also assume that the first address returned by a
* gethostbyname (gethostname()) is unique across all the machines at the
* "site".
*
* We also further assume that pids fit in 32-bits. If something uses more
* than 32-bits, the fix is trivial, but it requires the unrolled uuencoding
* loop to be extended. * A similar fix is needed to support multithreaded
* servers, using a pid/tid combo.
*
* Together, the in_addr and pid are assumed to absolutely uniquely identify
* this one child from all other currently running children on all servers
* (including this physical server if it is running multiple httpds) from each
* other.
*
* The stamp and counter are used to distinguish all hits for a particular
* (in_addr,pid) pair. The stamp is updated using r->request_time,
* saving cpu cycles. The counter is never reset, and is used to permit up to
* 64k requests in a single second by a single child.
*
* The 112-bits of unique_id_rec are uuencoded using the alphabet
* [EMAIL PROTECTED], resulting in 19 bytes of printable characters. That is
then
* stuffed into the environment variable UNIQUE_ID so that it is available to
* other modules. The alphabet choice differs from normal base64 encoding
* [A-Za-z0-9+/] because + and / are special characters in URLs and we want to
* make it easy to use UNIQUE_ID in URLs.
*
* Note that UNIQUE_ID should be considered an opaque token by other
* applications. No attempt should be made to dissect its internal
components.
* It is an abstraction that may change in the future as the needs of this
* module change.
*
* It is highly desirable that identifiers exist for "eternity". But future
* needs (such as much faster webservers, moving to 64-bit pids, or moving to
a
* multithreaded server) may dictate a need to change the contents of
* unique_id_rec. Such a future implementation should ensure that the first
* field is still a time_t stamp. By doing that, it is possible for a site to
* have a "flag second" in which they stop all of their old-format servers,
* wait one entire second, and then start all of their new-servers. This
* procedure will ensure that the new space of identifiers is completely
unique
* from the old space. (Since the first four unencoded bytes always differ.)
*/
static unsigned global_in_addr;
static APACHE_TLS unique_id_rec cur_unique_id;
static void unique_id_global_init (server_rec *s, pool *p)
{
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
char str[MAXHOSTNAMELEN+1];
struct hostent *hent;
#ifndef NO_GETTIMEOFDAY
struct timeval tv;
#endif
/* First of all, verify some assumptions that have been made about
* the contents of unique_id_rec. We do it this way because it
* isn't affected by trailing padding.
*/
if (XtOffsetOf (unique_id_rec, counter) + sizeof (cur_unique_id.counter)
!= 14) {
log_error ("mod_unique_id: sorry the size assumptions are wrong in
mod_unique_id.c, please remove it from your server or fix the code!", s);
exit (1);
}
/* Now get the global in_addr. Note that it is not sufficient to use
* one of the addresses from the main_server, since those aren't as likely
* to be unique as the physical address of the machine
*/
if (gethostname (str, sizeof (str) - 1) != 0) {
log_unixerr ("gethostname", "mod_unique_id",
"mod_unique_id requires the hostname of the server", s);
exit (1);
}
if ((hent = gethostbyname (str)) == NULL) {
log_printf (s, "mod_unique_id: unable to gethostbyname(\"%s\")", str);
exit (1);
}
global_in_addr = ((struct in_addr *)hent->h_addr_list[0])->s_addr;
log_printf (s, "mod_unique_id: using ip addr %s",
inet_ntoa (*(struct in_addr *)hent->h_addr_list[0]));
/* If the server is pummelled with restart requests we could possibly
* end up in a situation where we're starting again during the same
* second that has been used in previous identifiers. Avoid that
* situation.
*
* In truth, for this to actually happen not only would it have to
* restart in the same second, but it would have to somehow get the
* same pids as one of the other servers that was running in that second.
* Which would mean a 64k wraparound on pids ... not very likely at
* all.
*
* But protecting against it is relatively cheap. We just sleep into
* the next second.
*/
#ifdef NO_GETTIMEOFDAY
sleep (1);
#else
if (gettimeofday (&tv, NULL) == -1) {
sleep (1);
} else if (tv.tv_usec) {
tv.tv_sec = 0;
tv.tv_usec = 1000000 - tv.tv_usec;
select (0, NULL, NULL, NULL, &tv);
}
#endif
}
static void unique_id_child_init (server_rec *s, pool *p)
{
pid_t pid;
#ifndef NO_GETTIMEOFDAY
struct timeval tv;
#endif
/* Note that we use the pid because it's possible that on the same
* physical machine there are multiple servers (i.e. using Listen).
* But it's guaranteed that none of them will share the same pids
* between children.
*
* XXX: for multithread this needs to use a pid/tid combo and probably
* XXX: needs to be expanded to 32 bits
*/
pid = getpid();
cur_unique_id.pid = pid;
/* Test our assumption that the pid is 16-bits. But note we can't just
* test sizeof (pid_t) because on some machines pid_t is 32-bits but
* pids are actually only 16-bits. It would have been really nice to
* test this during global_init ... but oh well.
*/
if (cur_unique_id.pid != pid) {
log_error ("mod_unique_id: oh no! pids are greater than 16-bits! I'm
broken!", s);
}
cur_unique_id.in_addr = global_in_addr;
/* If we use 0 as the initial counter we have a little less protection
* against restart problems, and a little less protection against a
* clock going backwards in time.
*/
#ifndef NO_GETTIMEOFDAY
if (gettimeofday (&tv, NULL) == -1) {
cur_unique_id.counter = 0;
} else {
cur_unique_id.counter = tv.tv_usec;
}
#else
cur_unique_id.counter = 0;
#endif
/* We must always use network ordering for these bytes, so that
identifiers
* are comparable between machines of different byte orderings. Note
* in_addr is already in network order.
*/
cur_unique_id.pid = htons (cur_unique_id.pid);
cur_unique_id.counter = htons (cur_unique_id.counter);
}
/* NOTE: This is *NOT* the same encoding used by uuencode ... the last two
* characters should be + and /. But those two characters have very special
* meanings in URLs, and we want to make it easy to use identifiers in
* URLs. So we replace them with @ and -.
*/
static const char uuencoder[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '@', '-',
};
static int gen_unique_id (request_rec *r)
{
/* when we uuencode it will take 19 bytes plus \0 */
char str[19 + 1];
const unsigned char *x;
unsigned short counter;
cur_unique_id.stamp = htonl (r->request_time);
/* do the uuencoding */
x = (const unsigned char *)&cur_unique_id;
str[0] = uuencoder[x[0] >> 2];
str[1] = uuencoder[((x[0] & 0x03) << 4) | ((x[1] & 0xf0) >> 4)];
str[2] = uuencoder[((x[1] & 0x0f) << 2) | ((x[2] & 0xc0) >> 6)];
str[3] = uuencoder[x[2] & 0x3f];
x += 3;
str[4] = uuencoder[x[0] >> 2];
str[5] = uuencoder[((x[0] & 0x03) << 4) | ((x[1] & 0xf0) >> 4)];
str[6] = uuencoder[((x[1] & 0x0f) << 2) | ((x[2] & 0xc0) >> 6)];
str[7] = uuencoder[x[2] & 0x3f];
x += 3;
str[8] = uuencoder[x[0] >> 2];
str[9] = uuencoder[((x[0] & 0x03) << 4) | ((x[1] & 0xf0) >> 4)];
str[10] = uuencoder[((x[1] & 0x0f) << 2) | ((x[2] & 0xc0) >> 6)];
str[11] = uuencoder[x[2] & 0x3f];
x += 3;
str[12] = uuencoder[x[0] >> 2];
str[13] = uuencoder[((x[0] & 0x03) << 4) | ((x[1] & 0xf0) >> 4)];
str[14] = uuencoder[((x[1] & 0x0f) << 2) | ((x[2] & 0xc0) >> 6)];
str[15] = uuencoder[x[2] & 0x3f];
x += 3;
str[16] = uuencoder[x[0] >> 2];
str[17] = uuencoder[((x[0] & 0x03) << 4) | ((x[1] & 0xf0) >> 4)];
str[18] = uuencoder[((x[1] & 0x0f) << 2) | (( 0 & 0xc0) >> 6)];
str[19] = '\0';
table_set (r->subprocess_env, "UNIQUE_ID", str);
/* and increment the identifier for the next call */
counter = ntohs (cur_unique_id.counter) + 1;
cur_unique_id.counter = htons (counter);
return DECLINED;
}
module MODULE_VAR_EXPORT unique_id_module = {
STANDARD_MODULE_STUFF,
unique_id_global_init, /* initializer */
NULL, /* dir config creater */
NULL, /* dir merger --- default is to override */
NULL, /* server config */
NULL, /* merge server configs */
NULL, /* command table */
NULL, /* handlers */
NULL, /* filename translation */
NULL, /* check_user_id */
NULL, /* check auth */
NULL, /* check access */
NULL, /* type_checker */
NULL, /* fixups */
NULL, /* logger */
NULL, /* header parser */
unique_id_child_init, /* child_init */
NULL, /* child_exit */
gen_unique_id /* post_read_request */
};