# Configuring and Using the Twisted.Web Server

## Installation

To install the Twisted.Web server, you'll need to have installed Twisted.

Twisted servers, like the web server, do not have configuration files. Instead, you instantiate the server and store it into a 'Pickle' file, `web.tap`. This file will then be loaded by the Twisted Daemon.

    % mktap web --path /path/to/web/content

If you just want to serve content from your own home directory, the following will do:

    % mktap web --path ~/public_html/

Some other configuration options are available as well:

- `--port`: Specify the port for the web server to listen on. This defaults to 8080.
- `--logfile`: Specify the path to the log file.

The full set of options that are available can be seen with:

    % mktap web --help

## Using Twisted.Web

### Stopping and Starting the Server

Once you've created your `web.tap` file and done any configuration, you can start the server:

    % twistd -f web.tap

You can stop the server at any time by going back to the directory you started it in and running the command:

    % kill `cat twistd.pid`

### Serving Flat HTML

Twisted.Web serves flat HTML files just as it does any other flat file.

### Resource Scripts

A Resource script is a Python file ending with the extension `.rpy`, which is required to create an instance of a (subclass of a) `twisted.web.resource.Resource`.

Resource scripts have 3 special variables:

- `__file__`: The name of the .rpy file, including the full path. This variable is automatically defined and present within the namespace.
- `registry`: An object of class `twisted.web.static.Registry`. It can be used to access and set persistent data keyed by a class.
- `resource`: The variable which must be defined by the script and set to the resource instance that will be used to render the page.

A very simple Resource Script might look like:

    from twisted.web import resource
    class MyGreatResource(resource.Resource):
        def render(self, request):
            return "&lt;html&gt;foo&lt;/html&gt;"

    resource = MyGreatResource()

A slightly more complicated resource script, which accesses some persistent data, might look like:

    from twisted.web import resource
    from SillyWeb import Counter

    counter = registry.getComponent(Counter)
    if not counter:
       registry.setComponent(Counter, Counter())
    counter = registry.getComponent(Counter)

    class MyResource(resource.Resource):
        def render(self, request):
            counter.increment()
            return "you are visitor %d" % counter.getValue()

    resource = MyResource()

This is assuming you have the `SillyWeb.Counter` module, implemented something like the following:

    class Counter:

        def __init__(self):
            self.value = 0

        def increment(self):
            self.value += 1

        def getValue(self):
            return self.value

### DOM Templates

The DOM Templates system is a system for handling templated content. See its documentation for more details.

### Spreadable Web Servers

One of the most interesting applications of Twisted.Web is the distributed webserver; multiple servers can all answer requests on the same port, using the `twisted.spread` package for spreadable computing. In two different directories, run the commands:

    % mktap web --user
    % mktap web --personal [other options, if you desire]

Both of these create a `web.tap`; you need to run both at the same time. Once you have, go to `http://localhost:8080/your_username.twistd/` -- you will see the front page from the server you created with the `--personal` option. What's happening here is that the request you've sent is being relayed from the central (User) server to your own (Personal) server, over a PB connection. This technique can be highly useful for small community sites; using the code that makes this demo work, you can connect one HTTP port to multiple resources running with different permissions on the same machine, on different local machines, or even over the internet to a remote site.

### Serving PHP/Perl/CGI

Everything related to CGI is located in the `twisted.web.twcgi`, and it's here you'll find the classes that you need to subclass in order to support the language of your (or somebody elses) taste. You'll also need to create your own kind of resource if you are using a non-unix operatingsystem (such as Windows), or if the default resources has wrong pathnames to the parsers.

The following snippet is a .rpy that serves perl-files. Look at `twisted.web.twcgi` for more examples regarding twisted.web and CGI.

    from twisted.web import static, twcgi

    class PerlScript(twcgi.FilteredScript):
        filter = '/usr/bin/perl' # Points to the perl parser

    resource = static.File("/perlsite") # Points to the perl website
    resource.processors = {".pl": PerlScript} # Files that end with .pl will be
                                              # processed by PerlScript
    resource.indexNames = ['index.pl']

### Using VHostMonster

It is common to use one server (for example, Apache) on a site with multiple names which then uses reverse proxy (in Apache, via `mod_proxy`) to different internal web servers, possibly on different machines. However, naive configuration causes miscommunication: the internal server firmly believes it is running on internal-name:port, and will generate URLs to that effect, which will be completely wrong when received by the client.

While Apache has the ProxyPassReverse directive, it is really a hack and is nowhere near comprehensive enough. Instead, the recommended practice in case the internal web server is Twisted.Web is to use VHostMonster.

From the Twisted side, using VHostMonster is easy: just drop a file named (for example) `vhost.rpy` containing the following:

    from twisted.web import vhost
    resource = vhost.VHostMonsterResource()

Of course, an equivalent `.trp` can also be used. Make sure the web server is configured with the correct processors for the `rpy` or `trp` extensions (the web server `mktap web --path` generates by default is so configured).

From the Apache side, instead of using the following ProxyPass directive:

    <VirtualHost ip-addr>
    ProxyPass / http://localhost:8538/
    ServerName example.com
    </VirtualHost>

Use the following directive:

    <VirtualHost ip-addr>
    ProxyPass / http://localhost:8538/vhost.rpy/http/example.com:80/
    ServerName example.com
    </VirtualHost>

Here is an example for Twisted.Web's reverse proxy:

    from twisted.internet import app
    from twisted.web import proxy, server, vhost
    vhostName = 'example.com'
    reverseProxy = proxy.ReverseProxyResource('internal', 8538,
                                              '/vhost.rpy/http/'+vhostName+'/')
    root = vhost.NamedVirtualHost()
    root.addHost(vhostName, reverseProxy)
    site = server.Site(root)
    application = app.Application('web-proxy')
    application.listenTCP(80, site)

## Rewriting URLs

Sometimes it is convenient to modify the content of the `twisted.web.server.Request` object before passing it on. Because this is most often used to rewrite either the URL, the similarity to Apache's `mod_rewrite` has inspired the `twisted.web.rewrite` module. Using this module is done via wrapping a resource with a `twisted.web.rewrite.RewriterResource` which then has rewrite rules. Rewrite rules are functions which accept a request object, and possible modify it. After all rewrite rules run, the child resolution chain continues as if the wrapped resource, rather than the `RewriterResource`, was the child.

Here is an example, using the only rule currently supplied by Twisted itself:

    default_root = rewrite.RewriterResource(default, rewrite.tildeToUsers)

This causes the URL `/~foo/bar.html` to be treated like `/users/foo/bar.html`. If done after setting default's `users` child to a `twisted.web.distrib.UserDirectory`, it gives a configuration similar to the classical configuration of web server, common since the first NCSA servers.

Index