Source

Webware / WebKit / Docs / UsersGuide.html

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>WebKit User's Guide</title>
<link rel="stylesheet" href="../../Docs/Doc.css" type="text/css" />
</head>
<body>
<div class="document" id="webkit-user-s-guide">
<h1 class="title">WebKit User's Guide</h1>

<p>Webware for Python</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Version:</th><td class="field-body">1.1</td>
</tr>
<tr class="field"><th class="field-name">Released:</th><td class="field-body">08/03/11</td>
</tr>
</tbody>
</table>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#synopsis" id="id20">Synopsis</a></li>
<li><a class="reference internal" href="#feedback" id="id21">Feedback</a></li>
<li><a class="reference internal" href="#introduction" id="id22">Introduction</a><ul>
<li><a class="reference internal" href="#overview" id="id23">Overview</a></li>
<li><a class="reference internal" href="#compared-to-cgi-applications" id="id24">Compared to CGI applications</a></li>
<li><a class="reference internal" href="#papers" id="id25">Papers</a></li>
</ul>
</li>
<li><a class="reference internal" href="#errors-uncaught-exceptions" id="id26">Errors / Uncaught Exceptions</a></li>
<li><a class="reference internal" href="#configuration" id="id27">Configuration</a></li>
<li><a class="reference internal" href="#administration" id="id28">Administration</a></li>
<li><a class="reference internal" href="#debugging" id="id29">Debugging</a><ul>
<li><a class="reference internal" href="#print" id="id30">print</a></li>
<li><a class="reference internal" href="#raising-exceptions" id="id31">Raising Exceptions</a></li>
<li><a class="reference internal" href="#dumping-thread-stack-frames" id="id32">Dumping Thread Stack Frames</a></li>
<li><a class="reference internal" href="#restarting-the-server" id="id33">Restarting the Server</a></li>
<li><a class="reference internal" href="#assertions" id="id34">Assertions</a></li>
<li><a class="reference internal" href="#using-wingide" id="id35">Using WingIDE</a></li>
<li><a class="reference internal" href="#html-validation" id="id36">HTML Validation</a></li>
</ul>
</li>
<li><a class="reference internal" href="#naming-conventions" id="id37">Naming Conventions</a></li>
<li><a class="reference internal" href="#actions" id="id38">Actions</a></li>
<li><a class="reference internal" href="#plug-ins" id="id39">Plug-ins</a></li>
<li><a class="reference internal" href="#how-do-i-develop-an-app" id="id40">How do I develop an app?</a></li>
<li><a class="reference internal" href="#known-bugs" id="id41">Known Bugs</a></li>
<li><a class="reference internal" href="#credit" id="id42">Credit</a></li>
</ul>
</div>
<div class="section" id="synopsis">
<h1>Synopsis</h1>
<p>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.</p>
</div>
<div class="section" id="feedback">
<h1>Feedback</h1>
<p>You can e-mail <a class="reference external" href="mailto:webware-discuss&#64;lists.sourceforge.net">webware-discuss&#64;lists.sourceforge.net</a> to give feedback,
discuss features, and get help using WebKit.  If you have a bug to
report, use the <a class="reference external" href="http://sourceforge.net/tracker/?atid=104866&amp;group_id=4866&amp;func=browse">bug tracker</a>.</p>
</div>
<div class="section" id="introduction">
<h1>Introduction</h1>
<div class="section" id="overview">
<h2>Overview</h2>
<p>The core concepts of the WebKit are the Application, Servlet, Request,
Response and Transaction, for which there are one or more Python
classes.</p>
<p>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.</p>
<p>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.</p>
<p>In order to connect the web server and the application server a small
program called an <em>adapter</em> 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 <a class="reference external" href="InstallGuide.html">Install Guide</a> for
more information.</p>
<p>At a more detailed level, the process looks like this:</p>
<ul class="simple">
<li>At some point, someone has configured and run both a web server
(such as Apache) and the WebKit app server (WebKit/AppServer).</li>
<li>A user requests a web page by typing a URL or submitting a form.</li>
<li>The user's browser sends the request to the remote web server.</li>
<li>The web server invokes the adapter.</li>
<li>The adapter simply collects information about the request and sends
it to the WebKit app server which is ready and waiting.</li>
<li>The app server asks the Application object to dispatch the raw
request.</li>
<li>The application instantiates an HTTPRequest object and asks the
appropriate Servlet (as determined by examining the URL) to process
it.</li>
<li>The servlet generates content into a given HTTPResponse object,
whose content is then sent back by the app server to the adapter.</li>
<li>The adapter sends the content through the web server and ultimately to
the user's web browser.</li>
</ul>
<p>For a more detailed guide, see <a class="reference external" href="http://colorstudy.com/software/webware/Anatomy.html">Anatomy of a Webware Transaction</a>.</p>
</div>
<div class="section" id="compared-to-cgi-applications">
<h2>Compared to CGI applications</h2>
<p>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.</p>
<p>With the long-running 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.</p>
<p>Of course, CGIs can still be appropriate for &quot;one shot&quot; deals or
simple applications. Webware includes a <a class="reference external" href="../../CGIWrapper/Docs/index.html">CGI Wrapper</a> if you'd like
to encapsulate your CGI scripts with robust error handling, e-mail
notifications, etc.</p>
</div>
<div class="section" id="papers">
<h2>Papers</h2>
<p>You should also consider reading the <a class="reference external" href="http://www.webwareforpython.org/Papers">papers</a> which have been
written about Webware for Python, particularly the &quot;Introduction to
Webware for Python&quot; that was presented by Chuck Esterbrook at the
9th International Python Conference in 2001.</p>
</div>
</div>
<div class="section" id="errors-uncaught-exceptions">
<h1>Errors / Uncaught Exceptions</h1>
<p>One of the conveniences provided by WebKit is the handling of uncaught
exceptions. The response to an uncaught exception is:</p>
<ul class="simple">
<li>Log the time, error, script name and traceback to AppServer's console.</li>
<li>Display a web page containing an apologetic message to the user.</li>
<li>Save a technical web page with debugging information so that
developers can look at it after-the-fact. These HTML-based error
messages are stored one-per-file, if the <tt class="docutils literal">SaveErrorMessages</tt>
setting is true (the default). They are stored in the directory
named by the <tt class="docutils literal">ErrorMessagesDir</tt> (defaults to <tt class="docutils literal">&quot;ErrorMsgs&quot;</tt>).</li>
<li>Add an entry to the error log, found by default in
<tt class="docutils literal">Logs/Errors.csv</tt></li>
<li>E-mail the error message if the <tt class="docutils literal">EmailErrors</tt> setting is true,
using the settings <tt class="docutils literal">ErrorEmailServer</tt> and
<tt class="docutils literal">ErrorEmailHeaders</tt>. See <a class="reference external" href="Configuration.html#errors">Configuration</a> for more information.</li>
</ul>
<p>Archived error messages can be browsed through the <a class="reference internal" href="#administration">administration</a> page.</p>
<p>Error handling behavior can be configured as described in <a class="reference external" href="Configuration.html#errors">Configuration</a>.</p>
</div>
<div class="section" id="configuration">
<h1>Configuration</h1>
<p>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 <tt class="docutils literal">Configs/</tt> directory. A config file simply contains a
Python dictionary containing the items you wish to override. For
example:</p>
<pre class="literal-block">
{
    'SessionStore': 'Memory',
    'ShowDebugInfoOnErrors': 1
}
</pre>
<p>See the <a class="reference external" href="Configuration.html">Configuration Guide</a> for more information on settings.</p>
</div>
<div class="section" id="administration">
<h1>Administration</h1>
<p>WebKit has a built-in administration page that you can access via the
<tt class="docutils literal">Admin</tt> context. You can see a list of all contexts in the sidebar
of any <tt class="docutils literal">Example</tt> or <tt class="docutils literal">Admin</tt> page.</p>
<p>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.</p>
<p>More sensitive pages that give control over the app server require a
user name and password, the username is <tt class="docutils literal">admin</tt>, and you'll set the
password when you run <tt class="docutils literal">install.py</tt>. You can change the password in
<tt class="docutils literal">WebKit/Configs/Application.config</tt>.</p>
<p>The adminstration scripts provide further examples of writing pages
with WebKit, so you may wish to examine their source in
<tt class="docutils literal">WebKit/Admin/</tt>.</p>
</div>
<div class="section" id="debugging">
<h1>Debugging</h1>
<div class="section" id="print">
<h2>print</h2>
<p>The most common technique is the infamous <tt class="docutils literal">print</tt> statement. The
results of <tt class="docutils literal">print</tt> 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
&gt;&gt;) 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:</p>
<pre class="literal-block">
print '&gt;&gt; fields =', self.request().fields()
</pre>
</div>
<div class="section" id="raising-exceptions">
<h2>Raising Exceptions</h2>
<p>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 <a class="reference external" href="SampleError.html">example error
page</a>.</p>
<p>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 <tt class="docutils literal">print</tt> statement. For example:</p>
<pre class="literal-block">
raise Exception('self = %s' % self)
</pre>
</div>
<div class="section" id="dumping-thread-stack-frames">
<h2>Dumping Thread Stack Frames</h2>
<p>If you are using Python 2.5 or newer, of if you have the <a class="reference external" href="http://www.majid.info/mylos/stories/2004/06/10/threadframe.html">threadframe</a>
module installed, you can dump the stack frames of all running Webware
application server threads to standard output by simply sending a <tt class="docutils literal">SIGQUIT</tt>
or <tt class="docutils literal">SIGBREAK</tt> signal to the application server. On Windows, this can be
achieved by pressing Ctrl-Break or Shift-Ctrl-Break, or by trying to close
the console window.</p>
</div>
<div class="section" id="restarting-the-server">
<h2>Restarting the Server</h2>
<p>When a servlet's source code changes, it is reloaded. However,
ancestor classes of servlets and library modules are not.
You may wish to enable the auto-reloading feature in the <a class="reference external" href="Configuration.html#appserver-config">AppServer.config</a>
file to mitigate this problem.</p>
<p>In any case, when having problems, consider restarting the app server.</p>
<p>Another option is to use the AppControl page of the <a class="reference internal" href="#administration">Admin</a> context
to clear the servlet instance and class cache.</p>
</div>
<div class="section" id="assertions">
<h2>Assertions</h2>
<p>Assertions are used to ensure that the internal conditions of the
application are as expected. An assertion is equivalent to an <tt class="docutils literal">if</tt>
statement coupled with an exception. For example:</p>
<pre class="literal-block">
assert shoppingCart.total()&gt;=0.0, \
    'shopping cart total is %0.2f' % shoppingCart.total()
