
Module root directory applicationsWHIFF applications always reside in a WHIFF directory and each WHIFF directory must be configured to find the applications it contains as well as any external resources needed by that directory. The directory may also be configured for a standard "look and feel" and for standard error handling behaviour.
Installing resources
Installing static resources
Standard resources
Distributed resources implementations
Directory __init__ files
Served directory content
Recognizing templates and files in a directory
Importing applications or other root directories into a directory
WHIFF directories can be configured in a number of ways, including
When a web server "hands" a request to WHIFF the primary
entry point that initially receives the request is a
module root application for a WHIFF directory. To create a module root
application, import a Python module corresponding to the
directory you want to serve and use the
resolver.moduleRootApplication
constructor to wrap the module into a root application.
The signature for the resolver.moduleRootApplication
constructor is as follows:
class moduleRootApplication(WsgiComponent):
"Make a module into a WSGI app which serves its content (subject to security restrictions)"
def __init__(self,
# the server relative URL prefix for the directory
root_path="",
# the module/directory to serve
root_module=None,
# the application to handle "not found" urls
on_not_found=default_not_found_app,
# middleware to use to wrap all applications (overridden via "no-filter")
filter_middleware=None,
# middleware to handle uncaught exceptions
exception_middleware=None,
# additional environment entries to insert for each request
environment=None,
# resource gateway object
resourceGateway=None,
):
root_path parameter tells the application how to parse
request URLs. The root_path must be a prefix of all URLs for incoming requests
-- if it is not the request will be refused as a security precaution.
Here is an example CGI script that constructs a root application for the
resumes tutorial.
#!/Library/Frameworks/Python.framework/Versions/Current/bin/python
import sys
import wsgiref.handlers
import whiff.resolver
from whiff.resources import sessionDirectory
# add the path to the directory containing the "resumes" root directory to the python path
sys.path.append("/Users/Aaron/whiff/doc")
import resumes
# create a WSGI application to serve the resume directory
application = whiff.resolver.moduleRootApplication("/cgi-bin/resumes.cgi", resumes)
# add HTTP session resource
sessions = sessionDirectory.directorySessionFinder("/tmp/sessions", timeout=60*60)
application.registerResourceFinder(prefix="session", finder=sessions)
# add user profile resource
profiles = sessionDirectory.directoryProfileFinder("/tmp/profiles")
application.registerResourceFinder(prefix="profile", finder=profiles)
# serve a CGI request using the directory
wsgiref.handlers.CGIHandler().run(application)
application and then
attaches two resources to the application before using the application to respond
a CGI request. Resource allocation is described in the following sections.
To attach a resource to a root application, construct a filter object
for finding and allocating the resource, and attach the resource to
the root application using the registerResourceFinder
method.
The following code fragment from the example above allocates
a resource finder for storing user profiles as files in a directory,
and attaches the resource to the root application
using the prefix "profile"
# add user profile resource
profiles = sessionDirectory.directoryProfileFinder("/tmp/profiles")
application.registerResourceFinder(prefix="profile", finder=profiles)
"profile" resource is installed an application
executing on behalf of a user with a profile may get or put
profile entries using the resource path for the entry.
A configuration template might use the putResource
standard middleware to put the Name profile entry like this:
{{include "whiff_middleware/putResource"}}
{{using path}} ["profile", "item", "Name"] {{/using}}
{{using value}}Hunter S. Thompson{{/using}}
{{/include}}
GetResource
standard middleware to get the Name profile entry like this:
{{include "whiff_middleware/getResource"}}
["profile", "item", "Name"]
{{/include}}
Hunter S. Thompson.
application.registerStaticResource(prefix="ApplicationName",
resourceValue="Global Thermonuclear War")
["ApplicationName"].
Static resources may have any sort of value, including objects with complex
interfaces such as user authentication filters.
cgi standard resourcecgi standard resource stores form input element
parameters sent by the HTTP request.
The resource path ["cgi"] gets the sequence of names
for all cgi parameters.
The resource path ["cgi", null] gets the dictionary of names
to sequences of values for all cgi parameters.
The resource path ["cgi", "NAME"] gets the list of values
for the cgi parameter named NAME.
local standard resourcelocal standard resource provides a scratch area
which allows different parts of an application to share information.
For example an application component concerned with setting HTML
style parameters may use the local resource to store
style names to be used by other components which generate HTML fragments.
The resource path ["local", "NAME"] gets or puts a value
named NAME in the local storage resource.
counter standard resourcecounter standard resource may be used to keep counts.
For example a numbered sequence of paragraphs split across two columns
may be numbered consistently using a counter stored in the counter resource.
To initialize the counter NAME to the value 100, put 100 to
the resource path ["counter", "NAME"]. Getting the resource
path ["counter", "NAME"] will return the current value for
the NAME counter (100) and increment the value (setting it to 101
for the next get).
freshName standard resourcefreshName standard resource is used to generate
javascript variable names or DOM identifiers or other names which are
guaranteed to be "fresh" -- that is, they have not been used by any
other part of the application. Fresh names can be useful, for example,
to allow an application component to generate 5 similar javascript
functions and assign the functions different names which are guaranteed
to not collide with any other name used by the application.
A get for the resource path ["freshName", "NAME"] will
evaluate to something like NAME542 where NAME542
has not been used by any other part of the application.
The following resource finder implementations are included in the WHIFF distribution.
whiff.gateway.FileFinder is an example implementation
which permits read or (possibly) write access to a single file resource, protected
by a password.
whiff.gateway.FilePatternFinder
allows access to files in a directory matching a filename pattern.
whiff.gateway.SimplePasswordGateway
is resource container which allows access to other finders only
when a recognized user name and password is provided.
whiff.resources.FileByLines.LineFinder
allows read only access to lines of a file by line number.
whiff.resources.PageShadow.ShadowPageFinder
allows access to a file in a directory which cooresponds to the URL
of the request (this is used to store comments associated
with a page, for example).
whiff.resources.inMemorySession.memorySessionFinder
allows access to HTTP session storage implemented in memory for
single process servers.
whiff.resources.inMemorySession.memoryProfileFinder
allows access to User profile storage implemented in memory for
single process servers.
whiff.resources.sessionDirectory.directorySessionFinder
allows access to HTTP session information stored in files within a directory.
whiff.resources.sessionDirectory.directoryProfileFinder
allows access to user Profile information stored in files within a directory.
whiff.resources.GAESession.GAESessionFinder
allows access to HTTP session information stored using the Google App Engine datastorage.
whiff.resources.GAESession.GAEProfileFinder
allows access to user profile information stored using the Google App Engine datastorage.
whiff.resources.GAETreeStore.TreeResource
allows access to an arbitrarily large tree view data structure implemented using the Google App Engine datastorage.
__wsgi_directory__ = True
Normally the module interpreted as a root application will be a Python package
and the __wsgi_directory__ will be placed in the __init__.py
initializer for the module.
Modules within a root directory may be configured
as sub-directories or applications or they may not be
recognized as WHIFF components at all.
The URL naming a contained module is the URL of the parent module
joined with the name of the contained module. For example if the URL
of the parent directory is http://my.server.com/parent/directory
and the module is named mysub then the URL
locating the module is
http://my.server.com/parent/directory/mysub .
Other modules contained in the root directory will also be interpreted
as WHIFF application containers if they contain the __wsgi_directory__ = True
marking.
Other modules contained in the root directory which contain a function named __wsgi__
will be interpreted as WSGI applications where the __wsgi__ function defines
the application to respond to web requests on behalf of the module.
Other modules contained in the root directory which contain a constructor named __middleware__
will be interpreted as WSGI middleware applications where the __middleware__ callable defines
a constructor for creating middleware components on behalf of the module.
There are other ways to install WSGI functionality in a root directory which WHIFF will recognized, but they are not documented here at the moment, and they are not recommended for normal use.
__init__.py configuration for the module specifies otherwise.
To direct a root module to serve configuration template files and files with recognized extensions
add a line in the __init__.py like this:
resolver.publish_templates(__path__[0], globals(),
mime_extensions=True, directory_middleware=True)
__path__[0]) and create
recognized WHIFF applications to respond to configuration templates and files with extensions
that correspond to recognized MIME types. For example if the directory contains a file named
Application.whiff the content of the file will be interpreted as a configuration template
and requests with the relative URL Application will be served by that template.
If the directory contains a file named Picture.jpg the content of the file will
be interpreted as a JPEG image and requests with the relative URL Picture.jpg will
be served the contents of that file.
If the keyword directory_middleware=True is specified then the directory will also
respond to the relative URL "." by returning an HTML directory listing (this is
useful for testing, but may not be advisable for "production" deploys).
__init__.py file may include standard Python import statements
in order to make applications available from that directory.
An __init__.py can import a simple application or middleware
for local use.
For example a directory which
makes extensive use of the Mako templating engine may include
from whiff.middleware.mako import MakoFile
__init__.py, and this will allow all the components
in the directory to use the directive
{{include "MakoFile"}} ... {{/include}}
MakoFile middleware
{{include "whiff_middleware/mako/MakoFile"}} ... {{/include}}
Furthermore a directory may import another root directory module
to "mount" another application within the directory. For example the following
sequence mounts the root directory gfChat
in the file /usr/local/apache2/wsgi/top/__init__.py, to install
the WHIFF "chat" demo on my test server under the directory top.
import gfChat
__init__.py file. For example
the following declaration parameterizes the "python source code demo"
on my test server.
from whiff.servers.fsCSI import fsCSI
search = fsCSI.getApplication("/export/archive", "/export/Python-2.6.1")
|
Subsections: ++ Implementing a resource finder
× This section describes how to implement a special purpose resource for an application. |
||