# QP

QP is a package for defining and running multiple web applications based on Durus for persistence, standard persistent Session and User classes, easy interactive database sessions, qpy for assembling html, and forms and path traversal. QP makes it easier than ever to use these tools together.

QP includes a http/scgi server that dispatches requests to a pool of long-running single-threaded worker processes. With QP your applications can

1. use the QP http service directly,
2. use the QP http service through a proxy,
3. use the QP scgi service through Apache+mod_scgi or lighttpd,
4. use the QP scgi service through CGI, using the cgi2scgi adapter (DurusWorks/scgi/cgi2scgi.c) and any cgi-capable web server.

QP includes a site-management capability. One command line utility (named "qp") is used for controlling all of the servers for multiple sites. Run `qp --help` to see the options available for the `qp` command.

## Using QP

To define a new site named, for example, `hello`, start with a copy of the `proto` site: `cp -r /www/trunk/DurusWorks/proto /www/trunk/hello ln -s /www/trunk/hello/lib /www/pythonlib/hello ln -s /www/trunk/hello/site /www/qp_sites/hello` Edit `/www/trunk/hello/lib/ui/slash.qpy` to configure the service addresses. Edit your apache configuration to provide virtual hosts that connect to the correct port for the SCGI server. Edit `/www/trunk/hello/site/slash.py` and change the import to this: `from hello.ui.slash import SitePublisher, SiteDirectory` Use the `qp` command to check that the `hello` site runs. Now you can add your customizations to `/www/trunk/hello/lib` and use the `qp` command to stop and start the site as needed to check your changes.

The customization options and in particular, the usage of the SiteDirectory, SitePublisher, and Form classes are beyond the scope of this document. To learn more, please study the proto demo and the QP source code.

The `SitePublisher` class should be a subclass of `qp.pub.publish.Publisher`, with a `configuration` class attribute identifying addresses for the servers you want to run.

Note that python will find your site packages as a subpackages of `qp.sites`, so the slash module of a site named `hello`, for example, can be imported in python as `qp.sites.hello.slash`.

The `SiteDirectory` class should be a subclass of `qp.fill.directory.Directory` that defines your site's content.

## The Modules of QP

Here we will summarize the roles of some of the modules in the QP package.

qp.fill.css
  This module contains some utilities for generating css.
qp.fill.form
  This module defines the `Form` class, which provides a framework for rendering HTML forms and dealing with submitted forms.
qp.fill.widget
  This module defines a variety of `Widget` classes for use by the `Form` class. There are different widgets for different kinds of form inputs.
qp.fill.directory
  This module defines `Directory`. We use instances of this class to define the URL space of every application. Every QP site must define a `SiteDirectory` class that is a subclass of `Directory`. The `SiteDirectory` class defines the entry point for traversing the URL path.
qp.fill.durus_directory
  This module provides `DurusDirectory`, a very specialized subclass of `Directory` used for browsing directly into a Durus database. This is useful for learning about the database structure.
qp.fill.html
  This module defines short functions for generating common HTML structures.
qp.fill.static
  This module provides `StaticFile` and `StaticDirectory`, which allow applications to deliver static content.
qp.http.request
  Provides the `HTTPRequest` class.
qp.http.response
  Provides the `HTTPResponse` class.
qp.hub.dispatcher
  This provides the server dispatcher class used by QP. The dispatcher receives connections and passes them off to a pool of long-running child processes.
qp.hub.passfd
  This module, implemented as a C-extension module, provides functions for transmitting file descriptors using a socket. This is used by QP's SCGI server.
qp.hub.web
  This provides QP's handlers for SCGI and HTTP protocols.
qp.lib.delegation
  This module provides some functions that provide a compact way to say define methods that delegate to other instances.
qp.lib.keep
  A common requirement for a Durus database is to maintain a collection of uniquely identified instances of a given type. This module provides the `Keep` class that makes it easy to get this job done.
qp.lib.profiler
  This module provides `Profile`, a class that can be used to test the QP request/response machinery directly, without involving any HTTP transmissions.
qp.lib.site
  This module defines `Site`, the class that provides the API that QP uses for managing multiple sites.
qp.lib.spec
  This module provides a pattern of defining `spec`s, which are callables that are used to verify an argument's type or other qualities. We use the `spec` pattern to declare and verify the attributes of nearly all instances in the database.
qp.lib.tz
  This module provides a way to define time zones for use with Python's datetime class. The method used here provides timezones that are actually Python classes, so they act as singleton instances.
qp.lib.util
  This module provides a variety of utilities that did not seem to fit elsewhere.
qp.mail.rfc822_mailbox
  This module provides some tools for dealing with email addresses and headers.
qp.mail.send
  This module provides a `sendmail()` function and an `Email` class that can be used for constructing and sending email.
qp.pub.common
  This module provides a set of convenient accessor functions that are used very frequently in QP applications. These functions provide a shorter way to call some methods of the `SitePublisher` and other instances it references.
qp.pub.hit
  This defines the `Hit` class. An instance of `Hit` has references to the current `HTTPRequest` and `HTTPResponse` instances.
qp.pub.publish
  The `Publisher` base class is defined in this module. Every QP site must define a `SitePublisher` class that is a subclass of `Publisher`.
qp.pub.session
  The standard `Session` class is defined here.
qp.pub.user
  This module provides the standard `User` class. It also include the `Digester`, used behind the scenes to maintain information needed for authenticating users. The `TokenSet` is used by `User` to provide a way to prevent forms from being submitted more than once. This module also provides the `Permission` class, which stores sets of specific tokens signifying permissions that are granted.

## HTTPS

QP does not provide ssl service, but your QP applications can have https support by using

1. QP's scgi server along with a separate server that provides https and scgi (such as the standard, Apache + mod_scgi),
2. QP's http server along with an ssl-providing http proxy, or
3. QP's http server along with stunnel.

To use the stunnel method, just install stunnel (available from www.stunnel.org) and configure it to run in server mode and to accept connections on the public ('https_address') interface and forward them to the port on the local ('as_https_address') interface. The host and port of both of these interfaces must be identified in the SitePublisher's configuration dictionary.

## QP with lighttpd

The standard installation uses Apache, but the lighttpd HTTP server can be used similarly since it supports SCGI and SSL.

The following are the minimum `lighttpd.conf` customizations required to enable SCGI and set up a virtual host for http and https:: `server.modules = ("mod_access", "mod_scgi", "mod_accesslog") $HTTP["host"] == "www.example.com" { $SERVER["socket"] == "0:443" { ssl.engine = "enable" ssl.pemfile = "/www/ssl/server.pem" ssl.ca-file = "/www/ssl/server.crt" } scgi.server = ( "" => ( "localhost" => ( "host" => "127.0.0.1", "port" => 7003, "check-local" => "disable", # default disable-time is 60 seconds "disable-time" => 5 # seconds ) ) ) }`

## History

The QP package incorporates the work of the MEMS Exchange software developers going back to approximately late 2000. Other contributors include:
Michael Watkins
David Hess
Maas-Maarten Zeeman
Peter Wilkinson
Mario Ruggier

DurusWorks Documentation