Mass Virtual Hosting in Web Server 7
By elving on May 21, 2006
The new variable substitution functionality in Sun Java System Web Server 7 makes mass virtual hosting much simpler.
Both Sun Java System Web Server and Apache HTTP Server allow you to configure multiple websites on a single server instance. In Web Server, you can create a new virtual server using the <virtual-server> element. In Apache, you can create a new virtual host using the <VirtualHost> container. Unfortunately, both constructs are relatively heavy weight. At a minimum, they require the following every time you add or remove a website:
- Add/remove multiple configuration directives to/from the main server configuration file
- Reconfigure (Web Server) or, worse, restart (Apache) the server process
In ISP environments where there may be thousands — or even hundreds of thousands — of websites served by a single server instance, these can become significant drawbacks.
If you're deploying a large number of simple websites, you may wish to instead configure a single virtual server that can dynamically serve content for different websites. In Apache, you can do this using the mod_rewrite RewriteCond and RewriteRule directives in the httpd.conf configuration file. In Sun Java System Web Server 7, you can do this using the new parameter interpolation functionality that's built into the obj.conf configuration file.
Host-specific document roots using variables
At the most basic level, parameter interpolation means you can include variables in obj.conf parameters. For example, you can embed the
$urlhost variable in a parameter to set the document root based on the website the web browser requested:
NameTrans fn="document-root" root="/var/websites/
If you add the above directive to obj.conf, Web Server will return files from /var/websites/www.sun.com when a web browser requests www.sun.com and files from /var/websites/elving.com when a web browser requests elving.com.
Case-insensitivity with the lc expression function
Unfortunately, if a web browser requests wwW.suN.coM, the above directive instructs Web Server to look for /var/websites/wwW.suN.coM. That's probably not what you want. Fortunately, parameter interpolation also allows to embed expressions in parameters, and expressions can call the
lc() function to convert values to lowercase. Here's an example:
NameTrans fn="document-root" root="/var/websites/$(
Finishing touches with the <If> tag
For the really heavy lifting, we need to break out the <If> tag. Last week, I wrote about how the new <If> tag is useful for redirects. Well, it's also useful for mapping URLs to file system paths. For example, suppose www.sun.com, w3.sun.com, and sun.com should all map to the same directory. This is easily done with a regular expression and the <If> tag:
<If $urlhost =~ '\^(?i)(www\\.|w3\\.|)
([\^/\\\\]\*)$'> NameTrans fn="document-root" root="/var/websites/$(lc(
(?i) makes the regular expression case insensitive and
(www\\.|w3\\.|) indicates we want to separate out any leading
w3.. We use
([\^/\\\\]\*) instead of
(.\*) to guard against malicious users who might supply a bogus Host: header field that contains multiple path segments separated by slashes. The result of the regular expression match is stored in the variables
$2 contains the part we're interested in, the domain name minus any
With this magic in obj.conf, Web Server will return files from /var/websites/sun.com whenever a web browser requests www.sun.com, w3.sun.com, or sun.com.
There's still lots more that <If> can do. If you've got a web server configuration task you think <If> might be able to solve, by all means ask me about it here or head over to the Web Server forum to talk about it with others.
P.S. Did I mention that the Sun Java System Web Server 7 Technology Preview is free?