Exemple complet

Nous avons passé du temps à réfléchir à un exemple de module qui utiliserait tous les hooks disponibles. En même temps, nous avons effectué un travail considérable pour passer en revue les mécanismes internes d’Apache pour savoir ce qui se passe, et quand. Soudainement, nous avons pensé à écrire un module qui montrerait le déroulement de toutes ces étapes : mod_reveal.c était né. Il ne s’agit pas d’un module que vous intégrerez sans modification dans un serveur Apache car il produit ses informations sur la sortie standard des erreurs (qui aboutit, pour l’essentiel, dans le fichier log des erreurs). Plutôt que d’obscurcir sa fonctionnalité essentielle en incluant du code permettant d’activer ou désactiver la surveillance qu’il exerce, nous avons préféré le garder simple. Cela dit, même sous cette forme, ce module est très pratique, comme nous allons le voir dans cette section.

Présentation

Le module implémente deux commandes, RevealServerTag et RevealTag. La première donne un nom à un conteneur serveur et se trouve dans la configuration serveur. La seconde donne un nom à un conteneur répertoire (ou emplacement, ou fichier) et se trouve dans la configuration de répertoire. Lorsque ces deux configurations sont juxtaposées, la configuration résultante est balisée par une combinaison des marqueurs des deux conteneurs fusionnés. Ce module implémente également un handler, qui produit du HTML contenant des informations pertinentes sur une URL.

Tout module qui se respecte débute par une note de copyright :

/*

Reveal the order in which things are done.

 

Copyright (C) 1996, 1998 Ben Laurie

*/

Le fichier inclus http_protocol.h n’est utile que pour le traitement de la requête, les deux autres sont nécessaires pour quasiment tous les modules :

#include "httpd.h"

#include "http_config.h"

#include "http_protocol.h"

#include "http_request.h" [2.0]

#include "apr_strings.h" [2.0]

#include "http_connection.h" [2.0]

#include "http_log.h" [2.0]

#include "http_core.h" [2.0]

#include "scoreboard.h" [2.0]

#include <unistd.h> [2.0]

La structure de configuration de répertoire est la suivante :

typedef struct

{

char *szDir;

char *szTag;

} SPerDir;

Celle de la configuration du serveur est :

typedef struct

{

char *szServer;

char *szTag;

} SPerServer;

Dans la plupart des modules, on ne peut éviter une référence circulaire : la structure module est nécessaire pour accéder aux configurations serveur et répertoire dans les fonctions hook mais, pour construire cette structure, nous devons connaître les fonctions hook. Comme il n’y a qu’une seule structure module et beaucoup de fonctions hook, le plus simple consiste à créer une référence anticipée de la structure :

extern module reveal_module;

Sur certains systèmes, une chaîne NULL peut faire planter la fonction printf( ) ; nous définissons donc une fonction pour pouvoir traiter les chaînes NULL :

static const char *None(const char *szStr)

{

if(szStr)

return szStr;

return "(none)";

}

Comme les noms des serveurs et les numéros des ports ne sont souvent pas connus à la création des structures de serveurs, mais qu’ils sont renseignés lorsque la fonction d’initialisation est appelée, nous les renommons dans la fonction init. Vous remarquerez que nous devons itérer sur tous les serveurs car init n’est appelée qu’avec la structure de serveur « principale ». Nous en profitons pour afficher l’ancien et le nouveau nom, afin que nous puissions voir ce qui se passe. Pour être complets, nous ajoutons une chaîne indiquant la version du module à la chaîne de version du serveur (normalement, on ne le fait pas pour un module aussi mineur que celui-ci) :

static void SubRevealInit(server_rec *pServer,pool *pPool)

{

SPerServer *pPerServer=ap_get_module_config(pServer->module_config,

&reveal_module);

 

if(pServer->server_hostname &&

(!strncmp(pPerServer->szServer,"(none):",7)

|| !strcmp(pPerServer->szServer+strlen(pPerServer->szServer)

-2,":0")))

{

char szPort[20];

 

fprintf(stderr,"Init : update server name from %s\n",

pPerServer->szServer);

sprintf(szPort,"%d",pServer->port);

pPerServer->szServer=ap_pstrcat(pPool,pServer->server_hostname,":",

szPort,NULL);

}

fprintf(stderr,"Init : host=%s port=%d server=%s tag=%s\n",

pServer->server_hostname,pServer->port,pPerServer->szServer,

None(pPerServer->szTag));

}

 

static void RevealInit(server_rec *pServer,pool *pPool)

{

ap_add_version_component("Reveal/0.0");

for( ; pServer ; pServer=pServer->next)

SubRevealInit(pServer,pPool);

fprintf(stderr,"Init : done\n");

}

Nous créons maintenant la structure de la configuration du serveur. Comme cette fonction est appelée dès que le serveur est créé, pServer->server_hostname et pServer->port peuvent ne pas avoir été initialisé : leurs valeurs doivent donc être prises avec des circonspection (mais elles seront corrigées plus tard).

static void *RevealCreateServer(pool *pPool,server_rec *pServer)

{

SPerServer *pPerServer=ap_palloc(pPool,sizeof *pPerServer);

const char *szServer;

char szPort[20];

 

szServer=None(pServer->server_hostname);

sprintf(szPort,"%d",pServer->port);

pPerServer->szTag=NULL;

pPerServer->szServer=ap_pstrcat(pPool,szServer,":",szPort,NULL);

 

fprintf(stderr,"CreateServer: server=%s:%s\n",szServer,szPort);

return pPerServer;

}

Puis, nous fusionnons les deux configurations serveur. La configuration résultante est balisée avec les noms des deux configurations dont elle dérive (ou par la chaîne (none), si celles-ci n’étaient pas balisées). Vous remarquerez que nous créons une nouvelle structure de configuration serveur pour contenir la configuration fusionnée (c’est la façon habituelle de procéder) :

