Chandler Web Server
Thanks to the twisted framework, Chandler has an embedded webserver which can be activated via:
- Command line: -W (or --webserver)
- Environment variable: CHANDLERWEBSERVER=1888 ...or whatever port you choose
- Menu: Test | Activate built-in webserver
If you activate the webserver, by default it will listen to port 1888 (Raymond Chandler's birth year),
http://localhost:1888/ but you can specify a different port either via command line flag or via environment variable above.
The "document root" for the webserver is the parcels/osaf/app/webhome/ directory within Chandler; this path is configured within
parcels/osaf/app/__init.py__. In that same module you will see three twisted.web resource objects defined; each of these resources handle a specific URL path. For example, HTTP requests for
http://localhost:1888/photos/ are processed by the photos resource at
parcels/osaf/servlets/photo.py. The three pre-defined resources (or "servlets") are:
- /lobs -- a servlet which allows clients to request Lob attribute values containing data such as images (used by the photos servlet)
- /photos -- a servlet which finds all the Photo items in the repository and displays them; you can add photos to your repository either by using the Flickr importer (Collection menu | New Flickr Collection...) or by importing images from disk (File menu | Import/Export | Import an image from disk)
- /repo -- a tool for developers to inspect the repository; there is also a script included within Chandler that his invoked with the F4 function key -- pressing F4 will open up your web browser and display the currently selected Chandler item
Password Protecting Servlets
By default, the servlets are not password protected. You can enable passwords on a per-servlet basis by adding a
pim.Principal item to your personal parcel (details about personal parcels are at
ParcelLoading), and creating an Access Control List:
from application import schema
from repository.item import Access
from osaf import webserver, pim
def installParcel(parcel, oldVersion=None):
app_ns = schema.ns('osaf.app', parcel)
webserver_ns = schema.ns('osaf.webserver', parcel)
morgen = pim.Principal.update(parcel, 'principalMorgen',
login='morgen',
password='a_secret',
memberOf=[webserver_ns.public]
)
acl = Access.ACL( )
acl.append(Access.ACE(morgen.itsUUID, Access.Permission.READ))
app_ns.repoResource.setACL(acl)
Third-Party Servlets
To use these servlets, check them out and place them into a directory along your PARCELPATH
- /hello -- a "hello world" servlet showing a basic implementation
- /inbound -- an RSS/Feed servlet which displays unread FeedItems
- Author: Morgen Sagen
- Available via SVN from http://svn.osafoundation.org/sandbox/morgen/parcels/inbound
- You can add Feed Channels either by using the 'Collection menu | New Feed Channel' and entering a URL, or you can put a file named inbound.txt containing a URL per line into your Chandler profile directory; the location of your profile directory is platform-dependent (Linux: ~/.chandler, OS X: ~/Library/Application Support/Open Source Applications Foundation/Chandler, Windows: C:\Documents and Settings[Username]\Application Data\Open Source Applications Foundation\Chandler)
- /books -- an library catalog manager I'm working on for my sister-in-law's preschool
Developing a Servlet
A servlet is comprised of a Python class which implements HTTP request handing, and a Chandler item which associates that servlet class to the webserver object. The class you implement should be a subclass of
osaf.webserver.AuthenticatedResource which buys you two features: you can password protect the servlet, and the servlet will automatically get its own private repository view. Your servlet class is a descendant of twisted.web.resource, and therefore you implement render_GET(self, request) and return an HTML string or whatever is appropriate for your servlet.
HTTP request arguments are available in
request.args, while the URL path is in
request.postpath.
You can set custom HTTP response headers using request.setHeader( ). For example:
request.setHeader('Content-Type', mimeType)
request.setHeader('Content-Length', len(data))
The servlet's private repository view is available as
self.myView.
To associate a servlet with the Chandler webserver, the servlet's parcel should define an
osaf.webserver.Resource item with the following attributes assigned:
- location -- the URL path to associate with this servlet. For example, if you want your servlet to handle all requests under /foo set location to "foo"
- resourceClass -- the Python class implementing your servlet; use application.schema.importString( )
- server -- the webserver item to associate this servlet to; technically there could be multiple webserver instances, but we ship with one: app.mainServer
Please see the
"hello world servlet" example, also available via SVN at
http://svn.osafoundation.org/sandbox/morgen/parcels/helloservlet