</pre>
</div>
<div class="section" id="using-wingide">
<h2>Using WingIDE</h2>
<p>Here is what you need to do in order to debug a Webware web site
using the <a class="reference external" href="http://wingware.com">WingIDE</a> development environment:</p>
<ul>
<li><p class="first">Use the <a class="reference external" href="InstallGuide.html#makeappworkdir">MakeAppWorkDir</a> script
to make a local app work dir for your project.</p>
</li>
<li><p class="first">Create a run-debug.py script in the work directory with these contents:</p>
<pre class="literal-block">
import sys, Launch
Launch.main([sys.argv[0]] + ['DebugAppServer'] + sys.argv[1:])
</pre>
</li>
<li><p class="first">Add that file to the WingIDE project if you haven't already.</p>
</li>
<li><p class="first">Right-click and choose &quot;Set As Main Debug File&quot;.</p>
</li>
</ul>
<p>Now you can run from WingIDE, set break points, examine the stack, use
a Python prompt tied to any stack prompt, etc.</p>
<p>WingIDE also has a &quot;Debug &gt; Attach to Process...&quot; command which could
be useful to debug a test or production server.</p>
</div>
<div class="section" id="html-validation">
<h2>HTML Validation</h2>
<p>You can validate the HTML in your pages using the <a class="reference external" href="http://www.htmlhelp.com/tools/validator/">Web Designer
Group's HTML Validator</a>.  It is available as a <a class="reference external" href="http://www.htmlhelp.com/tools/validator/packages/">RPM package</a>, in
Debian as <tt class="docutils literal"><span class="pre">wdg-html-validator</span></tt> and you can also install the <a class="reference external" href="http://www.htmlhelp.com/tools/validator/source.html">source</a>.</p>
<p>To enable the validation, you have to override <tt class="docutils literal">.writeBodyParts()</tt>
in your <tt class="docutils literal">SitePage</tt>, as:</p>
<pre class="literal-block">
def writeBodyParts(self):
    Page.writeBodyParts()
    self.validateHTML()
