Synopsis
Feedback
Introduction
Python 9
Overview
Compared to CGI "apps"
Errors / Uncaught Exceptions
Configuration
AppServer.config
Application.config
Administration
Debugging
print
Raising Exceptions
Restarting the Server
Assertions
Naming Conventions
Actions
Plug-ins
How do I develop an app?
Known Bugs
Credit
Synopsis
WebKit provides Python classes for generating dynamic content from a web-based, server-side application. It is a significantly more powerful alternative to CGI scripts for application-oriented development.
Feedback
You can e-mail webware-discuss@lists.sourceforge.net to give feedback, discuss features and get help using WebKit.
Introduction
Python 9
A paper titled "Introduction to Webware" was accepted for Python 9, which runs the week of March 4th, 2001. Eventually, the conference proceedings make their way to the web. Unfortunately, at the time of this writing, we don't know what the URL will be, but if you poke around on that site or on python.org you can probably find them.
Overview
The core concepts of the WebKit are the Application, Servlet, Request, Response and Transaction, for which there are one or more Python classes.
The application resides on the server-side and manages incoming requests in order to deliver them to servlets which then produce responses that get sent back to the client. A transaction is a simple container object that holds references to all of these objects and is accessible to all of them.
Content is normally served in HTML or XML format over an HTTP connection. However, applications can provide other forms of content and the framework is designed to allow new classes for supporting protocols other than HTTP.
In order to connect the web server and the application server a small program called an adapter is used. It bundles a web browser request and sends it to the application server, which then processes it and sends the response back to the adapter which then outputs the results for use by the web server. Adapters come in various flavors including CGI, FastCGI and Apache mod. See the Install Guide for more information.
At a more detailed level, the process looks like this:
The alternative to a server-side application is a set of CGI scripts. However, a CGI script must always be launched from scratch and many common tasks will be performed repeatedly for each request. For example, loading libraries, opening database connections, reading configuration files, etc.
With the server-side application, the majority of these tasks can be done once at launch time and important results can be easily cached. This makes the application significantly more efficient.
Of course, CGIs can still be appropriate for "one shot" deals or simple applications. Webware includes a CGI Wrapper if you'd like to encapsulate your CGI scripts with robust error handling, e-mail notifications, etc.
Errors / Uncaught Exceptions
One of the conveniences provided by WebKit is the handling of uncaught exceptions. The response to an uncaught exception is:
SaveErrorMessages
setting is true (the default). They are stored in the directory named by the ErrorMessagesDir
(defaults to 'ErrorMsgs').
EmailErrors
setting is true, using the settings ErrorEmailServer
and ErrorEmailHeaders
. You'll need to configure these to active this feature.
Here is a sample error page.
Archived error messages can be browsed through the administration page.
Error handling behavior can be configured as described in Configuration.
There are several configuration parameters through which you can alter how WebKit behaves. They are described below, including their default values. Note that you can override the defaults by placing config files in the Configs/
directory. A config file simply contains a Python dictionary containing the items you wish to override. For example:
{
'SessionStore': 'Memory',
'ShowDebugInfoOnErrors': 1
}AppServer.config
= 1
= 1
= 127.0.0.1
= 8086
= []
= ['..']
= 10
= 'webware'
= ['index', 'Main']
= 1
=
['.pyc', '.pyo', '.py~', '.bak']
= 1
= 'Logs/Activity.csv'
=
['request.remoteAddress', 'request.method', 'request.uri', 'response.size', 'servlet.name', 'request.timeStamp', 'transaction.duration', 'transaction.errorOccurred']
=
{
'default': 'Examples',
'Admin': 'Admin',
'Examples': 'Examples',
'Docs': 'Docs',
'Testing': 'Testing',
}
= 'Dynamic'
= 60
= 1
= 0
= 10000
= 15
= 0
= 1
= 1
= 1
= 1
= 0
= 5
=
'The site is having technical difficulties with this page. An error has been logged, and the problem will be fixed as soon as possible. Sorry!'
= 'Logs/Errors.csv'
= 1
= 'ErrorMsgs'
= 0
= 'mail.-.com'
=
{
'From': '-@-.com',
'To': ['-@-.com'],
'Reply-to': '-@-.com',
'Content-type': 'text/html',
'Subject': 'Error'
}
=
{
'ReuseServlets': 1,
# Technique choices:
# serveContent, redirectSansAdapter
'Technique': 'serveContent',
# If serving content:
'CacheContent': 1, # set to 0 to reduce memory use
'CheckDate': 1,
}
= 1
WebKit has a built-in administration page that you can access via the Admin context. You can see a list of all contexts in the sidebar of any Example or Admin page.
The admin pages allows you to view WebKit's configuration, logs, and servlet cache, and perform actions such as clearing the cache, reloading selected modules and shutting down the app server.
More sensitive pages that give control over the app server require a user name and password, which defaults to admin/webware. You can change the password in WebKit/Configs/Application.config and should do so as soon as possible.
The adminstration scripts provide further examples of writing pages with WebKit, so you may wish to examine their source in WebKit/Admin/.
Debugging
As with all software development, you will need to debug your web application. The most popular techniques are detailed below.
print
The most common technique is the infamous print
statement. The results of print
statements go to the console where the WebKit application server was started (not to the HTML page as would happen with CGI). Prefixing the debugging output with a special tag (such as >>) is useful because it stands out on the console and you can search for the tag in source code to remove the print statements after they are no longer useful. For example:
print '>> fields =', self.request().fields()
Note that if you are using OneShot.cgi, then you will need to set ShowConsole to 1 in WebKit/Configs/OneShotAdapter.config.
Raising Exceptions
Uncaught expections are trapped at the application level where a useful error page is saved with information such as the traceback, environment, fields, etc. You can configure the application to automatically e-mail you this information. Here is an example error page.
When an application isn't behaving correctly, raising an exception can be useful because of the additional information that comes with it. Exceptions can be coupled with messages, thereby turning them into more powerful versions of the print
statement. For example:
raise Exception, 'self = %s' % self
Restarting the Server
When a servlet's source code changes, it is reloaded. However, ancestor classes of servlets are not. That is why web sites are often developed with the One Shot adapter and deployed with a more advanced, high performance adapter.
In any case, when having problems, consider restarting the app server.
Another option is to use the AppControl page of the Admin context to clear the servlet instance and class cache.
Assertions
Assertions are used to ensure that the internal conditions of the application are as expected. An assertion is equivalent to an if
statement coupled with an exception. For example:
assert shoppingCart.total()>=0.0, 'shopping cart total is %0.2f' % shoppingCart.total()
Naming Conventions
Cookies and form values that are named with surrounding underscores (such as _sid_
and _action_
) are reserved by WebKit for its own internal purposes. If you refrain from using surrounding underscores in your own names, then [a] you won't accidentally clobber an already existing internal name and [b] when new names are introduced by future versions of WebKit, they won't break your application.
Actions
Suppose you have a web page with a form and one or more buttons. Normally, when the form is submitted, a method such as Servlet's respondToPost()
or Page's writeHTML()
, will be invoked. However, you may find it more useful to bind the button to a specific method of your servlet such as new()
, remove()
etc. to implement the command, and reserve writeHTML()
for displaying the page. Note that your "command methods" can then invoke writeHTML()
after performing their task.
The action feature of Page let's you do this. The process goes like this:
1. Add buttons to your HTML form of type submit
and name _action_
. For example:
<input name=_action_ type=submit value=New>
<input name=_action_ type=submit value=Delete>
2. Add an actions()
method to your class to state which actions are valid. This is security requirement is important. Without it, hackers could invoke any servlet method they wanted! For example:
def actions(self): return SuperClass.actions(self) + ['New', 'Delete']
3. Unfortunately, the HTML submit button does not separate its value from its title/label. If your button labels don't match your method names, you will need to implement methodNameForAction()
to provide the mapping. You could simply use a dictionary to create the mapping, or if you know there is some relationship you could write the logic for it. For example,
def methodNameForAction(self, name): return string.lower(name)
4. Now you implement your action methods.
The ListBox example shows the use of actions.
Plug-ins
A plug-in is a software component that is loaded by WebKit in order to provide additional WebKit functionality without necessarily having to modify WebKit's source.
The most infamous plug-in is PSP (Python Server Pages) which ships with Webware.
Plug-ins often provide additional servlet factories, servlet subclasses, examples and documentation. Ultimately, it is the plug-in author's choice as to what to provide and in what manner.
Technically, plug-ins are Python packages that follow a few simple conventions in order to work with WebKit. More information can be found in PlugIn.py's doc strings. You can learn more about Python packages in the Python Tutorial, 6.4: "Packages".
How do I develop an app?
The answer to that question might not seem clear after being deluged with all the details. Here's a summary:
Known bugs and future work in general, is documented in Future.html.
Credit
Authors: Chuck Esterbrook, Jay Love, Geoff Talvola
Many people, mostly on the webware-discuss mailing list, have provided feedback and testing.
The design was inspired by both Apple's WebObjects and Java's Servlets.