Author: ts
Date: Fri Feb 29 12:42:03 2008
New Revision: 7465
Log:
- Finished design draft for If header implementation with a lock plugin.
# Note the warning and note hints in there.
Modified:
trunk/Webdav/design/design-1.1.txt
Modified: trunk/Webdav/design/design-1.1.txt
==============================================================================
--- trunk/Webdav/design/design-1.1.txt [iso-8859-1] (original)
+++ trunk/Webdav/design/design-1.1.txt [iso-8859-1] Fri Feb 29 12:42:03 2008
@@ -195,8 +195,8 @@
{
public function __construct(
array $lockTokens = array(),
- array $eTags = array(),
- bool $negated = false
+ array $eTags = array(),
+ bool $negated = false
);
property-read array $lockTokens;
@@ -209,8 +209,160 @@
defined to be negated ($negated === true). The combination represented by such
an object is a logical AND combination.
-Usage examples
---------------
+Code examples
+-------------
+
+Some small code examples to illustrate the above class design will be showen
+here.
+
+::
+
+ COPY /resource1 HTTP/1.1
+ Host: www.foo.bar
+ Destination: http://www.foo.bar/resource2
+ If: <http://www.foo.bar/resource1> (<locktoken:a-write-lock-token>
+ [W/"A weak ETag"]) (["strong ETag"])
+ <http://www.bar.bar/random>(["another strong ETag"])
+
+This example shows a tagged list in the If header, which will be parsed into an
+instance of ezcWebdavIfHeaderTaggedList will be created from it in the
+`Transport layer`_. The access to this object in the backend or the lock plugin
+will look as follows: ::
+
+ $res1items = $ifHeader['/resource1'];
+
+ $res2items = $ifHeader['/resource2'];
+
+ $randomItems = $ifHeader['/random'];
+
+The $res1items variable will contain an array reflecting the conditions
+specified for http://www.foo.bar/resource1. The $res2items variable will
+contain an empty array since no conditions were defined for this resource.
+While the $randomItems variable should normally not be requested (since the
+resource is not affected) it would contain the corresponding list items for the
+http://www.bar.bar/random resource.
+
+In contrast, the following reqeuest would return an instance of
+ezcWebdavIfHeaderNoTagList for the contained If header: ::
+
+ COPY /resource1 HTTP/1.1
+ Host: www.foo.bar
+ Destination: http://www.foo.bar/resource2
+ If: (<locktoken:a-write-lock-token> [W/"A weak ETag"]) (["strong ETag"])
+ (["another strong ETag"])
+
+Taking the same accesses to the corresponding $ifHeader variable as shown above
+will result in all 3 variables containing the same values: All 3 list items
+will be contained, since the If header does not use tagging to specify which
+resources are affected by the conditions.
+
+Plugin
+======
+
+If the lock plugin is active, it needs to hook into every affected request (see
+`Affected base methods`_) and check the If header conditions. The check does
+not only affect the checking of locktoken conditions, but also the check of
+etag validation, because both condition types are combineable.
+
+The procedure (in pseudo code) is as follows: ::
+
+ lock backend;
+ foreach ( <range of affected resources> as <basse resource> )
+ {
+ create propfind request for <base resource>;
+ set request properties to <getetag> and <lockdiscovery>;
+ set depth according to incoming request;
+ send request to backend;
+ foreach ( <resources in response> as <resource> )
+ {
+ if ( <resource> does not conform to If header )
+ {
+ return <precondition failed response>;
+ }
+ }
+ }
+ discard If header;
+ unlock backend;
+
+The If header needs to be discarded after correct validation of all entity
+tag/lock token conditions. This avoids that the backend checks for the entity
+tag conditions a second time.
+
+.. Note::
+ The checking of both (lock token and entity tag) conditions is necessary in
+ this case, although it results in a small part of code-duplication.
+
+.. Warning::
+ The behaviour showen here does not conform to 100% with the WebDAV RFC,
+ which states that the "If header is intended to have similar functionality
+ to the If- Match header defined in section 14.25 of [RFC2068]". If this is
+ taken literally, the lock plugin would need to check if a request would fail
+ without the If header before checking the If header itself. This would
+ result in unmanageable overhead and code duplication.
+
+.. Warning::
+ Actually the backend would have need to be locked completly, in case an If
+ header occured and was succesfully checked by the lock plugin. This complete
+ lock must be held until the corresponding response was created by the
+ backend. Else there is a race condition in the time frame after the lock
+ checking until the backend starts processing. This can lead to extremly
+ strange results in high-load environments.
+
+Backend layer
+=============
+
+The backend receives the parsed If header as described in the `Transport
+layer`_ section through the $headers property of the request object. We cannot
+enforce the honoring of the If header, so back ends do not neccessarily honor
+them. However, it should be properly documented that this header exists and is
+must be honored if shipped with a request.
+
+If a backend takes care for the header, it may only use the $eTag and $negated
+properties and must ignore the $lockTokens property. The latter one is used
+exclusively in the lock plugin. In case the lock plugin is active, the back end
+should never receive any If header. The If header will then be processed
+exclusively by the lock plugin.
+
+If the backend pays attention to the If header, it must honor it for every
+request and every resource path that is accessed during execution of the
+request. To include the checking of the If header into request processing the
+following algorith must be used (pseudo-code): ::
+
+ lock backend;
+ if ( preconditions for request without If header are not fulfilled )
+ {
+ return <corresponding error response>;
+ }
+ foreach ( <affected resources> as <resource> )
+ {
+ if ( If header not fulfilled for <resource> )
+ {
+ return <precondition failed error response>;
+ }
+ }
+ process request;
+ unlock backend;
+ return <corresponding response>;
+
+
+The backend does not need to take care of If headers, if the lock plugin is
+installed. In this case, the lock plugin will take over the complete check for
+the If headers conditions and remove the header from the request object
+afterwards.
+
+Infrastructure
+==============
+
+The ezcWebdavRequest class does currently not support the removal of headers as
+required by the lock plugin. A method ::
+
+ public removeHeader( $headerName )
+
+needs therefore to be added. This method also needs to invalidate the headers
+internally in the class, so that a manual revalidation using validateHeaders()
+needs to occur. Since the lock plugin will remove the If header before the
+request object passes ezcWebdavServer, the headers are validated anyways there.
+
Entity tag support
^^^^^^^^^^^^^^^^^^
--
svn-components mailing list
[email protected]
http://lists.ez.no/mailman/listinfo/svn-components