static void *RevealMergeServer(pool *pPool,void *_pBase,void *_pNew)

{

SPerServer *pBase=_pBase;

SPerServer *pNew=_pNew;

SPerServer *pMerged=ap_palloc(pPool,sizeof *pMerged);

 

fprintf(stderr,

"MergeServer : pBase: server=%s tag=%s pNew: server=%s tag=%s\n",

pBase->szServer,None(pBase->szTag),

pNew->szServer,None(pNew->szTag));

 

pMerged->szServer=ap_pstrcat(pPool,pBase->szServer,"+",pNew->szServer,

NULL);

pMerged->szTag=ap_pstrcat(pPool,None(pBase->szTag),"+",

None(pNew->szTag),NULL);

 

return pMerged;

}

Nous créons maintenant une structure de configuration répertoire. Si szDir vaut NULL, on lui affecte (none) pour garantir que les fusions futures auront quelque chose à fusionner ! Bien sûr, szDir vaut NULL une fois par serveur. Vous remarquerez que nous ne mémorisons pas dans le log le serveur concerné : la raison est qu’il n’y a pas moyen de le savoir. Il faut également signaler que cette fonction ne sera appelée pour un répertoire (ou un emplacement, ou un fichier) particulier que si une directive RevealTag apparaît dans ce conteneur :

static void *RevealCreateDir(pool *pPool,char *_szDir)

{

SPerDir *pPerDir=ap_palloc(pPool,sizeof *pPerDir);

const char *szDir=None(_szDir);

 

fprintf(stderr,"CreateDir : dir=%s\n",szDir);

 

pPerDir->szDir=ap_pstrdup(pPool,szDir);

pPerDir->szTag=NULL;

 

return pPerDir;

}

Puis, nous fusionnons les structures de répertoires. Là aussi, nous n’avons aucun idée du serveur que nous traitons. En pratique, vous constaterez que cette fonction est appelée très souvent :

static void *RevealMergeDir(pool *pPool,void *_pBase,void *_pNew)

{

SPerDir *pBase=_pBase;

SPerDir *pNew=_pNew;

SPerDir *pMerged=ap_palloc(pPool,sizeof *pMerged);

 

fprintf(stderr,"MergeDir : pBase: dir=%s tag=%s "

"pNew: dir=%s tag=%s\n",pBase->szDir,None(pBase->szTag),

pNew->szDir,None(pNew->szTag));

pMerged->szDir=ap_pstrcat(pPool,pBase->szDir,"+",pNew->szDir,NULL);

pMerged->szTag=ap_pstrcat(pPool,None(pBase->szTag),"+",

None(pNew->szTag),NULL);

return pMerged;

}

Voici une fonction annexe, utilisée par la plupart des autres hooks, qui affiche les configurations serveur et répertoire en cours d’utilisation. Bien qu’elle s’adresse à une situation dans laquelle il n’y a pas de configuration de répertoire, cela ne devrait jamais arriver :

static void ShowRequestStuff(request_rec *pReq)

{

SPerDir *pPerDir=ap_get_module_config(pReq->per_dir_config,

&reveal_module); [1.3]

SPerDir *pPerDir=pReq->per_dir_config ?

ap_get_module_config(pReq->per_dir_config,&reveal_module) : NULL; [2.0]

SPerServer *pPerServer=ap_get_module_config(pReq->server->

module_config,&reveal_module);

SPerDir none={"(null)","(null)"};

SPerDir noconf={"(no per-dir config)","(no per-dir config)"};

 

if(!pReq->per_dir_config)

pPerDir=&noconf;

else if(!pPerDir)

pPerDir=&none;

 

fprintf(stderr," server=%s tag=%s dir=%s tag=%s\n",

pPerServer->szServer,pPerServer->szTag,pPerDir->szDir,

pPerDir->szTag);

}

Les hooks suivants ne font rien de plus que de signaler qu’ils ont été utilisés :

static int RevealTranslate(request_rec *pReq)

{

fprintf(stderr,"Translate : uri=%s",pReq->uri);

ShowRequestStuff(pReq);

return DECLINED;

}

 

static int RevealCheckUserID(request_rec *pReq)

{

fprintf(stderr,"CheckUserID :");

ShowRequestStuff(pReq);

return DECLINED;

}

 

static int RevealCheckAuth(request_rec *pReq)

{

fprintf(stderr,"CheckAuth :");

ShowRequestStuff(pReq);

return DECLINED;

}

 

static int RevealCheckAccess(request_rec *pReq)

{

fprintf(stderr,"CheckAccess : ");

ShowRequestStuff(pReq);

return DECLINED;

}

 

static int RevealTypeChecker(request_rec *pReq)

{

fprintf(stderr,"TypeChecker :");

ShowRequestStuff(pReq);

return DECLINED;

}

 

static int RevealFixups(request_rec *pReq)

{

fprintf(stderr,"Fixups :");

ShowRequestStuff(pReq);

return DECLINED;

}

static int RevealLogger(request_rec *pReq)

{

fprintf(stderr,"Logger :");

ShowRequestStuff(pReq);

return DECLINED;

}

 

static int RevealHeaderParser(request_rec *pReq)

{

fprintf(stderr,"HeaderParser :");

ShowRequestStuff(pReq);

return DECLINED;

}

Vient ensuite la fonction d’initialisation des processus fils. Elle étend le marqueur server pour y inclure le PID de son instance de serveur. Notez que, comme la fonction init, elle doit itérer sur toutes les instances de serveur -- de plus, dans la version 2.0, elle doit enregistrer le handler de terminaison du fils :

static void RevealChildInit(server_rec *pServer, pool *pPool)

