home contents changes options help subscribe edit (external edit)

(Source: Building Dynamic Websites With Zope:chap3.html#ZPublisher )

ZPublisher is the component of the Zope framework that is responsible for the following tasks:

  1. build special objects REQUEST and [RESPONSE]?,
  2. fetch arguments, whether in the query string of the request locator (if the request method is GET or HEAD) or the request body (for other request methods), and decode them, if necessary,
  3. convert and/or package request arguments based on type suffixes of the argument names,
  4. resolve the path in the request locator into an object. This is called traversal,
  5. initiate user authentication,
  6. call the object or method located during traversal with the parameters required or available,
  7. handle any exceptions raised during this process.


These steps in detail

  1. Build special objects REQUEST and RESPONSE

    REQUEST will contain the complete details about the request. RESPONSE will later generate the HTTP response. Its methods can be used by application specific parts to influence this generation. Both objects will be described in detail in the next section.

  2. Fetch arguments

    The request can contain arguments to further specify what should be done or provide data for the action. For GET and HEAD requests, arguments are contained in the query string, for other request methods in the request body. Parameters are often encoded with different encoding schemes and can be serialized in different ways. ZPublisher fetches and decodes them as necessary.

  3. Convert and package arguments

    With the exception of files, all HTTP parameter values are strings. Often, however, functions need different data types as arguments: numbers, dates, structures. Of course, the functions could implement conversion from strings to the required data types themselves. However, it is nice to have this centralized. ZPublisher can provide the required conversions. It looks at type suffixes in the argument names and interprets them as requests to either convert the argument value to the given type or to package it with other values into a larger type. For example x:int=1 tells ZPublisher to convert the string value 1 into the integer 1 and associate it with the argument x. A single name can carry several type suffixes, for example x:int:list=1. The result is that the parameter x is defined with a list as value. The list has a single element, the integer 1.

    ZPublisher recognizes different kinds of suffixes: converters, packagers, actions, controllers. Usually, names should have at most one suffix from each kind. Thus, there should not be two converter suffixes, but a converter and a packager is okay[24]?. The order in which suffixes from different kinds appear is not significant.

    1. 1. Converters

      Converters convert the value into a given type and raise an exception, if this is impossible. All converters accept file values, too. Such files are read to obtain a string that is then converted. Zope supports the following converters:

      float, int, long, string

      converts into the indicated Python types

      date

      converts into a DateTime object. The value may be any string accepted by the DateTime constructor. It includes date strings in any form unambiguously recognized in the US and may have an optional time part. Look into the API reference in Zope's help system for details.

      tokens

      convert into a list of strings by splitting the value at whitespace

      text

      normalizes line endings. This may be useful for textarea values, as MS Windows and Unix have different line ending conventions.

      lines

      converts into a list of strings by splitting at line boundaries

      required

      converts into a string and raises an exception, if the string is empty

      boolean

      converts into a boolean, mapping the empty value to false and any other value to true[25]?

    2. 2. Packagers

      Packagers pack several parameter definitions with the same or related names into larger structures to make them easier to access. Zope supports the following packagers:

      list

      package all parameter values with the current parameter name into a list. In fact, this is the default, as soon as the request contains two or more definitions with the same name. Use the list packager, to get a list, even if the request contains only a single parameter definition for the given name. You will use this for form fields corresponding to multiple selections in order to handle the selection of a single or multiple items in a uniform way. Note, that the case "no items selected" must still be handled specially as in this case, the form control is unsuccessful and there is no parameter definition for it in the request.

      tuple

      package all parameter values with the current parameter name into a Python tuple. Tuples are very similar to lists but are read only, which Python calls immutable.

      record

      The current parameter name must have the form name.attribute The record packager collects such parameter definitions with the same name part into a record with the respective attributes and makes it available under name. If, for example, there are parameter definitions person.name:record=dieter person.email:record=dieter@handshake.de, then a record is build under the name person with attributes name and email and values dieter and dieter@handshake.de, respectively.

      records

      like record but it constructs a list of records. It seems magically for me how it determines when it should start a new record.

    3. 3. Actions

      Usually, ZPublisher calls the object selected during traversal to generate the HTTP response. If, however, the request contains an action, then this action determines the object to be called.

      Actions can have too forms: name:action_suffix=value or action_suffix=value. In the first case, name designates the object to be called and value is ignored; in the second case, value designates the object. Usually, the first form is used in form buttons, while the second form is used when the form action is to be determined by a Javascript. In both cases, the object designation can be a sequence of path segments, separated by /. It is interpreted in the context of the object determined by traversal. Its effect is very similar to an extension of the request locator path by the object designator. The feature exists to make processing of forms with more than one button easier. Each button can directly specify the method implementing its operation.

      There are two different types of actions: default and specific action. A default action can be overridden by a specific action. The default action uses the type suffix default_method (or its alias default_action) while the specific action uses method (or its alias action).

    4. 4. Controllers

      Controllers control, how ZPublisher processes the given parameter definition. ZPublisher implements the following controllers:

      default

      The definition defines a default value that should be used, when there is no other definition for the same parameter name. This feature is often used for checkboxes. Usually, an unchecked checkbox is not successful. It, therefore, will not contribute to the form data incorporated in the request making it difficult to reset the value corresponding to the checkbox. The default controller allows to provide the reset value for this case.

      ignore_empty

      The definition is ignored, if its value is empty. This allows to make use of default parameter values of Python functions instead of this definition.

  4. Traversal

    During traversal, ZPublisher traverses the Web site guided by the path component in the request's resource locator. We saw that an URI's path is a sequence of path segments.

    ZPublisher performs a sequence of traversal steps, usually one for each path segment. In each step, ZPublisher starts with an object, the current object, and has a sequence of path segments still to be traversed. It interprets its first segment as an accessor in the current object's context to get the next object. Usually, the next traversal step will use this object as current object and the segment sequence with the first segment removed. The process stops, when either all path segments have been processed or the current path segment does not access a new object[26]?. The second case usually indicates an error[27]?. ZPublisher starts the traversal with the root object and the complete request locator's path.

    If there is an object index_html accessible in the context of the object located during a successful traversal, then ZPublisher will select this index_html; otherwise, it will select the located object. This behavior is similar to that of other Web servers. They will look for an index.html in a context located by the request locator path (usually a folder) and return that.

    The remaining parts of this section are relevant only for product developers. Other readers may skip them.

    ZPublisher provides two traversal hooks. As we said in the introduction, a hook is a step in a procedure where the application can take over control when the normal framework implementation does not fit its needs.

    The first hook is called __before_publishing_traverse__. If defined, it is called at the start of a traversal step. It is defined when the step's current object has such an attribute. The attribute will be called with two arguments, the current object and the request object. Its return value is discarded, thus only its side effects are essential. Usually, it will modify the request object. The modification may be as simple as defining additional parameters or providing defaults. However, the request object also provides methods that change the path segments still to be traversed. Therefore, the hook can drastically change the traversal. This is used for example to implement virtual hosting or to facilitate internationalization. Products that use this hook are for example SiteAccess2? (for virtual hosting) and Localizer (a localization tool).

    The second hook is called __bobo_traverse__. If defined, it customizes the "accessor" notion. As we have seen, during a traversal step, ZPublisher uses the first path segment as an accessor to find the next object in the current object's context. Its default behavior is to first check for an attribute of the given name, then for a (mapping) key, then fails. However, if the current object has an attribute __bobo_traverse__, then this function is called with the request object and the segment as parameters to determine the next object. It can even return a tuple of objects. In this case, the last element defines the next object while the preceeding objects define the path to this object replacing the current object. This hook is used, for example, to implement advanced features of ZSQL methods such as direct traversal.

    During traversal, ZPublisher builds a sequence of objects visited during traversal to the final selected object. It makes the reverse list accessible as the request member PARENTS. PARENTS[0]? is the object's parent, the object visited before this object; PARENTS[1]? is the object's grand parent, and so on. The object itself is made available via the member PUBLISHED.

  5. Initiate Authentication

    Once ZPublisher has determined the object to be called during the traversal, it initiates authentication. It does not authenticate the user itself, but cooperates with other Zope objects, so called UserFolders? to fulfill this task.

    First, ZPublisher determines which roles can call the object. Then, ZPublisher goes back along the chain of nodes it had visited during traversal (but in reverse order). It checks each node, whether it contains a UserFolder? instance and if it does, whether this user folder can authenticate a user with the required roles. If authentication is successful, ZPublisher places the resulting user object as AUTHENTICATED_USER into the REQUEST object. Otherwise, ZPublisher continues its search towards the site root. The highest UserFolder? will return the Anonymous user, if it cannot authenticate the user and calling the object does not require special roles. If ZPublisher has reached the site root without being able to find a user folder that authenticated the user with sufficient privileges to call the object, it raises an Unauthorized exception. If not overridden by application specific code (e.g. special user folders), such an exception is turned into an "Unauthorized" HTTP response. Such an HTTP response causes the browser to pop up a login dialog.

  6. Call object/method

    Now, that traversal has determined the object to call and the necessary authorization is checked, ZPublisher can call the object.

    ZPublisher looks into the object and determines what parameters are mandatory or optional for the call. It then looks into the REQUEST object and then the objects context, in this order, to find such parameters. It then calls the object with the parameters found, raising an exception if a mandatory parameter has not been found.

    ZPublisher calls the object inside a transaction. This makes is possible to undo most types of side effects of the call in case it should fail. If the call raises an exception, the transaction is aborted. When the call returns without exception, the transaction is committed and other requests can see potential effects by this call.

  7. Handle errors

    ZPublisher handles all errors that occur during its proper operation or exceptions raised during the object call. It turns them into appropriate HTTP responses.



subject:
  ( 24 subscribers )