======== Overview ======== Introduction ============ Serf is a simple web server. It's a development tool to be used during the development of rich internet applications: it's not intended for deployment. A rich internet application is a web application in which most of the user interface is handled by Javascript in the browser, in a single-web page that provides interactivity. Typically this is done by building on existing Javascript libraries or frameworks. The application interacts with the server using Ajax. Ideally the server implements a restful web service so that client and server are decoupled. Serf offers a number of features: * serve up static files, both Javascript and CSS, but also files that can be used during testing such as ``*.json`` files. * URLs to these static files are unique as they contain a hash. this means that whenever you change the contents of a static file, the URL to that file changes automatically. This makes it possible to easily defeat browser caches during development, while still allowing infinite caching. * serf supports `hurry.resource`_, a system for distributing Javascript libraries as Python libraries. This makes it easy to create Javascript code that relies on other javascript code. .. _hurry.resource: http://pypi.python.org/pypi/hurry.resource How to run Serf =============== Serf installs itself as a command-line executable called ``serf``. It takes as an argument the dotted name of a Python package. This package should contain serf configuration. With the ``-p`` option the port number can also be indicated; it defaults to ``8080``. To serve up the Python package ``foo.bar``, write:: $ bin/serf foo.bar To serve up the Python package ``qux`` under port ``7000``, write:: $ bin/serf -p 7000 qux Configuring Serf ================ The primary way to configure Serf is to use ``hurry.resource``. To publish any static resources (javascript, CSS, images, HTML, etc) we need to declare a library:: import serf mylibrary = serf.Library('mylibrary', 'resources') In this example, `mylibrary`` is the name of the library, and ``resources`` is a path to a directory that contains the static resources involved. Note that these paths are relative from the same package that the module itself is defined in. When pointed to a package that contains this code, Serf will start to serve up the static resource ``/mylibrary``. Any actual resources however will be in hashed URLs, so that URLs to resources will look like this:: /mylibrary/618ab5135353a/foo.js Note that you *have* to use ``serf.Library`` for Serf to pick up the library automatically. Serf can also pick up ``resource.Library`` instances, but only when they're exposed using the special ``hurry.resource.libraries`` entry point as described in the `hurry.resource documentation `_. When preparing a library for general distribution you should get rid of the dependency on ``serf.Library`` and start using the entry point instead. Special defaulting rules ======================== A single-page rich client application is driven by a single HTML page, and typically the page we pick for this we name ``index.html``. When you go to ``/mylibrary`` by itself Serf will redirect you to ``/mylibrary//index.html`` automatically. To make the root URL work (``/``), create a library named ``index``, with a file ``index.html``. The root URL will automatically redirect to this file. Creating a resource inclusion ============================= We can now use ``hurry.resource`` to create a resource inclusion that we want to be included on a web page. Let's define a simple one for ``foo.js`` in ``mylibrary``:: from hurry import resource foo = resource.ResourceInclusion(mylibrary, 'foo.js') This defines that in the library ``mylibrary`` there is a file called ``foo.js`` that can now be automatically included. Resource inclusions can be more involved and mark dependencies themselves. For more information about that, see the `hurry.resource documentation `_. Making a HTML page include a resource inclusion =============================================== Now we need to express that a particular HTML page actually depends on this resource inclusion to work:: import serf dep = serf.Dependency(mylibrary, 'index.html', [foo]) Serf will now automatically include a reference to ``foo.js`` in the ``index.html`` web page in the ``mylibrary`` resource. So, when ``index.html`` is requested, the right resource (and all its dependencies) should be present. Pre-wrapped resource inclusions =============================== A number of Javascript libraries have been pre-packaged with ``hurry.resource``, so to use them all you have to do is make your package depend on them in ``setup.py`` and then you can import the resource inclusions from them and depend on them. Here is an incomplete listing:: * `hurry.jquery `_ * `hurry.jqueryui `_ * `hurry.yui `_ * `hurry.tinymce `_ Recognizing resource extensions =============================== By default Serf recognizes a number of file extensions (``.html``, ``.js``, ``.css``, `.json``, ``.png``, ``.jpg``, ``.gif``) and will serve them with the appropriate content type. Other extensions are served as ``text/plain`` by default. If you want to configure what content type should be served for a file extension, you can use ``Extension``:: foo = serf.Extension('foo', 'text/foo') Now all files with the extension ``.foo`` will be served with the ``text/foo`` content type.