To illustrate mod_reveal.c in use, we used the following configuration:
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>
Note that the <Directory>
and
<Location>
sections in the first virtual
host actually refer to the same place. This is to illustrate the
order in which the sections are combined. Also note that the
<LocationMatch>
section
doesn’t have to correspond to a real file; looking
at any location that ends with .reveal will
invoke mod_reveal.c ’s handler.
Starting the server produces this on the screen:
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
Notice that in 2.0, the pre_config
hook actually
comes slightly after configuration has started!
Notice that the <Location>
and
<LocationMatch>
sections are treated as
directories as far as the code is concerned. At this point,
stderr
is switched to the error log, and the
following is logged:
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
At this point, the first-pass initialization is complete, and Apache destroys the configurations and starts again (this double initialization is required because directives may change things such as the location of the initialization files):[9]
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)
Now we’ve created all the server and directory sections, and the top-level server is merged with the virtual hosts:
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
Now the init
functions are called (which rename
the servers now that their “real”
names are known):
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 logs its startup message:
[Sun Jul 12 13:08:01 1998] [notice] Apache/1.3.1-dev (Unix) Reveal/0.0 configured — resuming normal operations
Child
init
s are called:
Child Init : pid=23287 Child Init : pid=23288 Child Init : pid=23289 Child Init : pid=23290 Child Init : pid=23291
And Apache is ready to start handling requests. First, we request http://host: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
Because / is a directory, Apache attempts to use /index.html instead (in this case, it didn’t exist, but Apache still goes through the motions):
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
At this point, 1.3 and 2.0 diverge fairly radically. In 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
Pretty straightforward, but note that the configurations used are the
merge of the main server’s and the first virtual
host’s. Also notice the Child
init
at the end: this is because Apache decided
the load warranted starting another child to handle it.
But 2.0 is rather more complex:
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=/
Up to this point, we’re checking for /index.html and then continuing with /. From here, we get lots of extra stuff caused by mod_autoindex using internal requests to construct the URLs for the index page:
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+H1Protected Directory 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+H1Protected Directory 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
And now normal programming is resumed:
Logger : server=scuzzy.ben.algroup.co.uk:9001[79410] tag=MainServer+H1 dir=(none)+(none) tag=MainDir+H1Main unparsed_uri=/
And finally, a request is created in anticipation of the next request on the same connection:
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)
At this point, 2.0 is finished.
Rather than go on at length, here’s the most complicated request we can make: 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]
After the post_read_request
phase, some merging is
done on the basis of location (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
Essentially the same thing happens in 2.0, but in a different order:
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
Of course, this illustrates the need to make sure your directory and server mergers behave sensibly despite ordering changes. Note that the end product of these two different ordering is, in fact, identical.
Then the URL is translated into a filename, using the newly merged directory configuration:
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]
Now that the filename is known, even more merging can be done. Notice
that this time the section tagged as
H1ProtectedDirectory
is pulled in, too:
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]
Note that 2.0 cunningly reuses an earlier merge and does the job in one less step.
And finally the request proceeds as usual:
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]
And there we have it. Although the merging of directories, locations, files, and so on gets rather hairy, Apache deals with it all for you, presenting you with a single server and directory configuration on which to base your code’s decisions.
[9] You could argue that this procedure could lead to an infinite sequence of reinitializations. Well, in theory, it could, but in real life, Apache initializes twice, and that is that.