Bluish Coder

Programming Languages, Martials Arts and Computers. The Weblog of Chris Double.


 

Note that this article relates to Factor 0.91 and is out of date for newer Factor versions

The Factor webserver can do virtual hosting. There is a 'vhosts' variable that holds a hashtable mapping the names of the virtual hosts to a hashtable holding the variables that that host can access.

A 'default' virtual host entry exists for any web request with a host that does not have an explicit entry.

Responders can be shared between virtual hosts and be available only from a specific one.

Serving Files

The following is a simple example of adding a virtual host:

vhosts get [
  "bluishcoder.co.nz" H{ } clone dup [ "/var/www/bluishcoder/" "doc-root" set ] bind swap set
  "double.co.nz" H{ } clone dup [ "/var/www/double/" "doc-root" set ] bind swap set
] bind

This creates a virtual host that will be used when a web request arrives for 'bluishcoder.co.nz'. Note that it must match exactly. So if you want 'www.bluishcoder.co.nz' you need to add another entry for it.

This virtual host gets its own document root. So all requests for the root responder of 'bluishcoder.co.nz' will come from files in '/var/www/bluishcoder/'.

A second virtual host is also added for 'double.co.nz' and it will serve files from '/var/www/double/'.

Responders

All virtual hosts have access to the global 'responders' variable. This means that all virtual hosts will automatically provide access along the path of '/responder/foo' where 'foo' is a globally installed responder.

It is possible to have a host have its own private set of responders. There's a bit of a trick to this. You can just add a responder from within the namespace for that vhost. This won't work for example:

vhosts get [
  "factor.bluishcoder.co.nz" H{ } clone dup [ 
    "foo-resources" [
      [
        "/var/www/resources/" "doc-root" set
        file-responder
      ] with-scope
    ] add-simple-responder
  ] bind swap set
] bind

This will actually create the 'foo-resources' responder in the global responder table and all virtual hosts provide access to it.

To prevent this you need to first shadow the global responder table from within the namespace and then add the new responder. You can copy the global table if you want to have access to all its responders, or create an empty one. This example creates a copy of the global responder table:

vhosts get [
  "factor.bluishcoder.co.nz" H{ } clone dup [ 
    responders get H{ } assoc-clone-like responders set
    "foo-resources" [
      [
         "/var/www/resources/" "doc-root" set
         file-responder
      ] with-scope
    ] add-simple-responder
  ] bind swap set
] bind

The relevant line is:

responders get H{ } assoc-clone-like responders set

This creates a copy of the existing responder table and will shadow the global responders table.

Creating Site Files

To make it easy to load sites when restarting the Factor instance I use the Factor module system. I create a 'sites' directory underneath the 'Factor/extras' directory. Underneath 'sites' I have subdirectories for the virtual hosts:

Factor/extras/sites/bluishcoder
             /sites/double

Each of these 'sites' has the main file contain code like the following:

USING: kernel http.server http.server.responders namespaces assocs ;
vhosts get [
  "bluishcoder.co.nz" H{ } clone dup [ 
  "/home/chris/www/bluishcoder.co.nz/" "doc-root" set 
] bind swap set 
  "www.bluishcoder.co.nz" H{ } clone dup [ 
    "/home/chris/www/bluishcoder.co.nz/" "doc-root" set 
  ] bind swap set 
] bind

From the factor instance I can then load this like a normal module:

USE: sites.bluishcoder

If I edit it to add new responders, etc I can reload it:

refresh-all
! or: "sites/bluishcoder" reload-vocab
Links