Virtual Hosting Services

Zope comes with two objects that help you do virtual hosting, SiteRoot and Virtual Host Monster. Virtual hosting is a way to serve many web sites with one Zope server.

SiteRoots are an artifact of an older generation of Zope virtual hosting services that are only retained in current Zope versions for backwards-compatibility purposes. They are not documented in this book because they are somewhat "dangerous" for new users, as they have the capability of temporarily "locking you out" of your Zope instance if you configure them improperly. Luckily, we have Virtual Host Monsters, which do everything that SiteRoots do and more without any of the dangerous side effects of SiteRoots. If you want to do virtual hosting in Zope, you should almost certainly be using a Virtual Host Monster.

Virtual Host Monster

Zope objects need to generate their own URLs from time to time. For instance, when a Zope object has its "absolute_url" method called, it needs to return a URL which is appropriate for itself. This URL typically contains a hostname, a port, and a path. In a "default" Zope installation, this hostname, port, and path is typically what you want. But when it comes time to serve multiple websites out of a single Zope instance, each with their own "top-level" domain name, or when it comes time to integrate a Zope Folder within an existing website using Apache or another webserver, the URLs that Zope objects generate need to change to suit your configuration.

A Virtual Host Monster's only job is to change the URLs which your Zope objects generate. This allows you to customize the URLs that are displayed within your Zope application, allowing an object to have a different URL when accessed in a different way. This is most typically useful, for example, when you wish to "publish" the contents of a single Zope Folder (e.g. '/FooFolder') as a URL that does not actually contain this Folder's name (e.g as the hostname 'http://www.foofolder.com/').

The Virtual Host Monster performs this job by intercepting and deciphering information passed to Zope within special path elements encoded in the URLs of requests which come in to Zope. If these special path elements are absent in the URLs of requests to the Zope server, the Virtual Host Monster does nothing. If they are present, however, the Virtual Host Monster deciphers the information passed in via these path elements and causes your Zope objects to generate a URL that is different from their "default" URL.

The Zope values which are effected by the presence of a Virtual Host Monster include REQUEST variables starting with URL or BASE (such as URL1, BASE2, URLPATH0), and the absolute_url() methods of objects.

Virtual Host Monster configuration can be complicated, because it requires that you rewrite URLs "on the way in" to Zope. In order for the special path elements to be introduced into the URL of the request sent to Zope, a front-end URL "rewriting" tool needs to be employed. Virtual Host Monster comes with a simple rewriting tool in the form of its Mappings view, or alternately you can use Apache or another webserver to rewrite URLs of requests destined to Zope for you.

Where to Put a Virtual Host Monster And What To Name It

A single Virtual Host Monster in your Zope root can handle all of your virtual hosting needs. It doesn't matter what id you give it, as long as nothing else in your site has the same id.

Special VHM Path Elements VirtualHostBase and VirtualHostRoot

A Virtual Host Monster doesn't do anything unless it sees one of the following special path elements in a URL:

VirtualHostBase
if a VirtualHostMonster "sees" this name in the incoming URL, it causes Zope objects to generate URLs with a potentially different protocol, a potentially different hostname, and a potentially different port number.
VirtualHostRoot
if a VirtualHostMonster "sees" this name in the incoming URL, it causes Zope objects to generate URLs which have a potentially different "path root"

VirtualHostBase

The VirtualHostBase declaration is typically found at the beginning of an incoming URL. A Virtual Host Monster will intercept two path elements following this name and will use them to compose a new protocol, hostname, and port number.

The two path elements which must follow a VirtualHostBase declaration are protocol and hostname:portnumber. They must be separated by a single slash. The colon and portnumber parts of the second element are optional, and if they don't exist, the Virtual Host Monster will not change the port number of Zope-generated URLs.