{

char szPID[20];

 

fprintf(stderr,"Child Init : pid=%d\n",(int)getpid());

 

sprintf(szPID,"[%d]",(int)getpid());

for( ; pServer ; pServer=pServer->next)

{

SPerServer *pPerServer=ap_get_module_config(pServer->module_config,

&reveal_module);

pPerServer->szServer=ap_pstrcat(pPool,pPerServer->szServer,szPID,

NULL);

}

apr_pool_cleanup_register(pPool,pServer,RevealChildExit,
RevealChildExit);[2.0]

}

Les deux derniers hooks écrivent simplement dans le log -- vous remarquerez, cependant, que la déclaration de RevealChildExit( ) de la version 1.3 est totalement différente de celle de la version 2.0. De plus, en 2.0, RevealChildExit( ) doit apparaître avant RevealChildInit( ) pour éviter les erreurs de compilation :

(1.3)

static void RevealChildExit(server_rec *pServer, pool *pPool)

{

fprintf(stderr,"Child Exit : pid=%d\n",(int)getpid());

}

(2.0)

static apr_status_t RevealChildExit(void *p)

{

fprintf(stderr,"Child Exit : pid=%d\n",(int)getpid());

 

return OK;

}

 

static int RevealPostReadRequest(request_rec *pReq)

{

fprintf(stderr,"PostReadReq : method=%s uri=%s protocol=%s",

pReq->method,pReq->unparsed_uri,pReq->protocol);

ShowRequestStuff(pReq);

 

return DECLINED;

}

Le code suivant est celui du handler de la directive RevealTag. Si plusieurs RevealTag apparaissent dans un conteneur, elles sont raccordées par un « - ». La fonction renvoie NULL s’il n’y a pas eu d’erreur :

static const char *RevealTag(cmd_parms *cmd, SPerDir *pPerDir, char *arg)

{

SPerServer *pPerServer=ap_get_module_config(cmd->server->module_config,

&reveal_module);

 

fprintf(stderr,"Tag : new=%s dir=%s server=%s tag=%s\n",

arg,pPerDir->szDir,pPerServer->szServer,

None(pPerServer->szTag));

if(pPerDir->szTag)

pPerDir->szTag=ap_pstrcat(cmd->pool,pPerDir->szTag,"-",arg,NULL);

else

pPerDir->szTag=ap_pstrdup(cmd->pool,arg);

 

return NULL;

}

Cette fonction gère la directive RevealServerTag. Là aussi, si plusieurs RevealServerTag apparaissent dans un conteneur serveur, elles sont raccordées par un « - » :

static const char *RevealServerTag(cmd_parms *cmd, SPerDir *pPerDir, char *arg)

{

SPerServer *pPerServer=ap_get_module_config(cmd->server->module_config,

&reveal_module);

 

fprintf(stderr,"ServerTag : new=%s server=%s stag=%s\n", arg,

pPerServer->szServer,None(pPerServer->szTag));

 

if(pPerServer->szTag)

pPerServer->szTag=ap_pstrcat(cmd->pool,pPerServer->szTag,"-",arg, NULL);

else

pPerServer->szTag=ap_pstrdup(cmd->pool,arg);

 

return NULL;

}

 

Nous lions maintenant les directives à leurs handlers. Vous remarquerez que RevealTag utilise ACCESS_CONF|OR_ALL pour son req_override : elle est donc autorisée à chaque fois qu’un conteneur <Directory> apparaît. RevealServerTag n’a de sens qu’à l’extérieur des conteneurs <Directory>, c’est pourquoi elle utilise RSRC_CONF :

(1.3)static command_rec aCommands[]=

