Zope Logo - z object publishing environment
Home News Information Community Support Download

Zope ORB

Introduction

The Zope ORB provides a simple mechanism for publishing a collection of Python objects as World-Wide-Web (Web) resources without any plumbing (e.g. CGI) specific code. The Zope ORB is the central component of the Zope web application platform.

The Zope ORB is part of the ZPublisher Package.

Benefits

  • Applications do not have to include code for interfacing with the web server.

  • Applications can be moved from one publishing mechanism, such as CGI, to another mechanism, such as PCGI, ZopeHTTPServer, Fast CGI or COM, with no change.

  • Python objects are published as Python objects. The web server "calls" the objects in much the same way that other Python objects would.

  • Automatic conversion of URL to object/sub-object traversal.

  • Automatic marshaling of form data, cookie data, and request meta-data to Python function arguments.

  • Automated exception handling.

  • Automatic generation of CGI headers.

  • Automated authentication and authorization.

Published objects

Objects are published by including them in a published module. When a module is published, any objects that:

  • can be found in the module's global name space,

  • that do not have names starting with an underscore,

  • that have non-empty documentation strings, and

  • that are not modules

are published.

Sub-objects (or sub-sub objects, ...) of published objects are also published, as long as the sub-objects:

  • have non-empty doc strings,

  • have names that do not begin with an underscore, and

  • are not modules.

Note that object methods are considered to be subobjects.

Object-to-subobject traversal is done by converting steps in the URI path to get attribute or get item calls. For example, in traversing from http://some.host/some_module/object to http://some.host/some_module/object/subobject, the module publisher will try to get some_module.object.subobject. If the access fails with other than an attribute error, then the object publisher raises a "NotFound" exception. If the access fails with an attribute error, then the object publisher will try to obtain the subobject with: some_module.object["subobject"]. If this access fails, then the object publisher raises a "Not Found" exception. If either of the accesses suceeds, then, of course, processing continues.

During object traversal, the names . and .. have special meaning if the application does not provide meaning for them. If the name . is encountered and the application does not provide a value, then the name is effectively skipped. For example, the path x/./y is equivalent to x/y. If the name .. is encountered and the application does not provide a value, then the parent of the object being traversed is used. For example, x/y/../z is almost equivalent to x/z, except that y is considered to be part of the path to z. If y has a user folder, it will be consulted when validadting access to z before a user folder in x is consulted.

Normally, URL traversal begins with the published module. If the Published module has a global variable named bobo_application, then traversal begins with this object instead.

If the final object encountered when traversing the URL has an index_html attribute, the object traversal will continue to this attribute. This is useful for providing default methods for objects.

Access Control

Object access can be further controlled via roles and user databases.

The Zope authorization model uses roles to control access to objects. As Zope traverses URLs, it checked for __roles__ attributes in the objects it encounters. The last value found controls access to the published object.

If found, __roles__ should be None or a sequence of role names. If __roles__ is None, then the published object is public. If __roles__ is not None, then the user must provide a user name and password that can be validated by a user database.

Zope Permissions

The Zope platform offers a higher level of abstraction for binding roles to methods with permissions. A permission is a collection of methods. When a permission is bound to a role, it equivanent to assigning the given role to each method in the permission. Permissions allow easier managment through the web.

User Databases

If an object has a __roles__ attribute that is not empty and not None, Zope tries to find a user database to authenticate the user. It searches for user databases by looking for an __allow_groups__ attribute, first in the published object, then in it's container, and so on until a user database is found. When a user database is found, Zope attempts to validate the user against the user database. If validation fails, then Zope will continue searching for user databases until the user can be validated or until no more user databases can be found.

User database objects

The user database may be an object that provides a validate method:

         validate(request, http_authorization, roles)

where:

request

a mapping object that contains request information,

http_authorization

the value of the HTTP Authorization header or None if no authorization header was provided, and

roles

a list of user role names

The validate method returns None if it cannot validate a user and a user object if it can. Normally, if the validate method returns None, Zope will try to use other user databases, however, a user database can prevent this by raising an exception.