</pre>
<p>If your pages contain invalid HTML, a message will be appended to the
page.</p>
</div>
</div>
<div class="section" id="naming-conventions">
<h1>Naming Conventions</h1>
<p>Cookies and form values that are named with surrounding underscores
(such as <tt class="docutils literal">_sid_</tt> and <tt class="docutils literal">_action_</tt>) are generally reserved by WebKit
and various plugins and extensions for their 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.</p>
</div>
<div class="section" id="actions">
<h1>Actions</h1>
<p>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 <tt class="docutils literal">respondToPost()</tt> or Page's <tt class="docutils literal">writeBody()</tt>, will be
invoked. However, you may find it more useful to bind the button to a
specific method of your servlet such as <tt class="docutils literal">new()</tt>, <tt class="docutils literal">remove()</tt>
etc. to implement the command, and reserve <tt class="docutils literal">writeBody()</tt> for
displaying the page and the form that invokes these methods.  Note
that your &quot;command methods&quot; can then invoke <tt class="docutils literal">writeBody()</tt> after
performing their task.</p>
<p>The <em>action</em> feature of <tt class="docutils literal">Page</tt> let's you do this. The process goes
like this:</p>
<ol class="arabic">
<li><p class="first">Add buttons to your HTML form of type <tt class="docutils literal">submit</tt> and name
<tt class="docutils literal">_action_</tt>. For example:</p>
<pre class="literal-block">
&lt;input name=&quot;_action_&quot; type=&quot;submit&quot; value=&quot;New&quot;&gt;
&lt;input name=&quot;_action_&quot; type=&quot;submit&quot; value=&quot;Delete&quot;&gt;
</pre>
</li>
<li><p class="first">Alternately, name the submit button <tt class="docutils literal">_action_methodName</tt>.  For
example:</p>
<pre class="literal-block">
&lt;input name=&quot;_action_New&quot; type=&quot;submit&quot; value=&quot;Create New Item&quot;&gt;
</pre>
</li>
<li><p class="first">Add an <tt class="docutils literal">actions()</tt> method to your class to state which actions
are valid.  (If WebKit didn't force you to do this, someone could
potentially submit data that would cause any method of your servlet
to be run).  For example:</p>
<pre class="literal-block">
def actions(self):
    return SuperClass.actions(self) + ['New', 'Delete']
