Attention

You are looking at outdated documentation for version 1.x. A newer version is available.

5.1. WsgiDAV Architecture

This document gives a brief introduction to the WsgiDAV application package (targeted to developers).

See also

WsgiDAV API Doc

5.1.1. WSGI application stack

WsgiDAV is a WSGI application.

WSGI <http://www.python.org/peps/pep-0333.html> stands for Web Server Gateway Interface, a proposed standard interface between web servers and Python web applications or frameworks, to promote web application portability across a variety of web servers. If you are unfamiliar with WSGI, do take a moment to read the PEP.

As most WSGI applications, WsgiDAV consists of middleware which serve as pre-filters and post-processors, and the actual application.

WSGI application stack:

<Request>
  |
<Server> -> wsgidav_app.WsgiDavApp (container)
             |
             +-> debug_filter.WsgiDavDebugFilter (middleware, optional)
                   |
                 error_printer.ErrorPrinter (middleware)
                   |
                 http_authenticator.HTTPAuthenticator (middleware)
                   |           \- Uses a domain controller object
                   |
                 dir_browser.WsgiDavDirBrowser (middleware, optional)
                   |
                 request_resolver.RequestResolver (middleware)
                   |
                   *-> request_server.RequestServer (application)
                               \- Uses a DAVProvider object
                                   \- Uses a lock manager object
                                      and  a property  manager object

This is default stack. Middleware order can be configured using middleware_stack option. You can write your own or extend existing middleware and place it on middleware stack.

See the following sections for details.

5.1.2. WsgiDavApp

WSGI container, that handles the HTTP requests. This object is passed to the WSGI server and represents our WsgiDAV application to the outside.

On init:

Use the configuration dictionary to initialize lock manager, property manager, domain controller.

Create a dictionary of share-to-provider mappings.

Initialize middleware objects and RequestResolver and setup the WSGI application stack.

For every request:

Find the registered DAV provider for the current request.

Add or modify info in the WSGI environ:

environ[“SCRIPT_NAME”]
Mount-point of the current share.
environ[“PATH_INFO”]
Resource path, relative to the mount path.
environ[“wsgidav.provider”]
DAVProvider object that is registered for handling the current request.
environ[“wsgidav.config”]
Configuration dictionary.
environ[“wsgidav.verbose”]
Debug level [0-3].

Log the HTTP request, then pass the request to the first middleware.

Note: The OPTIONS method for the ‘*’ path is handled directly.

See Developers info for more information about the WsgiDAV architecture.

5.1.3. WsgiDavDebugFilter

WSGI middleware used for debugging (optional).

This module dumps request and response information to the console, depending on current debug configuration.

On init:
Define HTTP methods and litmus tests, that should turn on the verbose mode (currently hard coded).
For every request:

Increase value of environ['verbose'], if the request should be debugged. Also dump request and response headers and body.

Then pass the request to the next middleware.

These configuration settings are evaluated:

verbose

This is also used by other modules. This filter adds additional information depending on the value.

verbose Effect
0 No additional output.
1 No additional output (only standard request logging).
2 Dump headers of all requests and responses.
3 Dump headers and bodies of all requests and responses.
debug_methods

Boost verbosity to 3 while processing certain request methods. This option is ignored, when verbose < 2.

Configured like:

debug_methods = ["PROPPATCH", "PROPFIND", "GET", "HEAD","DELETE",
                 "PUT", "COPY", "MOVE", "LOCK", "UNLOCK",
                 ]
debug_litmus

Boost verbosity to 3 while processing litmus tests that contain certain substrings. This option is ignored, when verbose < 2.

Configured like:

debug_litmus = ["notowner_modify", "props: 16", ]

See Developers info for more information about the WsgiDAV architecture.

5.1.4. ErrorPrinter

Middleware error_printer.ErrorPrinter Handle DAV exceptions and internal errors.

On init:
Store error handling preferences.
For every request:
Pass the request to the next middleware. If a DAV exception occurs, log info, then pass it on. Internal exceptions are converted to HTTP_INTERNAL_ERRORs.

5.1.5. HTTPAuthenticator

Middleware http_authenticator.HTTPAuthenticator Uses a domain controller to establish HTTP authentication.

On init:
Store the domain controller object that is used for authentication.
For every request:

if authentication is required and user is not logged in: return authentication response.

Else set these values:

``environ['httpauthentication.realm']``
``environ['httpauthentication.username']``

5.1.6. WsgiDavDirBrowser

Middleware dir_browser.WsgiDavDirBrowser Handles GET requests on collections to display a HTML directory listing.

On init:

For every request:

If path maps to a collection:
Render collection members as directory (HTML table).

5.1.7. RequestResolver

Middleware request_resolver.RequestResolver Find the mapped DAV-Provider, create a new RequestServer instance, and dispatch the request.

On init:

Store URL-to-DAV-Provider mapping.

For every request:

Setup environ["SCRIPT_NAME"] to request realm and and environ["PATH_INFO"] to resource path.

Then find the registered DAV-Provider for this realm, create a new RequestServer instance, and pass the request to it.

Note: The OPTIONS method for ‘*’ is handled directly.

5.1.8. RequestServer

Application request_server.RequestServer Handles one single WebDAV request.

On init:

Store a reference to the DAV-Provider object.

For every request:

Handle one single WebDAV method (PROPFIND, PROPPATCH, LOCK, …) using a DAV-Provider instance. Then return the response body or raise an DAVError.

Note: this object only handles one single request.