If validation succeeds Zope assigns the user object to the request variable, AUTHENTICATED_USER. Zope currently places no restriction on user objects.

Mapping user databases

If the user database is a mapping object, then the keys of the object are role names and values are the associated user groups for the roles. Zope attempts to validate the user by searching for a user name and password matching the user name and password given in the HTTP Authorization header in a groups for role names matching the roles in the published object's __roles__ attribute.

If validation succeeds Zope assigns the user name to the request variable, AUTHENTICATED_USER.

Zope User Folders

The Zope platform provides a default user database object called a User Folder. User folders allow easy managment of users and roles though the web.

Authentication user interface

When a user first accesses a protected object, Zope returns an error response to the web browser that causes a password dialog to be displayed.

Specifying a realm name for basic authentication

You can control the realm name used for Zope's Basic authentication by providing a module variable named __bobo_realm__.

Using the web server to perform authentication

Some web servers cannot be coaxed into passing authentication information to applications. In this case, Zope applications cannot perform authentication. If the web server is configured to authenticate access to a Zope application, then the Zope application can still perform authorization using the REMOTE_USER variable. Zope does this automatically when mapping user databases are used, and custom user databases may do this too.

In this case, it may be necessary to provide more than one path to an application, one that is authenticated, and one that isn't, if public methods and non-public methods are interspursed.

Fixed-attribute objects

For some interesting objects, such as functions, and methods, it may not be possible for applications to set __roles__ attributes. In these cases, the object's parent object may contain attribute object_name__roles__, which will be used as surrogates for the object's __role__ attribute.

Function, method, and class objects

If a published object is a function, method, or class, then the object will be called and the return value of the call will be returned as the HTTP resonse. Calling arguments will be supplied from "environment variables", from URL-encoded form data, if any, and from HTTP cookies by matching argument names defined for the object with variable names.

Accessing request data directly

If the object being called has an argument named REQUEST, then a request object will be passed. Request objects encapsulate request meta data and provide full access to all environment data, form data, cookies, and the input data stream (i.e. body data as a stream).

Providing finer control over responses and stream output

If the object being called has an argument named RESPONSE, then a response object will be passed. This object can be used to specify HTTP headers and to perform stream-oriented output. Rather than returning a result, data may be output by calling the write and flush methods of the response object one or more times. This is useful, for example, when outputing results from a time-consuming task, since partial results may be displayed long before complete results are available.

Argument Types and File upload

Normally, string arguments are passed to called objects. The called object must be prepared to convert string arguments to other data types, such as numbers.

If file upload fields are used, however, then FileUpload objects will be passed instead for these fields. FileUpload objects bahave like file objects and provide attributes for inspecting the uploaded file's source name and the upload headers, such as content-type.

If field names in form data are of the form: name:type, then an attempt will be to convert data from from strings to the indicated type. The data types currently supported are:

float

Python floating point numbers

int

Python integers

long

Python long integers

string

python strings

required

non-blank python strings

date

Date-time values

list

Python list of values, even if there is only one value.

lines

Python list of values entered as multiple lines in a single field

tokens

Python list of values entered as multiple space-separated tokens in a single field

tuple

Python tuple of values, even if there is only one.

method

Augment PATH_INFO with information from the form field. (See "Method Arguments" blow.)

For example, if the name of a field in an input form is age:int, then the field value will be passed in argument, age, and an attempt will be made to convert the argument value to an integer. This conversion also works with file upload, so using a file upload field with a name like myfile:string will cause the UploadFile to be converted to a string before being passed to the object.

Method Arguments

Sometimes, it is desireble to control which method is called based on form data. For example, one might have a form with a select list and want to choose which method to call depening on the item chosen. Similarly, one might have multiple submit buttons and want to invoke a different method for each button.

Zope provides a way to select methods using form variables through use of the "method" argument type. The method type allows the request PATH_INFO to be augmented using information from a form item name or value.

