1.15.2 Writing Applications

It can be slightly complicated to write your own WSGI applications so the web.wsgi.base provides a sample class from which you can derive your own application class. The class has the following API:

class BaseApplication( [status='200 OK'], [headers=[('Content-type','text/html')]])

The class defines the following attributes:

environ
A dictionary of environment variables similar to os.environ but also containing entries from the WSGI server and any middleware being used. The environ dictionary is the main way your application will have access to the environment. You should not need to change environ.
status
A string of the form 'error_code messgae' which can be used to set the HTTP status code of the application. For example '200 OK' for a normal application, '500 Error' if there was a server error.
headers
A list of (field-name, field-value) tuples suitable for use in the WSGI start_response function. Any headers your application needs to send should be specified by this list in the order they should be sent. Note: The default value of the headers attribute is set to be [('Content-type','text/html')] in the class constructor, so if you do not want this HTTP header you should set a different value in the constrcutor or in your application.

The (field-name, field-value) format could be easily made into HTTP header messages suitable for direct printing:

messages = []
for header in self.headers:
    messages.append("%s: %s"%header)

Warning: WSGI applications and middleware should not normally use the print statement in the same way as in CGI scripts. Instead strings should be sent to the output() method where they will be returned at the end of execution of the class in accordance with the WSGI specification.

_output
A list of strings to be returned at the end of the application. The class defines the output() method which is used to directly append strings to _output so there should be no need to access _output directly.

The class defines the following methods:

start( )
This method should be over-ridden in derived classes to provide your application's functionality.

output( *text)
Takes one or more strings and appends them to the _output attribute when they will be returned at the end of program execution to display the program output. For example:

self.output('one')
self.output('one', 'two')

Note: If the values are not strings, they are convertes to strings using the builtin function str().

__call__( environ, start_response)
You should not need to modify this method but is documented here for a complete understanding as it provides the functionality which makes derived classes WSGI applications. This method sets up the environ attribute and calls start(). Once start() returns, it calls start_response(self.status, self.headers) to set the status and headers and returns self._output.

To create the 'Hello World!' example used at the start of the documentation with the BaseApplication class we could do the following:

import web.wsgi.base

class Application(web.wsgi.base.BaseApplication):
    def start(self):
        self.output('Hello World!')
        
application = Application()

Note: In this example we have used a class instance as the application whereas we previously used a function definition. Class instances must be initialised.

To use different HTTP headers we could do the following:

application = Application(headers=[('Content-type','text/plain')])

For application to always be treated as having failed we could set the status to '500 Error'

application = Application(status='500 Error')

To allow be able to set the text of the 'Hello World!' message from the class constructor we need to modify the class:

import web.wsgi.base

class Application(web.wsgi.base.BaseApplication):

    def __init__(self, status='200 OK', headers=[('Content-type','text/html'), text='Hello World!']):
        self.text = text
        web.wsgi.base.BaseApplication.__init__(self, status, headers)
    
    def start(self):
        self.output(self.text)
        
application = Application(text='Hello World Again!')

Warning: When deriving your own classes it is important you do not accidently over-write any of the attributes or methods of the base class, otherwise your class may not function as you intended.