{

{ "RevealTag", RevealTag, NULL, ACCESS_CONF|OR_ALL, TAKE1, "a tag for
this section"},

{ "RevealServerTag", RevealServerTag, NULL, RSRC_CONF, TAKE1, "a tag for
this server" },

{ NULL }

};

(2.0)static command_rec aCommands[]=

{

AP_INIT_TAKE1("RevealTag", RevealTag, NULL, ACCESS_CONF|OR_ALL,

"a tag for this section"),

AP_INIT_TAKE1("RevealServerTag", RevealServerTag, NULL, RSRC_CONF,

"a tag for this server" ),

{ NULL }

};

Les deux fonctions utilitaires suivantes produisent simplement des informations sous la forme d’une ligne de tableau :

static void TShow(request_rec *pReq,const char *szHead,const char *szItem)

{

ap_rprintf(pReq,"<TR><TH>%s<TD>%s\n",szHead,szItem);

}

 

static void TShowN(request_rec *pReq,const char *szHead,int nItem)

{

ap_rprintf(pReq,"<TR><TH>%s<TD>%d\n",szHead,nItem);

}

Le code suivant est le handler de requête ; il produit le code HTML décrivant les configurations qui gèrent l’URI :

static int RevealHandler(request_rec *pReq)

{

SPerDir *pPerDir=ap_get_module_config(pReq->per_dir_config,

&reveal_module);

SPerServer *pPerServer=ap_get_module_config(pReq->server->

module_config,&reveal_module);

 

pReq->content_type="text/html";

ap_send_http_header(pReq);

 

ap_rputs("<CENTER><H1>Revelation of ",pReq);

ap_rputs(pReq->uri,pReq);

ap_rputs("</H1></CENTER><HR>\n",pReq);

ap_rputs("<TABLE>\n",pReq);

TShow(pReq,"URI",pReq->uri);

TShow(pReq,"Filename",pReq->filename);

TShow(pReq,"Server name",pReq->server->server_hostname);

TShowN(pReq,"Server port",pReq->server->port);

TShow(pReq,"Server config",pPerServer->szServer);

TShow(pReq,"Server config tag",pPerServer->szTag);

TShow(pReq,"Directory config",pPerDir->szDir);

TShow(pReq,"Directory config tag",pPerDir->szTag);

ap_rputs("</TABLE>\n",pReq);

 

return OK;

}

Nous associons ici le handler de requête avec la chaîne de handler (1.3) :

static handler_rec aHandlers[]=

{

{ "reveal", RevealHandler },

{ NULL },

};

Enfin, voici la structure module pour la version 1.3 :

module reveal_module = {

STANDARD_MODULE_STUFF,

RevealInit, /* initializer */

RevealCreateDir, /* dir config creater */

RevealMergeDir, /* dir merger --- default is to override */

RevealCreateServer, /* server config */

RevealMergeServer, /* merge server configs */

aCommands, /* command table */

aHandlers, /* handlers */

RevealTranslate, /* filename translation */

RevealCheckUserID, /* check_user_id */

RevealCheckAuth, /* check auth */

RevealCheckAccess, /* check access */

RevealTypeChecker, /* type_checker */

RevealFixups, /* fixups */

RevealLogger, /* logger */

RevealHeaderParser, /* header parser */

RevealChildInit, /* child init */

RevealChildExit, /* child exit */

RevealPostReadRequest, /* post read request */ };

Dans la version 2.0, nous avons une fonction d’enregistrement du hook et la structure module :

static void RegisterHooks(apr_pool_t *pPool)

{

ap_hook_post_config(RevealInit,NULL,NULL,APR_HOOK_MIDDLE);

ap_hook_handler(RevealHandler,NULL,NULL,APR_HOOK_MIDDLE);

ap_hook_translate_name(RevealTranslate,NULL,NULL,APR_HOOK_MIDDLE);

ap_hook_check_user_id(RevealCheckUserID,NULL,NULL,APR_HOOK_MIDDLE);

ap_hook_auth_checker(RevealCheckAuth,NULL,NULL,APR_HOOK_MIDDLE);

ap_hook_access_checker(RevealCheckAccess,NULL,NULL,APR_HOOK_MIDDLE);

ap_hook_type_checker(RevealTypeChecker,NULL,NULL,APR_HOOK_MIDDLE);

ap_hook_fixups(RevealFixups,NULL,NULL,APR_HOOK_MIDDLE);

ap_hook_log_transaction(RevealLogger,NULL,NULL,APR_HOOK_MIDDLE);

ap_hook_header_parser(RevealHeaderParser,NULL,NULL,APR_HOOK_MIDDLE);

ap_hook_child_init(RevealChildInit,NULL,NULL,APR_HOOK_MIDDLE);

ap_hook_post_read_request(RevealPostReadRequest,NULL,NULL,APR_HOOK_MIDDLE);

}

 

module reveal_module = {

STANDARD20_MODULE_STUFF,

RevealCreateDir, /* dir config creater */

RevealMergeDir, /* dir merger --- default is to override */

RevealCreateServer, /* server config */

RevealMergeServer, /* merge server configs */

aCommands, /* command table */

RegisterHooks /* hook registration */

};

Pour inclure ce module dans Apache, on ajoute la ligne suivante :

AddModule modules/extra/mod_reveal.o

dans Configuration. Vous pouvez l’essayer sur votre serveur préféré : il suffit de saupoudrer le fichier httpd.conf de directives RevealTag et RevealServerTag. À cause du volume énorme de messages de log produit, il est déconseillé de le faire sur un serveur en production !

Exemple de résultat

Pour tester mod_reveal.c, nous l’avons utilisé avec la configuration suivante :

Listen 9001

Listen 9000

 

TransferLog /home/ben/www/APACHE3/book/logs/access_log

ErrorLog /home/ben/www/APACHE3/book/logs/error_log

RevealTag MainDir

RevealServerTag MainServer

<LocationMatch /.reveal>

RevealTag Revealer

SetHandler reveal

</LocationMatch>

 

<VirtualHost *:9001>

DocumentRoot /home/ben/www/APACHE3/docs

RevealTag H1Main

RevealServerTag H1

<Directory /home/ben/www/APACHE3/docs/protected>

RevealTag H1ProtectedDirectory

</Directory>

<Location /protected>

RevealTag H1ProtectedLocation

</Location>

</VirtualHost>

 

<VirtualHost *:9000>

DocumentRoot /home/camilla/www/APACHE3/docs

RevealTag H2Main

RevealServerTag H2

</VirtualHost>

Notez que les conteneurs <Directory> et <Location> du premier hôte virtuel désignent, en fait, le même emplacement : c’est pour montrer l’ordre dans lequel les conteneurs sont combinés. Notez également que le conteneur <LocationMatch> ne doit pas nécessairement correspondre à un vrai fichier : une recherche d’un emplacement quelconque se terminant par .reveal invoquera le handler de mod_reveal.c. Le lancement du serveur produit les messages suivants à l’écran :

bash$ httpd -d ~/www/APACHE3/book/

CreateServer: server=(none):0

CreateDir : dir=(none)

PreConfig [2.0]

Tag : new=MainDir dir=(none) server=(none):0 tag=(none)

ServerTag : new=MainServer server=(none):0 stag=(none)

CreateDir : dir=/.reveal

Tag : new=Revealer dir=/.reveal server=(none):0 tag=MainServer

CreateDir : dir=(none)

CreateServer : server=(none):9001

Tag : new=H1Main dir=(none) server=(none):9001 tag=(none)

ServerTag : new=H1 server=(none):9001 stag=(none)

CreateDir : dir=/home/ben/www/APACHE3/docs/protected

Tag : new=H1ProtectedDirectory dir=/home/ben/www/APACHE3/docs/protected

server=(none) :9001 tag=H1

CreateDir : dir=/protected

Tag : new=H1ProtectedLocation dir=/protected server=(none):9001 tag=H1

CreateDir : dir=(none)

CreateServer : server=(none):9000

Tag : new=H2Main dir=(none) server=(none):9000 tag=(none)

ServerTag : new=H2 server=(none):9000 stag=(none)

MergeServer : pBase: server=(none):0 tag=MainServer pNew: server=(none):9000

tag=H2

MergeDir : pBase: dir=(none) tag=MainDir pNew: dir=(none) tag=H2Main

MergeServer : pBase: server=(none):0 tag=MainServer pNew: server=(none):9001

tag=H1

MergeDir : pBase: dir=(none) tag=MainDir pNew: dir=(none) tag=H1Main

Dans la version 2.0, vous remarquerez que le hook pre_config apparaît en fait légèrement après que la configuration ait démarré !

Notez que les conteneurs <Location> et <LocationMatch> sont traités comme des répertoires du point de vue du code. À ce stade, stderr est redirigé vers le fichier log des erreurs et les messages suivants y sont inscrits :

OpenLogs : server=(none):0 tag=MainServer [2.0]

Init : update server name from (none):0

Init : host=scuzzy.ben.algroup.co.uk port=0 server=scuzzy.ben.
algroup.co.uk:0 tag=MainServer

Init : update server name from (none):0+(none):9000

Init : host=scuzzy.ben.algroup.co.uk port=9000 server=scuzzy.ben.
algroup.co.uk:9000 tag=MainServer+H2

Init : update server name from (none):0+(none):9001

Init : host=scuzzy.ben.algroup.co.uk port=9001 server=scuzzy.ben.
algroup.co.uk:9001 tag=MainServer+H1

Init : done

La première passe de l’initialisation est désormais terminée, Apache supprime les configurations et redémarre (cette double initialisation est nécessaire car les directives peuvent modifier des choses telles que l’emplacement des fichiers d’initialisation) :

CreateServer : server=(none):0

CreateDir : dir=(none)

Tag : new=MainDir dir=(none) server=(none):0 tag=(none)

ServerTag : new=MainServer server=(none):0 stag=(none)

CreateDir : dir=/.reveal

Tag : new=Revealer dir=/.reveal server=(none):0 tag=MainServer

CreateDir : dir=(none)

CreateServer : server=(none):9001

Tag : new=H1Main dir=(none) server=(none):9001 tag=(none)

ServerTag : new=H1 server=(none):9001 stag=(none)

CreateDir : dir=/home/ben/www/APACHE3/docs/protected

Tag : new=H1ProtectedDirectory dir=/home/ben/www/APACHE3/docs/protected
server=(none) :9001 tag=H1

CreateDir : dir=/protected Tag : new=H1ProtectedLocation dir=/protected
server=(none) : 9001 tag=H1

CreateDir : dir=(none)

CreateServer : server=(none):9000

Tag : new=H2Main dir=(none) server=(none):9000 tag=(none)

ServerTag : new=H2 server=(none):9000 stag=(none)

Nous avons maintenant créé tous les conteneurs serveurs et répertoires, et le serveur principal est fusionné avec les hôtes virtuels :

MergeServer : pBase: server=(none):0 tag=MainServer pNew: server=(none):9000
tag=H2

MergeDir : pBase: dir=(none) tag=MainDir pNew: dir=(none) tag=H2Main

MergeServer : pBase: server=(none):0 tag=MainServer pNew: server=(none):9001
tag=H1

MergeDir : pBase: dir=(none) tag=MainDir pNew: dir=(none) tag=H1Main

Les fonctions init sont alors appelées (elles renomment les serveurs, maintenant que leurs « vrais » noms sont connus) :

Init : update server name from (none):0

Init : host=freeby.ben.algroup.co.uk port=0 server=freeby.ben.
algroup.co.uk:0 tag=MainServer

Init : update server name from (none):0+(none):9000

Init : host=freeby.ben.algroup.co.uk port=9000 server=freeby.ben.
algroup.co.uk:9000 tag=MainServer+H2

Init : update server name from (none):0+(none):9001

Init : host=freeby.ben.algroup.co.uk port=9001 server=freeby.ben.
algroup.co.uk:9001 tag=MainServer+H1

Init : done

Apache inscrit dans le fichier log son message de démarrage :

[Sun Jul 12 13:08:01 1998] [notice] Apache/1.3.1-dev (Unix) Reveal/0.0
configured -- resuming normal operations

Les init des processus fils sont appelées :

Child Init : pid=23287

Child Init : pid=23288

Child Init : pid=23289

Child Init : pid=23290

Child Init : pid=23291

Apache est maintenant prêt à répondre aux requêtes. Commençons par http://hote:9001/ :

CreateConnection : server=scuzzy.ben.algroup.co.uk:0[78348]
tag=MainServer conn_id=0 [2.0]

PreConnection : keepalive=0 double_reverse=0 [2.0]

ProcessConnection : keepalive=0 double_reverse=0 [2.0]

CreateRequest : server=scuzzy.ben.algroup.co.uk:9001[78348]
tag=MainServer+H1 dir=(no per-dir config)
tag=(no per-dir config) [2.0]

PostReadReq : method=GET uri=/ protocol=HTTP/1.0

server=freeby.ben.algroup.co.uk:9001[23287]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main

QuickHandler : lookup_uri=0 server=scuzzy.ben.algroup.co.uk:9001[78348]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main [2.0]

Translate : uri=/ server=freeby.ben.algroup.co.uk:9001[23287]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main

MapToStorage : server=scuzzy.ben.algroup.co.uk:9001[78348]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main [2.0]

HeaderParser : server=freeby.ben.algroup.co.uk:9001[23287]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main

CheckAccess : server=freeby.ben.algroup.co.uk:9001[23287]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main

TypeChecker : server=freeby.ben.algroup.co.uk:9001[23287]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main [1.3]

Fixups : server=freeby.ben.algroup.co.uk:9001[23287]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main

Comme / est un répertoire, Apache tente d’utiliser /index.html à la place (ici, ce fichier n’existe pas, mais Apache effectue quand même les étapes) :

CreateRequest : server=scuzzy.ben.algroup.co.uk:9001[78348]

tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main [2.0]

QuickHandler : lookup_uri=1 server=scuzzy.ben.algroup.co.uk:9001[78348]

tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main [2.0]

Translate : uri=/index.html server=freeby.ben.algroup.co.uk:9001[23287]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main

À partir de là, les versions 1.3 et 2.0 divergent de façon assez radicale. Dans la version 1.3 :

CheckAccess : server=freeby.ben.algroup.co.uk:9001[23287] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main

TypeChecker : server=freeby.ben.algroup.co.uk:9001[23287] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main

Fixups : server=freeby.ben.algroup.co.uk:9001[23287] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main

Logger : server=freeby.ben.algroup.co.uk:9001[23287] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main

Child Init : pid=23351

C’est assez clair, mais remarquez que les configurations utilisées sont la fusion de celle du serveur principal et de celle du premier hôte virtuel. Notez également le Child Init final : c’est parce qu’Apache a décidé que la charge méritait le lancement d’un autre processus fils.

La version 2.0 est un peu plus complexe :

MapToStorage : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main unparsed_uri=/index.html

Fixups : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main unparsed_uri=/index.html

InsertFilter : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main unparsed_uri=/

Jusqu’à maintenant, nous recherchions /index.html, puis nous continuions avec /. Désormais, nous obtenons beaucoup d’informations supplémentaires produites par mod_autoindex, qui utilise des requêtes internes pour construire les URL pour la page d’index :

CreateRequest : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main unparsed_uri=(null)

MapToStorage : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main unparsed_uri=/protected/

MergeDir : pBase: dir=(none)+(none) tag=MainDir+H1Main pNew:
dir=/home/ben/www5/docs/protected/ tag=H1ProtectedDirectory

CheckAccess : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1
dir=(none)+(none)+/home/ben/www5/docs/protected/
tag=MainDir+H1Main+H1ProtectedDirectory unparsed_uri=/protected/

Fixups : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1
dir=(none)+(none)+/home/ben/www5/docs/protected/
tag=MainDir+H1Main+H1ProtectedDirectory unparsed_uri=/protected/

CreateRequest : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main unparsed_uri=(null)

QuickHandler : lookup_uri=1 server=scuzzy.ben.algroup.co.uk:9001[79410]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main
unparsed_uri=/protected/index.html

MergeDir : pBase: dir=(none)+(none) tag=MainDir+H1Main pNew: dir=/protected
tag=H1ProtectedLocation

Translate : uri=/protected/index.html server=scuzzy.ben.
algroup.co.uk:9001[79410] tag=MainServer+H1 dir=(none)+(none)+/
protected tag=MainDir+H1Main+H1ProtectedLocation unparsed_uri=/
protected/index.html

MapToStorage : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main unparsed_uri=/protected/
index.html

MergeDir : pBase: dir=(none)+(none) tag=MainDir+H1Main pNew:
dir=/home/ben/www5/docs/protected/ tag=H1ProtectedDirectory

MergeDir : pBase: dir=(none)+(none)+/home/ben/www5/docs/protected/
tag=MainDir+H1Main+H1ProtectedDirectory pNew: dir=/protected
tag=H1ProtectedLocation

CheckAccess : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1
dir=(none)+(none)+/home/ben/www5/docs/protected/+/protected
tag=MainDir+H1Main+H1ProtectedDirectory+H1ProtectedLocation
unparsed_uri=/protected/index.html

Fixups : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1
dir=(none)+(none)+/home/ben/www5/docs/protected/+/protected
tag=MainDir+H1Main+H1ProtectedDirectory+H1ProtectedLocation
unparsed_uri=/protected/index.html

Le cheminement normal reprend alors :

Logger : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main unparsed_uri=/

Et, enfin, une requête est créée pour anticiper la prochaine requête sur la même connexion :

CreateRequest : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1 dir=(no per-dir config) tag=(no per-dir config) unparsed_uri=(null)

C’est maintenant fini pour la version 2.0.

Plutôt que de faire durer en longueur, voici la requête la plus compliquée que nous pouvons faire : http://host:9001/protected/.reveal :

CreateConnection : server=scuzzy.ben.algroup.co.uk:0[84997]
tag=MainServer conn_id=0 [2.0]

PreConnection : keepalive=0 double_reverse=0 [2.0]

ProcessConnection : keepalive=0 double_reverse=0 [2.0]

CreateRequest : server=scuzzy.ben.algroup.co.uk:9001[84997] tag=MainServer+H1
dir=(no per-dir config) tag=(no per-dir config)
unparsed_uri=(null) [2.0]

PostReadReq : method=GET uri=/protected/.reveal protocol=HTTP/1.0
server=freeby.ben.algroup.co.uk:9001[23288] tag=MainServer+H1
dir=(none)+(none) tag=MainDir+H1Main

QuickHandler : lookup_uri=0 server=scuzzy.ben.algroup.co.uk:9001[84997]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main
unparsed_uri=/protected/.reveal [2.0]

Après l’étape post_read_request, une fusion s’effectue sur la base de l’emplacement (1.3) :

MergeDir : pBase: dir=(none)+(none) tag=MainDir+H1Main pNew: dir=/.reveal
tag=Revealer MergeDir : pBase: dir=(none)+(none)+/.reveal
tag=MainDir+H1Main+Revealer pNew: dir=/protected
tag=H1ProtectedLocation

C’est la même chose en 2.0, mais dans un ordre différent :

MergeDir : pBase: dir=/.reveal tag=Revealer pNew:
dir=/protected tag=H1ProtectedLocation

MergeDir : pBase: dir=(none)+(none) tag=MainDir+H1Main pNew:
dir=/.reveal+/protected tag=Revealer+H1ProtectedLocation

Cela illustre, bien sûr, la nécessité de s’assurer que les fonctions de fusion de serveurs et de répertoire fonctionnent bien malgré les modifications d’ordonnancement. Vous remarquerez que le résultat final de ces deux ordonnancements différents est, en fait, identique.

L’URL est ensuite traduite en nom de fichier, à l’aide de la nouvelle configuration de répertoires fusionnée :

Translate : uri=/protected/.reveal server=freeby.ben.algroup.co.uk:9001
[23288] tag=MainServer+H1 dir=(none)+(none)+/.reveal+/protected
tag=MainDir+H1Main+Revealer+H1ProtectedLocation

MapToStorage : server=scuzzy.ben.algroup.co.uk:9001[84997]
tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main
unparsed_uri=/protected/.reveal [2.0]

Maintenant que l’on connaît le nom de fichier, on peut fusionner un peu plus. Vous remarquerez que, cette fois-ci, la section marquée H1ProtectedDirectory est également ajoutée :

MergeDir : pBase: dir=(none)+(none) tag=MainDir+H1Main pNew:
dir=/home/ ben/www/APACHE3/docs/protected
tag=H1ProtectedDirectory

MergeDir : pBase: dir=(none)+(none)+/home/ben/www/APACHE3/docs/protected
tag=MainDir+H1Main+H1ProtectedDirectory pNew: dir=/.reveal
tag=Revealer [1.3]

MergeDir : pBase: dir=(none)+(none)+/home/ben/www/APACHE3/docs/
protected+/.reveal tag=MainDir+H1Main+H1ProtectedDirectory+
Revealer pNew: dir=/ protected tag=H1ProtectedLocation [1.3]

MergeDir : pBase: dir=(none)+(none)+/home/ben/www5/docs/protected/
tag=MainDir+H1Main+H1ProtectedDirectory pNew: dir=/.reveal+/
protected tag=Revealer+H1ProtectedLocation [2.0]

Remarquez que la version 2.0 réutilise astucieusement une fusion antérieure et effectue ce travail en gagnant une étape.

Enfin, la requête se poursuit comme d’habitude :

HeaderParser : server=freeby.ben.algroup.co.uk:9001[23288] tag=MainServer+H1
dir=(none)+(none)+/home/ben/www/APACHE3/docs/protected+/
.reveal+/ protected tag=MainDir+H1Main+H1ProtectedDirectory+
Revealer+H1ProtectedLocation

CheckAccess : server=freeby.ben.algroup.co.uk:9001[23288] tag=MainServer+H1
dir=(none)+(none)+/home/ben/www/APACHE3/docs/protected+/
.reveal+/ protected tag=MainDir+H1Main+H1ProtectedDirectory+
Revealer+H1ProtectedLocation

TypeChecker : server=freeby.ben.algroup.co.uk:9001[23288] tag=MainServer+H1
dir=(none)+(none)+/home/ben/www/APACHE3/docs/protected+/
.reveal+/ protected tag=MainDir+H1Main+H1ProtectedDirectory+
Revealer+H1ProtectedLocation

Fixups : server=freeby.ben.algroup.co.uk:9001[23288] tag=MainServer+H1
dir=(none)+(none)+/home/ben/www/APACHE3/docs/protected+/
.reveal+/ protected tag=MainDir+H1Main+H1ProtectedDirectory+
Revealer+H1ProtectedLocation

InsertFilter : server=scuzzy.ben.algroup.co.uk:9001[84997] tag=MainServer+H1
dir=(none)+(none)+/home/ben/www5/docs/protected/+/.reveal+/
protected tag=MainDir+H1Main+H1ProtectedDirectory+Revealer+
H1ProtectedLocation unparsed_uri=/protected/.reveal [2.0]

Logger : server=freeby.ben.algroup.co.uk:9001[23288] tag=MainServer+H1
dir=(none)+(none)+/home/ben/www/APACHE3/docs/protected+/
.reveal+/ protected tag=MainDir+H1Main+H1ProtectedDirectory+
Revealer+H1ProtectedLocation

CreateRequest : server=scuzzy.ben.algroup.co.uk:9001[84997] tag=MainServer+H1
dir=(no per-dir config) tag=(no per-dir config)
unparsed_uri=(null) [2.0]

Et voilà. Bien que les fusions de répertoires, d’emplacements, de fichiers, etc. soient assez complexes, Apache s’occupe de tout à votre place et vous fournit une configuration de serveur et de répertoire unique sur laquelle vous pouvez fonder les décisions de votre code.

Apache La référence
titlepage.xhtml
APACHE-la-REF_split_000.htm
APACHE-la-REF_split_001.htm
APACHE-la-REF_split_002.htm
APACHE-la-REF_split_003.htm
APACHE-la-REF_split_004.htm
APACHE-la-REF_split_005.htm
APACHE-la-REF_split_006.htm
APACHE-la-REF_split_007.htm
APACHE-la-REF_split_008.htm
APACHE-la-REF_split_009.htm
APACHE-la-REF_split_010.htm
APACHE-la-REF_split_011.htm
APACHE-la-REF_split_012.htm
APACHE-la-REF_split_013.htm
APACHE-la-REF_split_014.htm
APACHE-la-REF_split_015.htm
APACHE-la-REF_split_016.htm
APACHE-la-REF_split_017.htm
APACHE-la-REF_split_018.htm
APACHE-la-REF_split_019.htm
APACHE-la-REF_split_020.htm
APACHE-la-REF_split_021.htm
APACHE-la-REF_split_022.htm
APACHE-la-REF_split_023.htm
APACHE-la-REF_split_024.htm
APACHE-la-REF_split_025.htm
APACHE-la-REF_split_026.htm
APACHE-la-REF_split_027.htm
APACHE-la-REF_split_028.htm
APACHE-la-REF_split_029.htm
APACHE-la-REF_split_030.htm
APACHE-la-REF_split_031.htm
APACHE-la-REF_split_032.htm
APACHE-la-REF_split_033.htm
APACHE-la-REF_split_034.htm
APACHE-la-REF_split_035.htm
APACHE-la-REF_split_036.htm
APACHE-la-REF_split_037.htm
APACHE-la-REF_split_038.htm
APACHE-la-REF_split_039.htm
APACHE-la-REF_split_040.htm
APACHE-la-REF_split_041.htm
APACHE-la-REF_split_042.htm
APACHE-la-REF_split_043.htm
APACHE-la-REF_split_044.htm
APACHE-la-REF_split_045.htm
APACHE-la-REF_split_046.htm
APACHE-la-REF_split_047.htm
APACHE-la-REF_split_048.htm
APACHE-la-REF_split_049.htm
APACHE-la-REF_split_050.htm
APACHE-la-REF_split_051.htm
APACHE-la-REF_split_052.htm
APACHE-la-REF_split_053.htm
APACHE-la-REF_split_054.htm
APACHE-la-REF_split_055.htm
APACHE-la-REF_split_056.htm
APACHE-la-REF_split_057.htm
APACHE-la-REF_split_058.htm
APACHE-la-REF_split_059.htm
APACHE-la-REF_split_060.htm
APACHE-la-REF_split_061.htm
APACHE-la-REF_split_062.htm
APACHE-la-REF_split_063.htm
APACHE-la-REF_split_064.htm
APACHE-la-REF_split_065.htm
APACHE-la-REF_split_066.htm
APACHE-la-REF_split_067.htm
APACHE-la-REF_split_068.htm
APACHE-la-REF_split_069.htm
APACHE-la-REF_split_070.htm
APACHE-la-REF_split_071.htm
APACHE-la-REF_split_072.htm
APACHE-la-REF_split_073.htm
APACHE-la-REF_split_074.htm
APACHE-la-REF_split_075.htm
APACHE-la-REF_split_076.htm
APACHE-la-REF_split_077.htm
APACHE-la-REF_split_078.htm
APACHE-la-REF_split_079.htm
APACHE-la-REF_split_080.htm
APACHE-la-REF_split_081.htm
APACHE-la-REF_split_082.htm
APACHE-la-REF_split_083.htm
APACHE-la-REF_split_084.htm
APACHE-la-REF_split_085.htm
APACHE-la-REF_split_086.htm
APACHE-la-REF_split_087.htm
APACHE-la-REF_split_088.htm
APACHE-la-REF_split_089.htm
APACHE-la-REF_split_090.htm
APACHE-la-REF_split_091.htm
APACHE-la-REF_split_092.htm
APACHE-la-REF_split_093.htm
APACHE-la-REF_split_094.htm
APACHE-la-REF_split_095.htm
APACHE-la-REF_split_096.htm
APACHE-la-REF_split_097.htm
APACHE-la-REF_split_098.htm
APACHE-la-REF_split_099.htm
APACHE-la-REF_split_100.htm
APACHE-la-REF_split_101.htm
APACHE-la-REF_split_102.htm
APACHE-la-REF_split_103.htm
APACHE-la-REF_split_104.htm
APACHE-la-REF_split_105.htm
APACHE-la-REF_split_106.htm
APACHE-la-REF_split_107.htm
APACHE-la-REF_split_108.htm
APACHE-la-REF_split_109.htm
APACHE-la-REF_split_110.htm
APACHE-la-REF_split_111.htm
APACHE-la-REF_split_112.htm
APACHE-la-REF_split_113.htm
APACHE-la-REF_split_114.htm
APACHE-la-REF_split_115.htm
APACHE-la-REF_split_116.htm
APACHE-la-REF_split_117.htm
APACHE-la-REF_split_118.htm
APACHE-la-REF_split_119.htm
APACHE-la-REF_split_120.htm
APACHE-la-REF_split_121.htm
APACHE-la-REF_split_122.htm
APACHE-la-REF_split_123.htm
APACHE-la-REF_split_124.htm
APACHE-la-REF_split_125.htm
APACHE-la-REF_split_126.htm
APACHE-la-REF_split_127.htm
APACHE-la-REF_split_128.htm
APACHE-la-REF_split_129.htm
APACHE-la-REF_split_130.htm
APACHE-la-REF_split_131.htm
APACHE-la-REF_split_132.htm
APACHE-la-REF_split_133.htm
APACHE-la-REF_split_134.htm
APACHE-la-REF_split_135.htm
APACHE-la-REF_split_136.htm
APACHE-la-REF_split_137.htm
APACHE-la-REF_split_138.htm
APACHE-la-REF_split_139.htm
APACHE-la-REF_split_140.htm
APACHE-la-REF_split_141.htm
APACHE-la-REF_split_142.htm
APACHE-la-REF_split_143.htm
APACHE-la-REF_split_144.htm
APACHE-la-REF_split_145.htm
APACHE-la-REF_split_146.htm
APACHE-la-REF_split_147.htm
APACHE-la-REF_split_148.htm
APACHE-la-REF_split_149.htm
APACHE-la-REF_split_150.htm
APACHE-la-REF_split_151.htm
APACHE-la-REF_split_152.htm
APACHE-la-REF_split_153.htm
APACHE-la-REF_split_154.htm
APACHE-la-REF_split_155.htm
APACHE-la-REF_split_156.htm
APACHE-la-REF_split_157.htm
APACHE-la-REF_split_158.htm
APACHE-la-REF_split_159.htm
APACHE-la-REF_split_160.htm
APACHE-la-REF_split_161.htm
APACHE-la-REF_split_162.htm
APACHE-la-REF_split_163.htm
APACHE-la-REF_split_164.htm
APACHE-la-REF_split_165.htm
APACHE-la-REF_split_166.htm
APACHE-la-REF_split_167.htm
APACHE-la-REF_split_168.htm
APACHE-la-REF_split_169.htm
APACHE-la-REF_split_170.htm
APACHE-la-REF_split_171.htm
APACHE-la-REF_split_172.htm
APACHE-la-REF_split_173.htm
APACHE-la-REF_split_174.htm