Examples:

           If a VHM is installed in the root folder, and a request comes in to           your Zope with the URL:             'http://zopeserver:8080/VirtualHostBase/http/www.buystuff.com'           URLs generated by Zope objects will start with           'http://buystuff.com:8080'.           If a VHM is installed in the root folder, and a request comes in to           your Zope with the URL:             'http://zopeserver:8080/VirtualHostBase/http/www.buystuff.com:80'           URLs generated by Zope objects will start with           'http://buystuff.com' (port 80 is the default port number           so it is left out).           If a VHM is installed in the root folder, and a request comes in to           your Zope with the URL:             'http://zopeserver:8080/VirtualHostBase/https/www.buystuff.com:443'           URLs generated by Zope objects will start with           'https://buystuff.com/'. (port 443 is the default https port number,           so it is left off.

 

One thing to note when reading the examples above is that if your Zope is running on a port number like 8080, and you want generated URLs to not include this port number and instead be served on the standard HTTP port (80), you must specifically include the default port 80 within the VirtualHostBase declaration, e.g. /VirtualHostBase/http/www.buystuff.com:80. If you don't specify the :80, your Zope's HTTP port number will be used (which is likely not what you want).

VirtualHostRoot

The VirtualHostRoot declaration is typically found near the end of an incoming URL. A Virtual Host Monster will gather up all path elements which precede and follow the VirtualHostRoot name, traverse the Zope object hierarchy with these elements, and publish the object it finds with the path rewritten to the path element(s) which follow(s) the VirtualHostRoot name.

This is easier to understand by example. For a URL /a/b/c/VirtualHostRoot/d, the Virtual Host Monster will traverse "a/b/c/d" and then generate a URL with path /d.

Examples:

           If a VHM is installed in the root folder, and a request comes in to           your Zope with the URL:             'http://zopeserver:8080/Folder/VirtualHostRoot/           The object 'Folder' will be traversed to and published,           URLs generated by Zope will start with           'http://zopeserver:8080/', and when they are visited, they           will be considered relative to 'Folder'.           If a VHM is installed in the root folder, and a request comes in to           your Zope with the URL:             'http://zopeserver:8080/HomeFolder/VirtualHostRoot/Chris           The object '/Folder/Chris' will be traversed to and           published, URLs generated by Zope will start with           'http://zopeserver:8080/Chris', and when they are visited,           they will be considered relative to '/HomeFolder/Chris'.

 

Using VirtualHostRoot and VirtualHostBase Together

The most common sort of virtual hosting setup is one in which you create a Folder in your Zope root for each domain that you want to serve. For instance the site http://www.buystuff.com is served from a Folder in the Zope root named /buystuff while the site http://www.mycause.org is served from a Folder in the Zope root named /mycause. In order to do this, you need to generate URLs that have both VirtualHostBase and VirtualHostRoot in them.

To access /mycause as http://www.mycause.org/, you would cause Zope to be visited via the following URL:

          /VirtualHostBase/http/www.mycause.org:80/mycause/VirtualHostRoot/

 

In the same Zope instance, to access /buystuff as http://www.buystuff.com/, you would cause Zope to be visited via the following URL:

          /VirtualHostBase/http/www.buystuff.com:80/buystuff/VirtualHostRoot/

 

Testing a Virtual Host Monster

Set up a Zope on your local machine that listens on HTTP port 8080 for incoming requests.

Visit the root folder, and select Virtual Host Monster from the Add list. Fill in the id on the add form as VHM and click Add.

Create a Folder in your Zope root named vhm_test. Within the newly-created vhm_test folder, create a DTML Method named index_html and enter the following into its body:

           <html>           <body>           <table border="1">             <tr>               <td>Absolute URL</td>               <td><dtml-var absolute_url></td>             </tr>             <tr>               <td>URL0</td>               <td><dtml-var URL0></td>             </tr>             <tr>               <td>URL1</td>               <td><dtml-var URL1></td>             </tr>           </table>           </body>           </html>

 

View the DTML Method by clicking on its View tab, and you will see something like the following:

          Absolute URL   http://localhost:8080/vhm_test           URL0           http://localhost:8080/vhm_test/index_html          URL1           http://localhost:8080/vhm_test 

 

Now visit the URL http://localhost:8080/vhm_test. You will be presented with something that looks almost exactly the same.

Now visit the URL http://localhost:8080/VirtualHostBase/http/zope.com:80/vhm_test. You will be presented with something that looks much like this:

        Absolute URL   http://zope.com/vhm_test         URL0           http://zope.com/vhm_test/index_html        URL1           http://zope.com/vhm_test

 

Note that the URLs that Zope is generating have changed. Instead of using localhost:8080 for the hostname and path, we've instructed Zope, through the use of a VirtualHostBase directive to use zope.com as the hostname. No port is shown because we've told Zope that we want to generate URLs with a port number of 80, which is the default http port.

Now visit the URL http://localhost:8080/VirtualHostBase/http/zope.com:80/vhm_test/VirtualHostRoot/. You will be presented with something that looks much like this:

        Absolute URL   http://zope.com        URL0           http://zope.com/index_html        URL1           http://zope.com

 

Note that we're now publishing the vhm_test folder as if it were the root folder of a domain named zope.com. We did this by appending a VirtualHostRoot directive to the incoming URL, which essentially says "traverse to the vhm_root folder as if it were the root of the site."

Arranging for Incoming URLs to be Rewritten

At this point, you're probably wondering just how in the world any of this helps you. You're certainly not going to ask people to use their browser to visit a URL like http://yourserver.com//VirtualHostBase/http/zope.com/vhm_test/VirtualHostRoot/ just so your Zope-generated URLs will be "right". That would defeat the purpose of virtual hosting entirely. The answer is: don't ask humans to do it, ask your computer to do it. There are two common (but mutually excusive) ways to accomplish this: via the VirtualHostMonster Mappings tab and via Apache "rewrite rules" (or your webserver's facility to do the same thing if you don't use Apache). Be warned: use either one of these facilities or the other but not both or very strange things may start to happen. We give examples of using both facilities below.

Virtual Host Monster Mappings Tab

Use the Virtual Host Monster's Mappings tab to cause your URLs to be rewritten if:

  • You run a "bare" Zope without a front-end webserver like Apache.
  • You have one or more folders in your Zope that you'd like to publish as "http://some.hostname.com/" instead of "http://hostname.com/a/folder".

The lines entered into the Mappings tab are in the form

The best way to explain how to use the Mappings tab is by example. Assuming you've added a Virtual Host Monster object in your root folder on a Zope running on localhost on port 8080, create an alias in your local system's hosts file (in /etc/hosts on UNIX and in c:\WINNT\system32\drivers\etc\hosts on Windows) that looks like this:

            127.0.0.1 www.example.com

 

This causes your local machine to contact itself when a hostname of wwww.example.com is encountered. For the sake of this example, we're going to want to contact Zope via the hostname www.example.com through a browser (also on your local host) and this makes it possible.

Then visit the VHM in the root folder and click on its Mappings tab. On a line by itself enter the following:

            www.example.com:8080/vhm_test

 

This will cause the vhm_test folder to be published when we visit http://www.example.com:8080. Visit http://www.example.com:8080. You will see:

            Absolute URL   http://www.example.com:8080            URL0           http://www.example.com:8080/index_html            URL1           http://www.example.com:8080

 

In the "real world" this means that you are "publishing" the vhm_test folder as http://'www.example.com:8080'.

You can match multiple subdomains by putting "." in front of the host name in the mapping rule. For example, ".buystuff.com" will match "my.buystuff.com", "zoom.buystuff.com", etc. If an exact match exists, it is used instead of a wildcard match.

Note that it is not possible to rewrite the port part (by default, '8080') of the URL this way. To change the port Zope is listening on, you will have to configure Zopes' start parameter or use Apache rewriting.

Apache Rewrite Rules

If you use Apache in front of Zope, instead of using the Mappings tab, you should use Apache's rewrite rule functionality to rewrite URLs in to Zope. The way this works is straightforward: Apache listens on its "normal" port, typically port 80. At the same time, Zope's web server (on the same host or on another host) listens on a different port (typically 8080). Apache accepts requests on its listening port. A virtual host declaration in Apache's configuration tells Apache to apply the contained directives to the specified virtual host.

Using Apache's rewrite rule functionality requires that the mod_rewrite and mod_proxy Apache modules be enabled. This can for instance be done by configuring Apache with the '--enable-modules="rewrite proxy"' flag during compile time or by loading the corresponding shared modules. If you are using the new Apache 2 series, you will also have to include the mod_proxy_http module. See the Apache documentation for details.

After you've got Apache configured with mod_rewrite and mod_proxy (and, depending on your Apache version, mod_proxy_http), you can start configuring Apache's config file and Zope for the following example. Assuming you've added a Virtual Host Monster object in your root folder on a Zope running on localhost on port 8080, create an alias in your local system's hosts file (in /etc/hosts on UNIX and in c:\WINNT\system32\drivers\etc\hosts on Windows) that looks like this:

            127.0.0.1 www.example.com

 

This causes your local machine to contact itself when a hostname of wwww.example.com is encountered. For the sake of this example, we're going to want to contact Zope via the hostname www.example.com through a browser (also on your local host) and this makes it possible.

Now, assuming you've got Apache running on port 80 and Zope running on port 8080 on your local machine, and assuming that you want to serve the folder named vhm_test in Zope as www.example.com and, add the following to your Apache's httpd.conf file and restart your Apache process:

            NameVirtualHost *            <VirtualHost *>            ServerName www.example.com            RewriteEngine On            RewriteRule ^/(.*) http://127.0.0.1:8080/VirtualHostBase/http/www.example.com:80/vhm_test/VirtualHostRoot/$1 [L,P]            </VirtualHost>

 

When you visit http://www.example.com in your browser, you will see:

            Absolute URL   http://www.example.com            URL0           http://www.example.com/index_html            URL1           http://www.example.com

 

This page is being served by Apache, but the results are coming from Zope. Requests come in to Apache with "normal" URLs (e.g. 'http://www.example.com'). The VirtualHost stanza in Apache's httpd.conf causes the request URL to be rewritten (e.g. to 'http://127.0.0.1:8080/VirtualHostBase/http/www.example.com:80/vhm_test/VirtualHostRoot/'). Apache then calls the rewritten URL, and returns the result.

See the Apache Documentation for more information on the subject of rewrite rules.

"Inside-Out" Virtual Hosting

Another use for virtual hosting is to make Zope appear to be part of a site controlled by another server. For example, Zope might only serve the contents of http://www.mycause.org/dynamic_stuff, while Apache or another webserver serves files via http://www.mycause.org/. To accomplish this, you want to add "dynamic_stuff" to the start of all Zope-generated URLs.

If you insert VirtualHostRoot, followed by one or more path elements that start with _vh_, then these elements will be ignored during traversal and then added (without the '_vh_') to the start of generated URLs. For instance, a request for "/a/VirtualHostRoot/_vh_z/" will traverse "a" and then generate URLs that start with /z.

In our example, you would have the main server send requests for http://www.mycause.org/dynamic_stuff/anything to Zope, rewritten as /VirtualHostRoot/_vh_dynamic_stuff/anything.