</pre>
</li>
<li><p class="first">Now you implement your action methods.</p>
</li>
</ol>
<p>The <tt class="docutils literal">ListBox</tt> example shows the use of actions (in
<tt class="docutils literal">WebKit/Examples/ListBox.py</tt>).</p>
<p>Note that if you procede as in 1., you can add a <tt class="docutils literal">methodNameForAction()</tt>
method to your class transforming the value from the submit button (its
label) to a valid method name. This will be needed, for instance, if there
is a blank in the label on the button. However, usually it's simpler to
procede as in 2. in such cases.</p>
</div>
<div class="section" id="plug-ins">
<h1>Plug-ins</h1>
<p>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.</p>
<p>The most infamous plug-in is PSP (Python Server Pages) which ships
with Webware.</p>
<p>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.</p>
<p>Technically, plug-ins are Python packages that follow a few simple
conventions in order to work with WebKit. See <a class="reference external" href="Developing.html#creatingplugins">Creating Plugins</a> for
information about writing your own.</p>
</div>
<div class="section" id="how-do-i-develop-an-app">
<h1>How do I develop an app?</h1>
<p>The answer to that question might not seem clear after being deluged
with all the details. Here's a summary:</p>
<ul class="simple">
<li>Make sure you can run the WebKit AppServer. See the <a class="reference external" href="InstallGuide.html">Install Guide</a>
for more information.</li>
</ul>
<ul class="simple">
<li>Read the source to the examples (in <tt class="docutils literal">WebKit/Examples</tt>), then
modify one of them to get your toes wet.</li>
<li>Create your own new example from scratch. Ninety-nine percent of the
time you will be subclassing the <tt class="docutils literal">Page</tt> class.</li>
<li>Familiarize yourself with the class docs in order to take advantage
of classes like Page, HTTPRequest, HTTPResponse and
Session. Unfortunately, I couldn't get generated class docs working
for this release, so you'll have to resort to breezing through the
source code which is coupled with documentation strings. Read the
examples first.</li>
<li>With this additional knowledge, create more sophisticated pages.</li>
<li>If you need to secure your pages using a login screen, you'll want
to look at the SecurePage, LoginPage, and SecureCountVisits examples
in <tt class="docutils literal">WebKit/Examples</tt>.  You'll need to modify them to suit your
particular needs.</li>
<li>The <a class="reference external" href="http://wiki.webwareforpython.org">Webware For Python Wiki</a> provides a lot of useful HowTos,
Recipes and other useful informaiton for Application developers.</li>
</ul>
<ul class="simple">
<li>Contribute enhancements and bug fixes back to the project. <tt class="docutils literal"><span class="pre">:-)</span></tt></li>
<li>The Webware user community is quite supportive and friendly:<ul>
<li>Discussion mailing list:
<a class="reference external" href="http://lists.sourceforge.net/mailman/listinfo/webware-discuss">http://lists.sourceforge.net/mailman/listinfo/webware-discuss</a></li>
<li>Make sure you find out about new versions when they're released,
via the announce list:
<a class="reference external" href="http://lists.sourceforge.net/mailman/listinfo/webware-announce">http://lists.sourceforge.net/mailman/listinfo/webware-announce</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="known-bugs">
<h1>Known Bugs</h1>
<p>Known bugs and future work in general are documented in <a class="reference external" href="Future.html">Future</a>.</p>
</div>
<div class="section" id="credit">
<h1>Credit</h1>
<p>Authors: Chuck Esterbrook, Jay Love, Geoff Talvola, Ian Bicking
and others (improvements and additions).</p>
<p>Many people, mostly on the webware-discuss mailing list, have provided
feedback, testing and patches.</p>
<p>The design was inspired by both Apple's WebObjects and Java's
Servlets.</p>
</div>
</div>
</body>
</html>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.