If the name of a form field is :method, then the value of the field is added to PATH_INFO. For example, if the original PATH_INFO is foo/bar and the value of a :method field is x/y, then PATH_INFO is transformed to foo/bar/x/y. This is useful when presenting a select list. Method names can be placed in the select option values.

If the name of a form field ends in :method and is longer than 7 characters, then the part of the name before :method is added to PATH_INFO. For example, if the original PATH_INFO is foo/bar and there is a x/y:method field, then PATH_INFO is transformed to foo/bar/x/y. In this case, the form value is ignored. This is useful for mapping submit buttons to methods, since submit button values are displayed and should, therefore, not contain method names.

Only one method field should be provided. If more than one method field is included in the request, the behavior is undefined.

The base HREF is set when method fields are provided. In the above examples, the base HREF is set to .../foo/bar/x. Of course, if, in this example, y was an object with an index_html method, then the base HREF would be reset to .../foo/bar/x/y.

Published objects that are not functions, methods, or classes

If a published object that is not a function, method, or class is accessed, then the object itself will be returned.

Return types

A published object, or the returned value of a called published object can be of any Python type. If the returned value has an asHTML method, then this method will be called to convert the object to HTML, otherwise the returned value will be converted to a string and examined to see if it appears to be an HTML document. If it appears to be an HTML document, then the response content-type will be set to text/html. Otherwise the content-type will be set to text/plain.

If the returned object is None or the string representation of the returned object is an empty string, then the HTTP return status will be set to "No Content", and no body will be returned. On some browsers, this will cause the displayed document to be unchanged.

Base References

In general, in Zope, relative URL references should be interpreted relative to the parent of the published object, to make it easy for objects to provide links to siblings.

If

  • the result of a request is HTML text,

  • the text does not define a base tag in the head portion of the HTML, and

  • The published object had an index_html attribute that was not included in the request URL,

then a base reference will be inserted that is the URL of the published object.

Exception handling

Unhandled exceptions are caught by the object publisher and are translated automatically to nicely formatted HTTP output.

When an exception is raised, the exception type is mapped to an HTTP code by matching the value of the exception type with a list of standard HTTP status names. Any exception types that do not match standard HTTP status names are mapped to "Internal Error" (500). The standard HTTP status names are: "OK", "Created", "Accepted", "No Content", "Multiple Choices", "Redirect", "Moved Permanently", "Moved Temporarily", "Not Modified", "Bad Request", "Unauthorized", "Forbidden", "Not Found", "Internal Error", "Not Implemented", "Bad Gateway", and "Service Unavailable", Variations on these names with different cases and without spaces are also valid.

An attempt is made to use the exception value as the body of the returned response. The object publisher will examine the exception value. If the value is a string that contains some white space, then it will be used as the body of the return error message. It it appears to be HTML, the the error content type will be set to text/html, otherwise, it will be set to text/plain. If the exception value is not a string containing white space, then the object publisher will generate it's own error message.

There are two exceptions to the above rule:

  1. If the exception type is: "Redirect", "Multiple Choices" "Moved Permanently", "Moved Temporarily", or "Not Modified", and the exception value is an absolute URI, then no body will be provided and a Location header will be included in the output with the given URI.

  2. If the exception type is "No Content", then no body will be returned.

When a body is returned, traceback information will be included in a comment in the output. The module variable __bobo_hide_tracebacks__ can be used to control how tracebacks are included. If this variable and false, then tracebacks are included in PRE tags, rather than in comments. This is very handy during debugging.

Redirection

Automatic redirection may be performed by a published object by raising an exception with a type and value of "Redirect" and a string containing an absolute URI.

The default object

If no object is specified in a URI, then the publisher will try to publish the object index_html, if it exists, otherwise the module's doc string will be published.

Pre- and post-call hooks

If a published module defines objects __bobo_before__ or __bobo_after__, then these functions will be called before or after a request is processed. One possible use for this is to acquire and release application locks in applications with background threads.

Curve graphic