RFC 2518

HTTP Extensions for Distributed Authoring -- WEBDAV

๐Ÿ“… published February 1999, from ietf

RFC 2518: HTTP Extensions for Distributed Authoring, aka WEBDAV ๐ŸŽ€

okay bestie, this is the RFC that taught the web how to be a shared folder ๐Ÿ“โœจ it's a Standards Track doc from February 1999, and the crew behind it is giving: Y. Goland (Microsoft), E. Whitehead (UC Irvine), A. Faizi (Netscape), S. Carter (Novell), and D. Jensen (Novell). it was written in the Network Working Group, and its title block doesn't list anything it obsoletes or updates, so it's standing on its own ๐Ÿ’…

Status of this Memo โœจ

this doc is an Internet standards track protocol for the Internet community, and it's literally asking for discussion and suggestions to make it better ๐Ÿซถ if you want to know where this protocol stands right now, check the current edition of the "Internet Official Protocol Standards" (STD 1). and the memo can be distributed with no limits ๐Ÿฆ‹

Copyright (C) The Internet Society (1999). All Rights Reserved. ๐Ÿ’œ

Abstract

okay so the big idea is this ๐ŸŒธ the doc defines a bunch of methods, headers, and content-types that sit on top of HTTP/1.1. they help you manage resource properties, make and handle resource collections, play with the namespace, and lock resources so people don't crash into each other ๐Ÿ”’ (that last part is the collision avoidance era, iykyk ๐Ÿ˜ญ)

Table of Contents ๐Ÿงš

ABSTRACT............................................................1
1 INTRODUCTION .....................................................5
2 NOTATIONAL CONVENTIONS ...........................................7
3 TERMINOLOGY ......................................................7
4 DATA MODEL FOR RESOURCE PROPERTIES ...............................8
4.1  The Resource Property Model ...................................8
4.2  Existing Metadata Proposals ...................................8
4.3  Properties and HTTP Headers ...................................9
4.4  Property Values ...............................................9
4.5  Property Names ...............................................10
4.6  Media Independent Links ......................................10
5 COLLECTIONS OF WEB RESOURCES ....................................11
5.1  HTTP URL Namespace Model .....................................11
5.2  Collection Resources .........................................11
5.3  Creation and Retrieval of Collection Resources ...............12
5.4  Source Resources and Output Resources ........................13
6 LOCKING .........................................................14
6.1  Exclusive Vs. Shared Locks ...................................14
6.2  Required Support .............................................16
6.3  Lock Tokens ..................................................16
6.4  opaquelocktoken Lock Token URI Scheme ........................16
 6.4.1  Node Field Generation Without the IEEE 802 Address ........17
6.5  Lock Capability Discovery ....................................19
6.6  Active Lock Discovery ........................................19
6.7  Usage Considerations .........................................19
7 WRITE LOCK ......................................................20
7.1  Methods Restricted by Write Locks ............................20
7.2  Write Locks and Lock Tokens ..................................20
7.3  Write Locks and Properties ...................................20
7.4  Write Locks and Null Resources ...............................21
7.5  Write Locks and Collections ..................................21
7.6  Write Locks and the If Request Header ........................22
 7.6.1  Example - Write Lock ......................................22
7.7  Write Locks and COPY/MOVE ....................................23
7.8  Refreshing Write Locks .......................................23
8 HTTP METHODS FOR DISTRIBUTED AUTHORING ..........................23
8.1  PROPFIND .....................................................24
 8.1.1  Example - Retrieving Named Properties .....................25
 8.1.2  Example - Using allprop to Retrieve All Properties ........26
 8.1.3  Example - Using propname to Retrieve all Property Names ...29
8.2  PROPPATCH ....................................................31
 8.2.1  Status Codes for use with 207 (Multi-Status) ..............31
 8.2.2  Example - PROPPATCH .......................................32
8.3  MKCOL Method .................................................33
 8.3.1  Request ...................................................33
 8.3.2  Status Codes ..............................................33
 8.3.3  Example - MKCOL ...........................................34
8.4  GET, HEAD for Collections ....................................34
8.5  POST for Collections .........................................35
8.6  DELETE .......................................................35
 8.6.1  DELETE for Non-Collection Resources .......................35
 8.6.2  DELETE for Collections ....................................36
8.7  PUT ..........................................................36
 8.7.1  PUT for Non-Collection Resources ..........................36
 8.7.2  PUT for Collections .......................................37
8.8  COPY Method ..................................................37
 8.8.1  COPY for HTTP/1.1 resources ...............................37
 8.8.2  COPY for Properties .......................................38
 8.8.3  COPY for Collections ......................................38
 8.8.4  COPY and the Overwrite Header .............................39
 8.8.5  Status Codes ..............................................39
 8.8.6  Example - COPY with Overwrite .............................40
 8.8.7  Example - COPY with No Overwrite ..........................40
 8.8.8  Example - COPY of a Collection ............................41
8.9  MOVE Method ..................................................42
 8.9.1  MOVE for Properties .......................................42
 8.9.2  MOVE for Collections ......................................42
 8.9.3  MOVE and the Overwrite Header .............................43
 8.9.4  Status Codes ..............................................43
 8.9.5  Example - MOVE of a Non-Collection ........................44
 8.9.6  Example - MOVE of a Collection ............................44
8.10 LOCK Method ..................................................45
 8.10.1 Operation .................................................46
 8.10.2 The Effect of Locks on Properties and Collections .........46
 8.10.3 Locking Replicated Resources ..............................46
 8.10.4 Depth and Locking .........................................46
 8.10.5 Interaction with other Methods ............................47
 8.10.6 Lock Compatibility Table ..................................47
 8.10.7 Status Codes ..............................................48
 8.10.8 Example - Simple Lock Request .............................48
 8.10.9 Example - Refreshing a Write Lock .........................49
 8.10.10 Example - Multi-Resource Lock Request ....................50
8.11 UNLOCK Method ................................................51
 8.11.1 Example - UNLOCK ..........................................52
9 HTTP HEADERS FOR DISTRIBUTED AUTHORING ..........................52
9.1  DAV Header ...................................................52
9.2  Depth Header .................................................52
9.3  Destination Header ...........................................54
9.4  If Header ....................................................54
 9.4.1  No-tag-list Production ....................................55
 9.4.2  Tagged-list Production ....................................55
 9.4.3  not Production ............................................56
 9.4.4  Matching Function .........................................56
 9.4.5  If Header and Non-DAV Compliant Proxies ...................57
9.5  Lock-Token Header ............................................57
9.6  Overwrite Header .............................................57
9.7  Status-URI Response Header ...................................57
9.8  Timeout Request Header .......................................58
10  STATUS CODE EXTENSIONS TO HTTP/1.1 ............................59
10.1 102 Processing ...............................................59
10.2 207 Multi-Status .............................................59
10.3 422 Unprocessable Entity .....................................60
10.4 423 Locked ...................................................60
10.5 424 Failed Dependency ........................................60
10.6 507 Insufficient Storage .....................................60
11  MULTI-STATUS RESPONSE .........................................60
12  XML ELEMENT DEFINITIONS .......................................61
12.1 activelock XML Element .......................................61

1. Introduction โœจ

Okay bestie, so this document describes an extension to the HTTP/1.1 protocol that lets clients do remote web content authoring operations ๐Ÿ’…. It gives you a coherent set of methods, headers, request entity body formats, and response entity body formats for four big jobs:

  • Properties: creating, removing, and querying info about Web pages, like their authors, creation dates, etc. You can also link pages of any media type to related pages ๐Ÿ”—.
  • Collections: making sets of documents and getting back a hierarchical membership listing, like a directory listing in a file system ๐Ÿ“.
  • Locking: keeping more than one person from working on a document at the same time ๐Ÿ”’. This stops the "lost update problem", where changes vanish because one author writes over another author's changes without merging them. Major yikes ๐Ÿ˜ญ.
  • Namespace Operations: telling the server to copy and move Web resources ๐Ÿšš.

The requirements and rationale for all this live in a companion document, "Requirements for a Distributed Authoring and Versioning Protocol for the World Wide Web" [RFC2291] ๐Ÿ“š.

The sections below give you the full tour: resource properties (section 4), collections of resources (section 5), and locking operations (section 6). They introduce the abstractions that the WebDAV-specific HTTP methods in section 8, "HTTP Methods for Distributed Authoring", manipulate ๐Ÿงš.

In HTTP/1.1, method parameter info was exclusively encoded in HTTP headers. WebDAV is different: it encodes method parameter info either in an Extensible Markup Language (XML) [REC-XML] request entity body, or in an HTTP header ๐Ÿฆ‹. XML won the job for two reasons. First, you can add extra XML elements to existing structures, which means extensibility. Second, XML can encode info in ISO 10646 character sets, which means internationalization support ๐ŸŒ. As a rule of thumb, parameters go in XML entity bodies when they have unbounded length, or when they may be shown to a human user and therefore need encoding in an ISO 10646 character set. Everything else goes in HTTP headers. Section 9 describes the new HTTP headers used with WebDAV methods ๐ŸŽ€.

XML isn't only for input, either. WebDAV also uses XML to encode the responses from methods, so you get the extensibility and internationalization perks on the way out too, not just on the way in ๐Ÿ’–.

The XML elements used in this specification are defined in section 12 ๐Ÿงฉ.

The XML namespace extension (Appendix 4) is also used here, so new XML elements can be added without fear of colliding with other element names ๐Ÿ™…โ€โ™€๏ธ.

HTTP/1.1 status codes are enough to describe most error conditions WebDAV methods run into, but a few errors don't fit neatly into the existing categories ๐Ÿคทโ€โ™€๏ธ. The new status codes developed for WebDAV methods are defined in section 10. Some WebDAV methods can operate over many resources at once, so the Multi-Status response was introduced to return status info for multiple resources. You'll find it described in section 11 ๐Ÿ“ฆ.

WebDAV uses the property mechanism to store info about the current state of a resource ๐Ÿง . For example, when a lock is taken out on a resource, a lock information property describes the current state of that lock. Section 13 defines the properties used within the WebDAV specification ๐Ÿ“.

To finish off, there are sections on what it means to be compliant with this specification (section 15), on internationalization support (section 16), and on security (section 17) ๐Ÿ›ก๏ธ. Stay tuned, it's about to get spicy ๐ŸŒถ๏ธ.

2. Notational Conventions

Since this document describes a set of extensions to the HTTP/1.1 protocol, the augmented BNF used here to describe protocol elements is exactly the same as the one described in section 2.1 of [RFC2068] ๐Ÿ“. That augmented BNF uses the basic production rules provided in section 2.2 of [RFC2068], so those rules apply to this document too.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [RFC2119] ๐Ÿซถ.

3. Terminology

Here's the vocab you need so we're all on the same page ๐Ÿ“–:

  • URI/URL - A Uniform Resource Identifier and Uniform Resource Locator, respectively. These terms (and the distinction between them) are defined in [RFC2396] ๐Ÿ”—.
  • Collection - A resource that contains a set of URIs, termed member URIs, which identify member resources and meets the requirements in section 5 of this specification ๐Ÿ“.
  • Member URI - A URI which is a member of the set of URIs contained by a collection ๐Ÿงท.
  • Internal Member URI - A Member URI that is immediately relative to the URI of the collection. (The definition of immediately relative is given in section 5.2 ๐Ÿงญ.)
  • Property - A name/value pair that contains descriptive information about a resource ๐Ÿท๏ธ.
  • Live Property - A property whose semantics and syntax are enforced by the server โšก. For example, the live "getcontentlength" property has its value, the length of the entity returned by a GET request, automatically calculated by the server. The server does the math so you don't have to ๐Ÿงฎ.
  • Dead Property - A property whose semantics and syntax are not enforced by the server ๐Ÿ’€. The server only records the value of a dead property, and the client is responsible for maintaining the consistency of its syntax and semantics. Main character client energy ๐Ÿ‘‘.
  • Null Resource - A resource which responds with a 404 (Not Found) to any HTTP/1.1 or DAV method except for PUT, MKCOL, OPTIONS and LOCK ๐Ÿซฅ. A NULL resource MUST NOT appear as a member of its parent collection ๐Ÿšซ.

4. Data Model for Resource Properties โœจ

๐Ÿšจ Heads up, bestie: the sections listed in the IMPORTANT note (12.2 through 23.4) weren't in the text I was given, so I haven't invented them. Send me the original text for those and I'll slay them in the next parts ๐Ÿ’….

4.1. The Resource Property Model

okay so properties are little pieces of data that describe what state a resource is in โœจ basically data about data ๐Ÿค“

They're used in distributed authoring environments so you can discover and manage resources efficiently ๐Ÿ’…. Like, a 'subject' property could let you index every resource by its subject, and an 'author' property could help you find which authors wrote which documents ๐Ÿ“š iconic.

The DAV property model is made of name/value pairs ๐ŸŽ€. The name of a property tells you its syntax and semantics, and it gives you an address to refer to them by ๐Ÿฆ‹.

There are two categories: "live" and "dead" ๐Ÿ’€. A live property has its syntax and semantics enforced by the server. That includes cases where a) the value is read-only and maintained by the server, and b) the value is maintained by the client but the server does syntax checking on submitted values. Every instance of a given live property MUST comply with the definition tied to that property name ๐Ÿ”ฅ. A dead property has its syntax and semantics enforced by the client, and the server just records the value verbatim ๐Ÿซถ.

4.2. Existing Metadata Proposals

Properties have long been essential for maintaining big document repositories ๐Ÿ“š, and lots of current proposals have some notion of a property or talk about web metadata more generally ๐ŸŒธ. These include PICS [REC-PICS], PICS-NG, XML, Web Collections, and several proposals for representing relationships within HTML. Work on PICS-NG and Web Collections got absorbed into the Resource Description Framework (RDF) metadata activity of the World Wide Web Consortium ๐Ÿงš. RDF is a network-based data model with an XML representation of that model ๐Ÿ’œ.

Some proposals come from a digital library perspective ๐Ÿ“–. These include the Dublin Core [RFC2413] metadata set and the Warwick Framework [WF], a container architecture for different metadata schemas. The literature has tons of metadata examples too, like MARC [USMARC], a bibliographic metadata format, and a technical report bibliographic format used by the Dienst system [RFC1807] ๐Ÿ“. Also, the proceedings from the first IEEE Metadata conference describe loads of community-specific metadata sets ๐Ÿ’….

Participants of the 1996 Metadata II Workshop in Warwick, UK [WF], noted that "new metadata sets will develop as the networked infrastructure matures" and "different communities will propose, design, and be responsible for different types of metadata." ๐Ÿซถ These observations hold up. Lots of community-specific sets already exist, and there's real motivation for new forms of metadata, because more and more communities are making their data available in digital form and that needs a metadata format to help with data location and cataloging ๐ŸŒˆ.

4.3. Properties and HTTP Headers

Properties already exist, in a limited sense, in HTTP message headers ๐Ÿ“จ. But in distributed authoring environments you need a relatively large number of properties to describe a resource's state, and setting or returning them all through HTTP headers is inefficient ๐Ÿ˜ญ. So we need a mechanism that lets a principal identify a set of properties it's interested in, then set or retrieve just those ones โœจ.

4.4. Property Values

The value of a property when expressed in XML MUST be well formed. ๐Ÿ’–

XML was picked because it's flexible, self-describing, structured, supports rich schema definitions, and supports multiple character sets ๐ŸŽ€. Its self-describing nature means any property's value can be extended by adding new elements. Older clients won't break on extensions, because they still have the data from the original schema and ignore elements they don't understand ๐Ÿฆ‹. Multiple character sets mean any human-readable property can be encoded and read in a character set the user is familiar with ๐ŸŒ. XML also supports multiple human languages through the "xml:lang" attribute, which handles cases where several languages share the same character set ๐ŸŒธ.

4.5. Property Names

A property name is a universally unique identifier that's associated with a schema, and that schema gives info about the property's syntax and semantics ๐Ÿ”‘.

Because a property's name is universally unique, clients can count on consistent behavior for a particular property across multiple resources, on the same server and across different servers, as long as that property is "live" on those resources and the implementation of the live property is faithful to its definition ๐Ÿ‘‘.

The XML namespace mechanism, which is based on URIs [RFC2396], is used to name properties because it prevents namespace collisions and provides for varying degrees of administrative control ๐Ÿง.

The property namespace is flat, meaning no hierarchy of properties is explicitly recognized. So if a property A and a property A/B both exist on a resource, there's no recognition of any relationship between the two ๐Ÿ™ˆ. A separate specification is expected to eventually come out and address hierarchical properties ๐Ÿ“.

Finally, it's not possible to define the same property twice on a single resource, because that would cause a collision in the resource's property namespace ๐Ÿšซ.

Although HTML resources support links to other resources, the Web needs more general support for links between resources of any media type (media types are also known as MIME types, or content types) ๐Ÿ”—. WebDAV provides such links. A WebDAV link is a special type of property value, formally defined in section 12.4, that lets typed connections be made between resources of any media type ๐Ÿฆ‹. The property value consists of source and destination Uniform Resource Identifiers (URIs), and the property name identifies the link type ๐Ÿ’œ.

5. Collections of Web Resources

This section describes a new type of Web resource, the collection, and talks about how it interacts with the HTTP URL namespace ๐Ÿ“. The purpose of a collection resource is to model collection-like objects (e.g., file system directories) within a server's namespace ๐Ÿ—‚๏ธ.

All DAV compliant resources MUST support the HTTP URL namespace model specified herein. ๐Ÿซถ

5.1. HTTP URL Namespace Model

The HTTP URL namespace is hierarchical, and the hierarchy is delimited with the "/" character ๐ŸŒณ.

An HTTP URL namespace is consistent if it meets the following conditions: for every URL in the HTTP hierarchy, there exists a collection that contains that URL as an internal member. The root, or top-level collection of the namespace under consideration, is exempt from the previous rule ๐Ÿ‘‘.

Neither HTTP/1.1 nor WebDAV require that the entire HTTP URL namespace be consistent. However, certain WebDAV methods are prohibited from producing results that cause namespace inconsistencies ๐Ÿ™….

Although implicit in [RFC2068] and [RFC2396], any resource, including collection resources, MAY be identified by more than one URI ๐Ÿฆ‹. For example, a resource could be identified by multiple HTTP URLs โœจ.

5.2. Collection Resources

A collection is a resource whose state consists of at least a list of internal member URIs and a set of properties, but which may have additional state too, like entity bodies returned by GET ๐Ÿ“‚. An internal member URI MUST be immediately relative to a base URI of the collection. In other words, the internal member URI equals a containing collection's URI plus an additional segment for non-collection resources, or additional segment plus trailing slash "/" for collection resources, where segment is defined in section 3.3 of [RFC2396] ๐Ÿงฉ.

Any given internal member URI MUST only belong to the collection once, i.e., it's illegal to have multiple instances of the same URI in a collection ๐Ÿšซ. Properties defined on collections behave exactly like properties on non-collection resources ๐Ÿ’….

For all WebDAV compliant resources A and B, identified by URIs U and V, for which U is immediately relative to V, B MUST be a collection that has U as an internal member URI. So if the resource with URL http://foo.com/bar/blah is WebDAV compliant and the resource with URL http://foo.com/bar/ is WebDAV compliant, then the resource with URL http://foo.com/bar/ must be a collection and must contain URL http://foo.com/bar/blah as an internal member ๐ŸŒธ.

Collection resources MAY list the URLs of non-WebDAV compliant children in the HTTP URL namespace hierarchy as internal members, but they aren't required to ๐Ÿคทโ€โ™€๏ธ. For example, if the resource with URL http://foo.com/bar/blah is not WebDAV compliant and the URL http://foo.com/bar/ identifies a collection, then http://foo.com/bar/blah may or may not be an internal member of the collection with URL http://foo.com/bar/ ๐Ÿค”.

If a WebDAV compliant resource has no WebDAV compliant children in the HTTP URL namespace hierarchy, then it isn't required to be a collection ๐Ÿ™Œ.

There's a standing convention that when a collection is referred to by its name without a trailing slash, the trailing slash is automatically appended ๐ŸŽ€. Due to this, a resource may accept a URI without a trailing "/" to point to a collection. In this case it SHOULD return a content-location header in the response pointing to the URI ending with the "/". For example, if a client invokes a method on http://foo.bar/blah (no trailing slash), the resource http://foo.bar/blah/ (trailing slash) may respond as if the operation were invoked on it, and should return a content-location header with http://foo.bar/blah/ in it. In general, clients SHOULD use the "/" form of collection names ๐Ÿ’–.

A resource MAY be a collection but not be WebDAV compliant. That is, the resource may comply with all the rules set out in this specification about how a collection is to behave, without necessarily supporting all methods that a WebDAV compliant resource is required to support. In such a case the resource may return the DAV:resourcetype property with the value DAV:collection but MUST NOT return a DAV header containing the value "1" on an OPTIONS response ๐Ÿฅน.

5.3 Creation and Retrieval of Collection Resources ๐ŸŽ€

okay so this spec uses MKCOL to make new collection resources instead of the HTTP/1.1 PUT or POST methods ๐Ÿ’… here's why, bestie:

PUT in HTTP/1.1 is defined to store the request body at the location given by the Request-URI ๐Ÿ“ฆ sure, you could build a description format for a collection and PUT it, but sending that description to the server is lowkey a disaster ๐Ÿ˜ญ if a collection description leaves out some existing resources, the server might read that as "delete those members pls" ๐Ÿ’€ which means PUT is secretly doing DELETE's job now. that changes what PUT means, and it makes it way harder to control DELETE with an access control scheme based on methods ๐Ÿ™ˆ

POST is super open-ended, so yes, you could construct a "create a collection" POST command ๐Ÿคทโ€โ™€๏ธ but it's not it, because then it'd be hard to separate access control for collection creation from every other use of POST ๐Ÿšซ

The exact behavior of GET and PUT on collections gets defined later in this document โœจ

5.4 Source Resources and Output Resources โญ

For lots of resources, the entity returned by a GET matches the persistent state of the resource exactly ๐Ÿ–ผ๏ธ think a GIF file sitting on a disk. in that simple case, the URI where you access the resource is the same URI where its source (the persistent state) lives. same goes for HTML source files the server doesn't process before sending ๐ŸŒธ

but the server can sometimes process HTML resources before they go out as a return entity body ๐Ÿงš for example, a server-side-include directive inside an HTML file might tell the server to swap the directive for another value, like the current date. so now GET gives back (HTML plus date), which is different from the persistent state of the resource (HTML plus directive). typically there's no way to access the HTML resource containing the unprocessed directive ๐Ÿ™ˆ

sometimes the entity GET returns is the output of a data-producing process described by one or more source resources (which might not even have a location in the URI namespace) ๐ŸŒˆ one data-producing process can dynamically generate the state of a potentially huge number of output resources. an example is a CGI script describing a "finger" gateway process that maps part of a server's namespace into finger requests, like http://www.foo.bar.org/finger_gateway/user@host ๐Ÿ’œ

without distributed authoring capabilities, it's totally acceptable to have no mapping of source resource(s) to the URI namespace. honestly, preventing access to the source resource(s) has desirable security benefits ๐Ÿ”’ but if remote editing of the source resource(s) is desired, they should be given a location in the URI namespace. that source location should not be one of the locations where the generated output is retrievable, since in general the server can't tell apart requests for source resources from requests for process output resources ๐Ÿซ  and there's often a many-to-many relationship between source resources and output resources ๐Ÿ”

on WebDAV compliant servers, the URI of the source resource(s) may be stored in a link on the output resource with type DAV:source (see section 13.10 for a description of the source link property) ๐Ÿ”— storing source URIs in links on output resources puts the burden of discovering the source on the authoring client ๐Ÿ•ต๏ธ note that the value of a source link is not guaranteed to point to the correct source. source links may break, or incorrect values may be entered ๐Ÿ’€ also, not all servers will let the client set the source link value. for example, a server that generates source links on the fly for its CGI files will most likely not let a client set that value ๐Ÿ™…โ€โ™€๏ธ

6 Locking ๐Ÿ”

the ability to lock a resource gives you a way to serialize access to it ๐Ÿซถ using a lock, an authoring client can provide a reasonable guarantee that another principal won't modify a resource while it's being edited. that's how a client can prevent the "lost update" problem ๐Ÿ˜ญ

this spec lets locks vary over two client-specified parameters: the number of principals involved (exclusive vs. shared) and the type of access being granted. this document only defines locking for one access type, write ๐Ÿ“ but the syntax is extensible, so locking for other access types can be specified eventually ๐Ÿฆ‹

6.1 Exclusive Vs. Shared Locks ๐Ÿ‘‘

the most basic lock is an exclusive lock. it's a lock where the access right in question is only granted to a single principal. this arbitration is needed because of a desire to avoid having to merge results ๐Ÿ™…โ€โ™€๏ธ

but sometimes the goal of a lock isn't to keep others out of an access right. it's more about giving principals a way to say they intend to exercise their access rights ๐Ÿ’… that's what shared locks are for. a shared lock lets multiple principals receive a lock, so any principal with appropriate access can get one โœจ

with shared locks there are two trust sets that affect a resource. the first is created by access permissions: principals who are trusted (for example, those who may write to the resource) ๐Ÿ’– among principals with access permission to write, the set of principals who've taken out a shared lock also must trust each other, creating a (typically) smaller trust set inside the access permission write set ๐Ÿค

starting from every possible principal on the Internet, in most situations the vast majority won't have write access to a given resource ๐ŸŒ of the small number who do, some may decide to guarantee their edits are free from overwrite conflicts by using exclusive write locks. others may decide they trust their collaborators not to overwrite their work (the potential collaborators being the set of principals with write permission) and use a shared lock, which tells collaborators that a principal may be working on the resource ๐Ÿ“ฃ

the WebDAV extensions to HTTP don't need to provide every communication path principals need to coordinate ๐Ÿ’ฌ with shared locks, principals may use any out-of-band channel to coordinate (face-to-face, written notes, post-it notes on the screen, telephone, Email, etc.) ๐Ÿ“’ the intent of a shared lock is just to let collaborators know who else may be working on a resource ๐Ÿซง

shared locks are included because experience from web distributed authoring systems showed exclusive locks are often too rigid ๐Ÿฅฒ an exclusive lock enforces a particular editing process: take out an exclusive lock, read the resource, perform edits, write the resource, release the lock. the problem is that locks aren't always properly released, like when a program crashes or a lock owner leaves without unlocking the resource ๐Ÿ’€ timeouts and administrative action can both remove an offending lock, but neither may be available when needed: the timeout may be long, or the administrator may not be around ๐Ÿ˜ฉ

6.2 Required Support ๐Ÿซถ

a WebDAV compliant server is not required to support locking in any form. if it does support locking, it may choose to support any combination of exclusive and shared locks for any access types โœจ

the reason for this flexibility is that locking policy hits the very heart of the resource management and versioning systems used by various storage repositories ๐Ÿ—„๏ธ these repositories need control over what sort of locking is made available. for example, some only support shared write locks, others only support exclusive write locks, and yet others use no locking at all ๐Ÿ™ƒ since each system is different enough to merit excluding certain locking features, this spec makes locking the sole axis of negotiation within WebDAV ๐ŸŽฏ

6.3 Lock Tokens ๐ŸŽŸ๏ธ

a lock token is a type of state token, represented as a URI, that identifies a particular lock ๐Ÿ”‘ every successful LOCK operation returns a lock token in the lockdiscovery property in the response body, and you can also find it through lock discovery on a resource ๐Ÿ”

Lock token URIs MUST be unique across all resources for all time ๐ŸŒŸ this uniqueness lets lock tokens be submitted across resources and servers without any fear of confusion ๐Ÿงš

this spec provides a lock token URI scheme called opaquelocktoken that meets the uniqueness requirements. but resources are free to return any URI scheme, as long as it meets the uniqueness requirements ๐ŸŒˆ

having a lock token gives you no special access rights ๐Ÿ™…โ€โ™€๏ธ anyone can find out anyone else's lock token by performing lock discovery. Locks MUST be enforced based upon whatever authentication mechanism the server uses, not based on the secrecy of the token values ๐Ÿ”

6.4 opaquelocktoken Lock Token URI Scheme ๐Ÿฆ‹

the opaquelocktoken URI scheme is designed to be unique across all resources for all time ๐Ÿ•ฐ๏ธ because of that uniqueness, a client may submit an opaque lock token in an If header on a resource other than the one that returned it ๐Ÿ’ซ

All resources MUST recognize the opaquelocktoken scheme and, at minimum, recognize that the lock token does not refer to an outstanding lock on the resource ๐Ÿ‘€

to guarantee uniqueness across all resources for all time, opaquelocktoken requires the use of the Universal Unique Identifier (UUID) mechanism, as described in [ISO-11578] ๐Ÿ†”

opaquelocktoken generators, however, have a choice of how they create these tokens ๐Ÿ“ they can either generate a new UUID for every lock token they create, or they can create a single UUID and then add extension characters. if the second method is selected, the program generating the extensions MUST guarantee that the same extension will never be used twice with the associated UUID ๐Ÿซข

here's the ABNF, bestie ๐ŸŽ€

OpaqueLockToken-URI = "opaquelocktoken:" UUID [Extension]  ; The UUID
   production is the string representation of a UUID, as defined in
   [ISO-11578]. Note that white space (LWS) is not allowed between
   elements of this production.

   Extension = path  ; path is defined in section 3.2.1 of RFC 2068
   [RFC2068]

6.4.1. Node Field Generation Without the IEEE 802 Address

okay so UUIDs (defined in [ISO-11578]) have a "node" field that normally holds one of the IEEE 802 addresses from the server machine ๐Ÿ˜ฌ and as noted in section 17.8, showing a machine's IEEE 802 address comes with a bunch of security risks. so this section gives you a different way to make the "node" field that doesn't use an IEEE 802 address ๐Ÿ” WebDAV servers MAY use this algorithm when they generate UUIDs. the text here is originally from an Internet-Draft by Paul Leach and Rich Salz, and we're giving them credit for it ๐Ÿซถ

the ideal move is to grab a 47 bit cryptographic quality random number and use it as the low 47 bits of the node ID, with the most significant bit of the first octet of the node ID set to 1 ๐Ÿฆ‹ that bit is the unicast/multicast bit, and it's never set in IEEE 802 addresses from network cards. so UUIDs from machines with network cards and UUIDs from machines without them can never collide ๐Ÿ’…

if a system doesn't have a primitive for making cryptographic quality random numbers, don't panic, because most systems have loads of randomness sources lying around โœจ they're system specific, but they often include things like:

  • the percent of memory in use
  • the size of main memory in bytes
  • the amount of free main memory in bytes
  • the size of the paging or swap file in bytes
  • free bytes of paging or swap file
  • the total size of user virtual address space in bytes
  • the total available user address space bytes
  • the size of boot disk drive in bytes
  • the free disk space on boot drive in bytes
  • the current time
  • the amount of time since the system booted
  • the individual sizes of files in various system directories
  • the creation, last read, and modification times of files in various system directories
  • the utilization factors of various system resources (heap, etc.)
  • current mouse cursor position
  • current caret position
  • current number of running processes, threads
  • handles or IDs of the desktop window and the active window
  • the value of stack pointer of the caller
  • the process and thread ID of caller
  • various processor architecture specific performance counters (instructions executed, cache misses, TLB misses)

(Note that it is precisely the above kinds of sources of randomness that are used to seed cryptographic quality random number generators on systems without special hardware for their construction.) ๐Ÿงš

also, stuff like the computer's name and the name of the operating system isn't random at all, but it helps tell the results apart from what other systems come up with ๐ŸŒˆ

the exact algorithm for making a node ID from this data is system specific, since the data available and the functions to get it are super system specific too ๐Ÿ™ˆ BUT, assuming you can smush all the randomness values into one buffer, and you have a cryptographic hash function like MD5, then any 6 bytes of the MD5 hash of the buffer, with the multicast bit (the high bit of the first byte) set, will be an appropriately random node ID ๐Ÿ”ฅ

other hash functions, like SHA-1, can be used too ๐Ÿ“ the only real requirement is that the result is suitably random. in other words, outputs from a set of uniformly distributed inputs have to be uniformly distributed themselves, and a single bit change in the input should be expected to flip about half of the output bits. that's the whole vibe โœจ


6.5. Lock Capability Discovery

okay so server lock support is optional, which means a client trying to lock a resource has two options: it can just try the lock and hope for the best ๐Ÿคž or it can do some kind of discovery to figure out what lock capabilities the server actually supports. that second thing is called lock capability discovery ๐Ÿ” it's different from discovering supported access control types, since some access control types don't have matching lock types at all. a client can check which lock types a server supports by retrieving the supportedlock property ๐Ÿ’œ

Any DAV compliant resource that supports the LOCK method MUST support the supportedlock property. no exceptions bestie ๐Ÿ‘‘


6.6. Active Lock Discovery

picture this: another principal locks a resource you want to access ๐Ÿ˜ค it's super useful for you to find out who that first principal is, and that's exactly what the lockdiscovery property is for ๐Ÿ•ต๏ธโ€โ™€๏ธ it lists all the outstanding locks, describes their type, and, where it's available, gives their lock token ๐ŸŽ€

Any DAV compliant resource that supports the LOCK method MUST support the lockdiscovery property. iconic behaviour ๐Ÿ’…


6.7. Usage Considerations

ngl the locking stuff here helps a lot with preventing lost updates, but it can't guarantee updates will never get lost ๐Ÿ˜ญ check out this disaster scenario:

Two clients A and B are both interested in editing the resource index.html.

  1. Client A is an HTTP client, not a WebDAV client, so it doesn't know how to do locking. ๐Ÿ™ƒ
  2. Client A doesn't lock the document, but it does a GET and starts editing.
  3. Client B does a LOCK, does a GET, and starts editing.
  4. Client B finishes editing, does a PUT, and then an UNLOCK.
  5. Client A does a PUT, overwriting and losing all of B's changes. ๐Ÿ’€

there are a few reasons why the WebDAV protocol itself can't stop this situation ๐Ÿ™ˆ first, it can't force every client to use locking, because it has to stay compatible with HTTP clients that don't understand locking at all. second, it can't require servers to support locking, because repositories come in all kinds of flavours, and some of them rely on reservations and merging instead of locks ๐ŸŒธ and finally, it's stateless, so it can't enforce a sequence like LOCK / GET / PUT / UNLOCK. not me being sad about statelessness ๐Ÿ˜ฉ

WebDAV servers that support locking can make accidental overwrites less likely by requiring clients to lock resources before they modify them โœจ but that kind of server would basically stop HTTP 1.0 and HTTP 1.1 clients from modifying resources at all, so it's a trade-off ๐Ÿซ 

WebDAV clients can be good citizens by doing a lock / retrieve / write / unlock sequence (at least by default) whenever they talk to a WebDAV server that supports locking ๐Ÿฆ‹

HTTP 1.1 clients can be good citizens too, and avoid overwriting other clients' changes, by putting entity tags in If-Match headers on any requests that would modify resources ๐Ÿงš

information managers can also try to prevent overwrites by building client-side procedures that require locking before anyone modifies WebDAV resources ๐ŸŒˆ


7. Write Lock โœจ

okay this section is all about the semantics of the write lock type ๐Ÿ” the write lock is one specific instance of a lock type, and it's the only lock type described in this specification ๐Ÿ‘‘


7.1. Methods Restricted by Write Locks

a write lock MUST stop a principal without the lock from successfully running PUT, POST, PROPPATCH, LOCK, UNLOCK, MOVE, DELETE, or MKCOL on the locked resource ๐Ÿšซ all the other current methods, GET especially, work independently of the lock ๐Ÿ“

note, though, that as new methods get created, someone will have to specify how they interact with a write lock ๐Ÿ™ˆ


7.2. Write Locks and Lock Tokens

a successful request for an exclusive or shared write lock MUST result in a unique lock token being generated and associated with the requesting principal ๐ŸŽ€ so if five principals have a shared write lock on the same resource, there will be five lock tokens, one for each principal. five girlies, five tokens ๐Ÿ’…


7.3. Write Locks and Properties

okay so people without a write lock can't change a property on a resource, but live property values can still change while the resource is locked, because of the requirements in their schemas ๐ŸŒธ

only dead properties and live properties that are defined to respect locks are guaranteed not to change while the resource is write locked ๐Ÿ”’


7.4. Write Locks and Null Resources

it's possible to put a write lock on a null resource, which lets you lock the name ๐Ÿฆ‹

a write locked null resource, which people call a lock-null resource, MUST respond with a 404 (Not Found) or 405 (Method Not Allowed) to any HTTP/1.1 or DAV methods except for PUT, MKCOL, OPTIONS, PROPFIND, LOCK, and UNLOCK ๐Ÿ™…โ€โ™€๏ธ a lock-null resource MUST appear as a member of its parent collection ๐ŸŒˆ it also MUST have all the mandatory DAV properties defined on it. most of those, like all the get* properties, won't have a value, because a lock-null resource doesn't support the GET method ๐Ÿซ  lock-null resources MUST have defined values for lockdiscovery and supportedlock ๐Ÿ’œ

until a method like PUT or MKCOL is successfully run on the lock-null resource, it MUST stay in the lock-null state ๐Ÿงš but once a PUT or MKCOL goes through successfully, the resource stops being in the lock-null state, periodt โœจ

if the resource gets unlocked for any reason, without a PUT, MKCOL, or similar method having been successfully run on it, then the resource MUST go back to the null state ๐Ÿ”„


7.5. Write Locks and Collections

a write lock on a collection, whether it came from a "Depth: 0" or a "Depth: infinity" lock request, stops non-lock owners from adding or removing member URIs of that collection ๐Ÿšง so when a principal does a PUT or POST to create a new resource at a URI that has to be an internal member of a write locked collection (to keep the HTTP namespace consistent), or does a DELETE on a resource whose URI is an existing internal member URI of a write locked collection, the request MUST fail if that principal doesn't have a write lock on the collection ๐Ÿ™…โ€โ™€๏ธ

BUT, if a write lock request goes to a collection that has member URIs for resources currently locked in a way that conflicts with the write lock, the request MUST fail with a 423 (Locked) status code ๐Ÿ˜ค

if a lock owner causes the URI of a resource to be added as an internal member URI of a locked collection, then the new resource MUST be automatically added to the lock ๐Ÿ” this is the only way a resource can get added to a write lock ๐Ÿ’… for example, if the collection /a/b/ is write locked and the resource /c is moved to /a/b/c, then the resource /a/b/c gets added to the write lock ๐ŸŽ€

7.6 Write Locks and the If Request Header โœจ

okay so, if a user agent doesn't have to know about a lock when it asks for something on a locked resource, this drama can happen ๐Ÿ˜ญ. Program A, run by User A, grabs a write lock on a resource. Then Program B, also run by User A, has zero clue about that lock and still does a PUT to the locked resource, and the PUT goes through!! Why? Because locks belong to a principal, not a program, so Program B is using principal A's credentials and is allowed to PUT. BUT if Program B had known about the lock, it would never have overwritten the resource and would've popped up a dialog box to tell the user about the conflict ๐Ÿ’…. So we need a way to stop different programs with the same authorization from accidentally ignoring each other's locks ๐Ÿซถ.

Here's the fix: a lock token MUST be submitted by an authorized principal in the If header for all locked resources that a method may interact with, or the method MUST fail. For example, if a resource is getting moved and both the source and destination are locked, then you need two lock tokens, one for the source and one for the destination ๐Ÿ”.

7.6.1 Example - Write Lock

Request

COPY /~fielding/index.html HTTP/1.1
Host: www.ics.uci.edu
Destination: http://www.ics.uci.edu/users/f/fielding/index.html
If: <http://www.ics.uci.edu/users/f/fielding/index.html>
    (<opaquelocktoken:f81d4fae-7dec-11d0-a765-00a0c91e6bf6>)

Response

HTTP/1.1 204 No Content

In this example, even though both the source and destination are locked, only one lock token needs to be submitted, the one for the destination ๐Ÿฆ‹. That's because a COPY doesn't modify the source resource, so the write lock on the source doesn't affect it at all. Also, user agent authentication already happened through a mechanism outside the HTTP protocol, down in the underlying transport layer ๐ŸŒธ.

7.7 Write Locks and COPY/MOVE

A COPY method invocation MUST NOT duplicate any write locks active on the source. However, like we mentioned before, if the COPY drops the resource into a collection that is locked with "Depth: infinity", then the resource gets added to that lock ๐ŸŽ€.

A successful MOVE request on a write locked resource MUST NOT move the write lock along with the resource. Lowkey though, the resource can still get added to an existing lock at the destination, as specified in section 7.5. For example, if the MOVE makes the resource a child of a collection that is locked with "Depth: infinity", then the resource gets added to that collection's lock ๐Ÿ’œ. Also, if a resource locked with "Depth: infinity" gets moved to a destination inside the same lock's scope (like somewhere in the namespace tree that the lock covers), the moved resource gets added to the lock again โœจ. In both of these examples, as specified in section 7.6, an If header must be submitted containing a lock token for both the source and the destination ๐Ÿ”‘.

7.8 Refreshing Write Locks

A client MUST NOT submit the same write lock request twice. Honestly, a client always knows when it's resubmitting the same lock request, because it has to include the lock token in the If header to make a request for a resource that's already locked ๐Ÿ™ˆ.

However, a client may submit a LOCK method with an If header but without a body. This form of LOCK MUST only be used to "refresh" a lock. Meaning, at minimum, that any timers associated with the lock MUST be re-set โฐ.

A server may return a Timeout header with a lock refresh that is different from the Timeout header returned when the lock was originally requested. Clients may also submit Timeout headers of arbitrary value with their lock refresh requests. And servers, as always, may ignore Timeout headers submitted by the client ๐Ÿงš.

If an error is received in response to a refresh LOCK request, the client SHOULD assume that the lock was not refreshed ๐Ÿ’€.


8 HTTP Methods for Distributed Authoring โœจ

The following new HTTP methods use XML as a request and response format. All DAV compliant clients and resources MUST use XML parsers that are compliant with [REC-XML]. All XML used in either requests or responses MUST be, at minimum, well formed. If a server receives ill-formed XML in a request, it MUST reject the entire request with a 400 (Bad Request). If a client receives ill-formed XML in a response, then it MUST NOT assume anything about the outcome of the executed method, and SHOULD treat the server as malfunctioning ๐Ÿ˜ฑ.

8.1 PROPFIND

The PROPFIND method retrieves properties defined on the resource identified by the Request-URI, if the resource does not have any internal members. Or, if the resource is a collection that has internal member URIs, it retrieves properties defined on the resource identified by the Request-URI and potentially its member resources. All DAV compliant resources MUST support the PROPFIND method and the propfind XML element (section 12.14), along with all XML elements defined for use with that element ๐Ÿ’….

A client may submit a Depth header with a value of "0", "1", or "infinity" with a PROPFIND on a collection resource with internal member URIs. DAV compliant servers MUST support the "0", "1" and "infinity" behaviors. By default, the PROPFIND method without a Depth header MUST act as if a "Depth: infinity" header was included ๐ŸŒˆ.

A client may submit a propfind XML element in the body of the request method, describing what information it wants. It's possible to request particular property values, all property values, or a list of the names of the resource's properties. A client may also choose not to submit a request body. An empty PROPFIND request body MUST be treated as a request for the names and values of all properties ๐Ÿ“.

All servers MUST support returning a response of content type text/xml or application/xml that contains a multistatus XML element describing the results of the attempts to retrieve the various properties ๐Ÿ“ฆ.

If there is an error retrieving a property, then a proper error result MUST be included in the response. Asking for the value of a property that doesn't exist is an error, and it MUST be noted (if the response uses a multistatus XML element) with a response XML element that contains a 404 (Not Found) status value ๐Ÿ™…โ€โ™€๏ธ.

So, the multistatus XML element for a collection resource with member URIs MUST include a response XML element for each member URI of the collection, to whatever depth was requested. Each response XML element MUST contain an href XML element that gives the URI of the resource on which the properties in the prop XML element are defined. Results for a PROPFIND on a collection resource with internal member URIs come back as a flat list, and the order of the entries doesn't matter ๐Ÿง.

For allprop and propname, if a principal doesn't have the right to know whether a particular property exists, then the property should be silently excluded from the response ๐Ÿคซ.

The results of this method SHOULD NOT be cached ๐Ÿšซ.

8.1.1 Example - Retrieving Named Properties

Request

PROPFIND  /file HTTP/1.1
Host: www.foo.bar
Content-type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
  <D:prop xmlns:R="http://www.foo.bar/boxschema/">
       <R:bigbox/>
       <R:author/>
       <R:DingALing/>
       <R:Random/>
  </D:prop>
</D:propfind>

Response

HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:">
  <D:response>
       <D:href>http://www.foo.bar/file</D:href>
       <D:propstat>
            <D:prop xmlns:R="http://www.foo.bar/boxschema/">
                 <R:bigbox>
                      <R:BoxType>Box type A</R:BoxType>
                 </R:bigbox>
                 <R:author>
                      <R:Name>J.J. Johnson</R:Name>
                 </R:author>
            </D:prop>
            <D:status>HTTP/1.1 200 OK</D:status>
       </D:propstat>
       <D:propstat>
            <D:prop><R:DingALing/><R:Random/></D:prop>
            <D:status>HTTP/1.1 403 Forbidden</D:status>
            <D:responsedescription> The user does not have access to
the DingALing property.
            </D:responsedescription>
       </D:propstat>
  </D:response>
  <D:responsedescription> There has been an access violation error.
  </D:responsedescription>
</D:multistatus>

In this example, PROPFIND is run on a non-collection resource, http://www.foo.bar/file. The propfind XML element names four properties whose values are being requested. But only two properties come back, because the principal making the request didn't have enough access rights to see the third and fourth properties ๐Ÿ‘€โœจ.

8.1.2. Example - Using allprop to Retrieve All Properties ๐ŸŽ€

>>Request

PROPFIND  /container/ HTTP/1.1
Host: www.foo.bar
Depth: 1
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
  <D:allprop/>
</D:propfind>

>>Response

HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:">
  <D:response>
       <D:href>http://www.foo.bar/container/</D:href>
       <D:propstat>
            <D:prop xmlns:R="http://www.foo.bar/boxschema/">
                 <R:bigbox>
                      <R:BoxType>Box type A</R:BoxType>
                 </R:bigbox>
                 <R:author>

                      <R:Name>Hadrian</R:Name>
                 </R:author>
                 <D:creationdate>
                      1997-12-01T17:42:21-08:00
                 </D:creationdate>
                 <D:displayname>
                      Example collection
                 </D:displayname>
                 <D:resourcetype><D:collection/></D:resourcetype>
                 <D:supportedlock>
                      <D:lockentry>
                           <D:lockscope><D:exclusive/></D:lockscope>
                           <D:locktype><D:write/></D:locktype>
                      </D:lockentry>
                      <D:lockentry>
                           <D:lockscope><D:shared/></D:lockscope>
                           <D:locktype><D:write/></D:locktype>
                      </D:lockentry>
                 </D:supportedlock>
            </D:prop>
            <D:status>HTTP/1.1 200 OK</D:status>
       </D:propstat>
  </D:response>
  <D:response>
       <D:href>http://www.foo.bar/container/front.html</D:href>
       <D:propstat>
            <D:prop xmlns:R="http://www.foo.bar/boxschema/">
                 <R:bigbox>
                      <R:BoxType>Box type B</R:BoxType>
                 </R:bigbox>
                 <D:creationdate>
                      1997-12-01T18:27:21-08:00
                 </D:creationdate>
                 <D:displayname>
                      Example HTML resource
                 </D:displayname>
                 <D:getcontentlength>
                      4525
                 </D:getcontentlength>
                 <D:getcontenttype>
                      text/html
                 </D:getcontenttype>
                 <D:getetag>
                      zzyzx
                 </D:getetag>
                 <D:getlastmodified>
                      Monday, 12-Jan-98 09:25:56 GMT
                 </D:getlastmodified>
                 <D:resourcetype/>
                 <D:supportedlock>
                      <D:lockentry>
                           <D:lockscope><D:exclusive/></D:lockscope>
                           <D:locktype><D:write/></D:locktype>
                      </D:lockentry>
                      <D:lockentry>
                           <D:lockscope><D:shared/></D:lockscope>
                           <D:locktype><D:write/></D:locktype>
                      </D:lockentry>
                 </D:supportedlock>
            </D:prop>
            <D:status>HTTP/1.1 200 OK</D:status>
       </D:propstat>
  </D:response>
</D:multistatus>

okay so in this one, we PROPFIND the /container/ collection with a Depth: 1 header, which means the request covers the resource itself plus its children ๐Ÿ‘€, and the body asks for allprop, so the server hands back the name and value of every property on each resource ๐Ÿ’…

The collection http://www.foo.bar/container/ has six properties: http://www.foo.bar/boxschema/bigbox, http://www.foo.bar/boxschema/author, DAV:creationdate, DAV:displayname, DAV:resourcetype, and DAV:supportedlock ๐ŸŒธ

The last four are the WebDAV-specific ones, defined in section 13. Since GET isn't supported on this resource, the get* properties (like getcontentlength) don't exist on it at all ๐Ÿ™ˆ The DAV properties tell us the collection was created on December 1, 1997, at 5:42:21PM, in a time zone 8 hours west of GMT (creationdate), is named "Example collection" (displayname), is a collection (resourcetype), and supports exclusive and shared write locks (supportedlock) ๐Ÿ”ฅ

front.html has nine properties: http://www.foo.bar/boxschema/bigbox (another instance of the "bigbox" property type), DAV:creationdate, DAV:displayname, DAV:getcontentlength, DAV:getcontenttype, DAV:getetag, DAV:getlastmodified, DAV:resourcetype, and DAV:supportedlock โœจ

Its DAV properties say it was created on December 1, 1997, at 6:27:21PM, in that same GMT-8 zone, is named "Example HTML resource", is 4525 bytes long, is text/html, has an entity tag of "zzyzx", was last modified on Monday, January 12, 1998, at 09:25:56 GMT, has an empty resource type (so it's not a collection, periodt ๐Ÿ’€), and supports both exclusive and shared write locks ๐Ÿฆ‹


8.1.3. Example - Using propname to Retrieve all Property Names ๐Ÿงš

>>Request

PROPFIND  /container/ HTTP/1.1
Host: www.foo.bar
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<propfind xmlns="DAV:">
  <propname/>
</propfind>

>>Response

HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:">
  <response>
       <href>http://www.foo.bar/container/</href>
       <propstat>
            <prop xmlns:R="http://www.foo.bar/boxschema/">
                 <R:bigbox/>
                 <R:author/>
                 <creationdate/>
                 <displayname/>
                 <resourcetype/>
                 <supportedlock/>
            </prop>
            <status>HTTP/1.1 200 OK</status>
       </propstat>
  </response>
  <response>
       <href>http://www.foo.bar/container/front.html</href>
       <propstat>
            <prop xmlns:R="http://www.foo.bar/boxschema/">
                 <R:bigbox/>
                 <creationdate/>
                 <displayname/>
                 <getcontentlength/>
                 <getcontenttype/>
                 <getetag/>
                 <getlastmodified/>
                 <resourcetype/>
                 <supportedlock/>
            </prop>
            <status>HTTP/1.1 200 OK</status>
       </propstat>
  </response>
</multistatus>

This time we PROPFIND the collection http://www.foo.bar/container/ with a propname element in the body, which means we only want the names of the properties, not their values ๐Ÿซถ There's no Depth header here, so it defaults to "infinity", and we get the property names for the collection and everything underneath it ๐ŸŒˆ

Same as before, the collection has six properties: http://www.foo.bar/boxschema/bigbox, http://www.foo.bar/boxschema/author, DAV:creationdate, DAV:displayname, DAV:resourcetype, and DAV:supportedlock ๐Ÿ“

The member http://www.foo.bar/container/index.html has nine properties: http://www.foo.bar/boxschema/bigbox, DAV:creationdate, DAV:displayname, DAV:getcontentlength, DAV:getcontenttype, DAV:getetag, DAV:getlastmodified, DAV:resourcetype, and DAV:supportedlock ๐Ÿ’œ

This example also shows off XML namespace scoping and the default namespace. Since the xmlns attribute has no prefix (no "shorthand name" letter), the namespace applies to every element inside it by default, so any element that doesn't say which namespace it belongs to is automatically in the DAV: namespace ๐Ÿ‘‘


8.2. PROPPATCH ๐ŸŒธ

PROPPATCH processes the instructions in the request body that set and/or remove properties on the resource identified by the Request-URI ๐ŸŽ€

Every DAV compliant resource MUST support PROPPATCH and MUST process instructions written with the propertyupdate, set, and remove XML elements of the DAV schema. Running these directives is, of course, subject to access control constraints ๐Ÿ”’ DAV compliant resources SHOULD also support setting arbitrary dead properties โœจ

The request body of a PROPPATCH MUST contain the propertyupdate XML element. Instructions MUST be processed in the order they're received (top to bottom) ๐Ÿ“ And here's the all-or-nothing part: instructions MUST either all be executed or none executed. So if any error pops up during processing, every instruction that already ran MUST be undone, and a proper error result gets returned ๐Ÿ˜ญ The nitty-gritty of processing set and remove is in section 12.13.

8.2.1. Status Codes for use with 207 (Multi-Status) ๐Ÿ’…

These are examples of response codes you'd expect in a 207 (Multi-Status) response for this method. Heads up though: unless it's explicitly prohibited, any 2/3/4/5xx series response code may be used in a 207 (Multi-Status) response ๐Ÿ‘€

  • 200 (OK) - The command succeeded. Since a body can mix sets and removes, a 201 (Created) seems inappropriate ๐Ÿ“
  • 403 (Forbidden) - The client, for reasons the server chooses not to specify, can't alter one of the properties ๐Ÿ™ˆ
  • 409 (Conflict) - The client provided a value whose semantics aren't appropriate for the property. This includes trying to set read-only properties ๐Ÿ’€
  • 423 (Locked) - The resource is locked, and the client either isn't a lock owner, or the lock type needs a lock token and the client didn't submit one ๐Ÿ”
  • 507 (Insufficient Storage) - The server didn't have enough space to record the property ๐Ÿงบ

8.2.2 Example - PROPPATCH โœจ

Request
PROPPATCH /bar.html HTTP/1.1
Host: www.foo.com
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:propertyupdate xmlns:D="DAV:"
xmlns:Z="http://www.w3.com/standards/z39.50/">
  <D:set>
       <D:prop>
            <Z:authors>
                 <Z:Author>Jim Whitehead</Z:Author>
                 <Z:Author>Roy Fielding</Z:Author>
            </Z:authors>
       </D:prop>
  </D:set>
  <D:remove>
       <D:prop><Z:Copyright-Owner/></D:prop>
  </D:remove>
</D:propertyupdate>
Response
HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:"
xmlns:Z="http://www.w3.com/standards/z39.50">
  <D:response>
       <D:href>http://www.foo.com/bar.html</D:href>
       <D:propstat>
            <D:prop><Z:Authors/></D:prop>
            <D:status>HTTP/1.1 424 Failed Dependency</D:status>
       </D:propstat>
       <D:propstat>
            <D:prop><Z:Copyright-Owner/></D:prop>
            <D:status>HTTP/1.1 409 Conflict</D:status>
       </D:propstat>
       <D:responsedescription> Copyright Owner can not be deleted or
altered.</D:responsedescription>
  </D:response>
</D:multistatus>

Okay so in this example the client asks the server to set the value of http://www.w3.com/standards/z39.50/Authors and to remove http://www.w3.com/standards/z39.50/Copyright-Owner ๐ŸŽ€. But the Copyright-Owner can't be removed, so no property changes happen at all ๐Ÿ˜ญ. The 424 (Failed Dependency) on Authors is the tea: it would have worked, except it's blocked by that Copyright-Owner conflict ๐Ÿ’….


8.3 MKCOL Method

The MKCOL method is how you make a brand new collection ๐Ÿ“. All DAV compliant resources MUST support the MKCOL method. No exceptions, bestie ๐Ÿซถ.

8.3.1 Request

MKCOL creates a new collection resource at whatever location the Request-URI points to ๐ŸŒธ. If the resource identified by the Request-URI is non-null, then the MKCOL MUST fail ๐Ÿ™…โ€โ™€๏ธ. During MKCOL processing, a server MUST make the Request-URI a member of its parent collection, unless the Request-URI is "/". If no such ancestor exists, the method MUST fail. When the MKCOL operation creates a new collection resource, all ancestors MUST already exist, or the method MUST fail with a 409 (Conflict) status code. For example, if someone asks for /a/b/c/d/ and neither /a/b/ nor /a/b/c/ exists, the request must fail ๐Ÿ’€.

When MKCOL is invoked without a request body, the newly created collection SHOULD have no members โœจ.

A MKCOL request message may contain a message body ๐Ÿงš. The behavior of a MKCOL request with a body is limited to creating collections, members of a collection, bodies of members, and properties on the collections or members. If the server receives a MKCOL request entity type it does not support or understand, it MUST respond with a 415 (Unsupported Media Type) status code. The exact behavior of MKCOL for various request media types is undefined in this document and will be specified in separate documents, so stay tuned ๐Ÿฆ‹.

8.3.2 Status Codes

Responses from a MKCOL request MUST NOT be cached, because MKCOL has non-idempotent semantics ๐Ÿ™ˆ.

  • 201 (Created) - The collection or structured resource was created in its entirety.
  • 403 (Forbidden) - This indicates at least one of two conditions: 1) the server does not allow the creation of collections at the given location in its namespace, or 2) the parent collection of the Request-URI exists but cannot accept members.
  • 405 (Method Not Allowed) - MKCOL can only be executed on a deleted/non-existent resource.
  • 409 (Conflict) - A collection cannot be made at the Request-URI until one or more intermediate collections have been created.
  • 415 (Unsupported Media Type) - The server does not support the request type of the body.
  • 507 (Insufficient Storage) - The resource does not have sufficient space to record the state of the resource after the execution of this method.

8.3.3 Example - MKCOL

This example creates a collection called /webdisc/xfiles/ on the server www.server.org ๐Ÿ›ธ.

Request
MKCOL /webdisc/xfiles/ HTTP/1.1
Host: www.server.org
Response
HTTP/1.1 201 Created

8.4 GET, HEAD for Collections

GET on a collection keeps its usual vibe ๐ŸŒˆ. GET is defined as, "retrieve whatever information (in the form of an entity) is identified by the Request-URI" [RFC2068]. When you GET a collection, you might get the contents of an "index.html" resource, a human-readable listing of the collection, or something else entirely. So the result of a GET on a collection might not match the membership of the collection at all ๐Ÿคทโ€โ™€๏ธ.

HEAD is just a GET without a response message body, so the semantics of HEAD stay the same for collection resources too ๐Ÿ’œ.


8.5 POST for Collections

Here's the deal: what POST actually does is decided by the server and often depends on the specific resource ๐Ÿค”. That makes POST on collections largely undefined, so it can't really be modified in a meaningful way. The semantics of POST stay unmodified when applied to a collection ๐Ÿ’….


8.6 DELETE

8.6.1 DELETE for Non-Collection Resources

If the DELETE method is issued to a non-collection resource whose URIs are an internal member of one or more collections, then during DELETE processing a server MUST remove any URI for the resource identified by the Request-URI from the collections that contain it as a member ๐Ÿงน.

8.6.2 DELETE for Collections

The DELETE method on a collection MUST act as if a "Depth: infinity" header was used on it ๐Ÿ”ฅ. A client MUST NOT submit a Depth header with a DELETE on a collection with any value other than infinity. Not even a little bit ๐Ÿ™…โ€โ™€๏ธ.

DELETE says that the collection in the Request-URI and every resource identified by its internal member URIs are to be deleted ๐Ÿ—‘๏ธ.

If any resource identified by a member URI cannot be deleted, then none of the member's ancestors MUST NOT be deleted, so the namespace stays consistent ๐Ÿซถ. Any headers included with DELETE MUST be applied while processing every resource to be deleted. When the DELETE method has completed processing, it MUST result in a consistent namespace โœจ.

If an error occurs with a resource other than the one identified in the Request-URI, then the response MUST be a 207 (Multi-Status). 424 (Failed Dependency) errors SHOULD NOT be in the 207 (Multi-Status). They can be safely left out, because the client will know that the ancestors of a resource could not be deleted when it gets an error for the ancestor's progeny ๐Ÿง . Additionally, 204 (No Content) errors SHOULD NOT be returned in the 207 (Multi-Status), because 204 (No Content) is the default success code ๐Ÿ“.

8.6.2.1 Example - DELETE

Request
DELETE  /container/ HTTP/1.1
Host: www.foo.bar
Response
HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<d:multistatus xmlns:d="DAV:">
  <d:response>
       <d:href>http://www.foo.bar/container/resource3</d:href>
       <d:status>HTTP/1.1 423 Locked</d:status>
  </d:response>
</d:multistatus>

In this example, the attempt to delete http://www.foo.bar/container/resource3 failed because it's locked and no lock token was submitted with the request ๐Ÿ”’. So the attempt to delete http://www.foo.bar/container/ also failed. The client knows that the attempt to delete http://www.foo.bar/container/ must have also failed, since the parent can not be deleted unless its child has also been deleted ๐Ÿงธ. Even though no Depth header was included, a depth of infinity is assumed because the method is on a collection ๐Ÿ’–.


8.7 PUT

8.7.1 PUT for Non-Collection Resources

A PUT performed on an existing resource replaces the GET response entity of that resource ๐ŸŽ€. Properties defined on the resource may be recomputed during PUT processing, but they aren't otherwise affected. For example, if a server recognizes the content type of the request body, it may be able to automatically extract information that could be profitably exposed as properties ๐Ÿฆ‹.

A PUT that would result in the creation of a resource without an appropriately scoped parent collection MUST fail with a 409 (Conflict) ๐Ÿ™…โ€โ™€๏ธ.

8.7.2 PUT for Collections

As defined in the HTTP/1.1 specification [RFC2068], the "PUT method requests that the enclosed entity be stored under the supplied Request-URI." ๐Ÿ“ฆ Since submitting an entity that represents a collection would implicitly encode creation and deletion of resources, this specification intentionally does not define a transmission format for creating a collection using PUT. Instead, the MKCOL method is defined to create collections ๐Ÿซถ.

When the PUT operation creates a new non-collection resource, all ancestors MUST already exist. If all ancestors do not exist, the method MUST fail with a 409 (Conflict) status code. For example, if resource /a/b/c/d.html is to be created and /a/b/c/ does not exist, then the request must fail ๐Ÿ’€.


8.8 COPY Method

The COPY method makes a duplicate of the source resource, which is identified by the Request-URI, in the destination resource, which is identified by the URI in the Destination header ๐Ÿ‘ฏ. The Destination header MUST be present. How COPY behaves depends on what type of source resource you're working with ๐ŸŒท.

All WebDAV compliant resources MUST support the COPY method. However, supporting COPY doesn't guarantee you can copy every resource ๐Ÿ˜ฌ. For example, separate programs may control resources on the same server. As a result, it may not be possible to copy a resource to a location that appears to be on the same server ๐Ÿ™ƒ.

8.8.1 COPY for HTTP/1.1 resources

When the source resource is not a collection, COPY creates a new resource at the destination whose state and behavior match the source as closely as possible ๐Ÿชž. After a successful COPY invocation, all properties on the source resource MUST be duplicated on the destination resource, subject to modifying headers and XML elements, following the definition for copying properties. The environment at the destination may be different from the source for reasons outside the server's control, such as missing resources needed for correct operation. So it may not be possible to completely duplicate the behavior of the resource at the destination ๐ŸŒ. Subsequent alterations to the destination resource will not modify the source resource, and subsequent alterations to the source resource will not modify the destination resource. Two separate lives, no drama ๐Ÿ’…โœจ.

8.8.2. COPY for Properties

Okay so this bit is all about what happens to properties when you COPY something ๐Ÿ’… Live properties SHOULD be duplicated as identically behaving live properties at the destination resource. If a property can't be copied live, then its value MUST be duplicated, octet-for-octet, into an identically named, dead property on the destination resource, subject to the effects of the propertybehavior XML element ๐ŸŽ€

The propertybehavior XML element is the boss here ๐Ÿ‘‘ It can say that properties get copied on a best-effort basis, that every live property has to be copied successfully or the whole method fails, or that a specific list of live properties has to be copied successfully or the method fails. The propertybehavior XML element is defined in section 12.12 โœจ

8.8.3 COPY for Collections

Main character energy time ๐Ÿฆ‹ A COPY on a collection without a Depth header MUST act as if a Depth header with value "infinity" was included. You're allowed to send a Depth header on a COPY on a collection with a value of "0" or "infinity" ๐Ÿ’– DAV compliant servers MUST support both the "0" and "infinity" Depth header behaviors ๐Ÿซถ

A COPY with depth infinity means the collection identified by the Request-URI gets copied to the location in the Destination header, and all of its internal member resources get copied to locations relative to it, recursively through every level of the collection hierarchy ๐ŸŒณ

A COPY with "Depth: 0" only copies the collection and its properties. It does NOT copy the resources identified by its internal member URIs ๐Ÿ™ˆ

Any headers included with a COPY MUST be applied while processing every resource being copied, except the Destination header ๐Ÿ”ฅ

The Destination header only gives the destination URI for the Request-URI. When it's applied to members of the collection identified by the Request-URI, the Destination value gets modified to match where that member sits in the hierarchy. So if the Request-URI is /a/ with Host header value http://fun.com/ and the Destination is http://fun.com/b/, then when http://fun.com/a/c/d is processed it must use a Destination of http://fun.com/b/c/d ๐Ÿงš

When the COPY method has finished, it MUST have created a consistent namespace at the destination (see section 5.1 for the definition of namespace consistency) ๐Ÿ’… But here's the tea: if an error happens while copying an internal collection, the server MUST NOT copy any resources identified by members of that collection. The server has to skip that whole subtree, because copying it anyway would make an inconsistent namespace ๐Ÿ˜ญ After detecting an error, the COPY operation SHOULD try to finish as much of the original copy as possible. The server should still attempt to copy other subtrees and their members that aren't descendants of the error-causing collection. For example, if an infinite depth copy runs on collection /a/, which contains collections /a/b/ and /a/c/, and an error happens copying /a/b/, an attempt should still be made to copy /a/c/ ๐Ÿ’– Similarly, if there's an error copying a non-collection resource during an infinite depth copy, the server SHOULD try to finish as much of the original copy operation as possible โœจ

If an error happens while executing the COPY method on a resource other than the one identified in the Request-URI, the response MUST be a 207 (Multi-Status) ๐ŸŒธ

Now the drama: the 424 (Failed Dependency) status code SHOULD NOT be returned in a 207 (Multi-Status) response from a COPY method. Those responses can be safely left out, because the client will already know that a resource's progeny couldn't be copied when it gets an error for the parent ๐Ÿ™ƒ Also, 201 (Created) and 204 (No Content) status codes SHOULD NOT be returned as values in 207 (Multi-Status) responses from COPY methods. They can be safely left out too, since they're the default success codes ๐ŸŽ€

8.8.4 COPY and the Overwrite Header

Okay this one is so important ๐Ÿ˜ญ If a resource exists at the destination and the Overwrite header is "T", then before doing the copy, the server MUST perform a DELETE with "Depth: infinity" on the destination resource. If the Overwrite header is set to "F", then the operation will fail ๐Ÿ’€

8.8.5 Status Codes

Here's the lineup of status codes for COPY ๐ŸŒˆ

  • 201 (Created) - The source resource was successfully copied. The copy operation created a brand-new resource โœจ
  • 204 (No Content) - The source resource was successfully copied to a pre-existing destination resource ๐Ÿซง
  • 403 (Forbidden) - The source and destination URIs are the same ๐Ÿ™…โ€โ™€๏ธ
  • 409 (Conflict) - A resource can't be created at the destination until one or more intermediate collections have been created ๐Ÿงฑ
  • 412 (Precondition Failed) - The server couldn't keep the liveness of the properties listed in the propertybehavior XML element, or the Overwrite header is "F" and the state of the destination resource is non-null ๐Ÿ˜ฌ
  • 423 (Locked) - The destination resource was locked ๐Ÿ”’
  • 502 (Bad Gateway) - This may happen when the destination is on another server and that destination server refuses to accept the resource ๐ŸŒ‰
  • 507 (Insufficient Storage) - The destination resource doesn't have enough space to record the state of the resource after this method runs ๐Ÿ’พ

8.8.6 Example - COPY with Overwrite

Let's see this in action ๐Ÿฆ‹ Here, the resource http://www.ics.uci.edu/~fielding/index.html is being copied to http://www.ics.uci.edu/users/f/fielding/index.html. The 204 (No Content) status code tells us the existing resource at the destination got overwritten ๐Ÿ“

Request

COPY /~fielding/index.html HTTP/1.1
Host: www.ics.uci.edu
Destination: http://www.ics.uci.edu/users/f/fielding/index.html

Response

HTTP/1.1 204 No Content

8.8.7 Example - COPY with No Overwrite

Same copy operation, but this time the Overwrite header is set to "F" ๐Ÿ™ˆ You get a 412 (Precondition Failed) back because the destination resource already has a non-null state. Bestie, no overwriting allowed ๐Ÿšซ

Request

COPY /~fielding/index.html HTTP/1.1
Host: www.ics.uci.edu
Destination: http://www.ics.uci.edu/users/f/fielding/index.html
Overwrite: F

Response

HTTP/1.1 412 Precondition Failed

8.8.8 Example - COPY of a Collection

Okay this is the big one with a whole collection ๐Ÿงบ

Request

COPY /container/ HTTP/1.1
Host: www.foo.bar
Destination: http://www.foo.bar/othercontainer/
Depth: infinity
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<d:propertybehavior xmlns:d="DAV:">
  <d:keepalive>*</d:keepalive>
</d:propertybehavior>

Response

HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<d:multistatus xmlns:d="DAV:">
  <d:response>
       <d:href>http://www.foo.bar/othercontainer/R2/</d:href>
       <d:status>HTTP/1.1 412 Precondition Failed</d:status>
  </d:response>
</d:multistatus>

The Depth header isn't needed here, because COPY on a collection already acts like "Depth: infinity" by default ๐ŸŒธ Most resources, plus the collection itself, got copied successfully. But collection R2 failed, most likely because the liveness of its properties couldn't be maintained (that's what the propertybehavior XML element is for). Since there was an error copying R2, none of R2's members were copied. There are no errors listed for those members, thanks to the error minimization rules in section 8.8.3 ๐Ÿ’–

8.9 MOVE Method

MOVE is giving COPY plus cleanup vibes ๐Ÿงš On a non-collection resource, MOVE is the logical equivalent of a copy (COPY), followed by consistency maintenance processing, followed by a delete of the source. All three actions happen atomically โœจ The consistency maintenance step lets the server make updates caused by the move, like changing every URI other than the Request-URI that identifies the source resource so it points to the new destination resource ๐Ÿ”—

So the Destination header MUST be present on all MOVE methods, and it MUST follow all COPY requirements for the COPY part of the MOVE method ๐Ÿ’… All DAV compliant resources MUST support the MOVE method. BUT support for MOVE doesn't guarantee that you can move a resource to any particular destination. Not me being picky ๐Ÿ™ƒ

For example, separate programs may control different sets of resources on the same server. So it might not be possible to move a resource within a namespace that seems to belong to the same server ๐Ÿซ 

If a resource exists at the destination, that destination resource will be DELETEd as a side effect of the MOVE operation, subject to the restrictions of the Overwrite header ๐Ÿ‘€

8.9.1 MOVE for Properties

The behavior of properties on a MOVE, including the effects of the propertybehavior XML element, MUST be the same as specified in section 8.8.2 ๐ŸŽ€

8.9.2 MOVE for Collections

A MOVE with "Depth: infinity" means the collection identified by the Request-URI gets moved to the URI in the Destination header, and all resources identified by its internal member URIs get moved to locations relative to it, recursively through every level of the collection hierarchy ๐ŸŒณ

The MOVE method on a collection MUST act as if a "Depth: infinity" header was used on it. A client MUST NOT submit a Depth header on a MOVE on a collection with any value other than "infinity" ๐Ÿ™…โ€โ™€๏ธ

Any headers included with MOVE MUST be applied while processing every resource being moved, except the Destination header โœจ

The Destination header works the same way it does for COPY on collections ๐Ÿ’–

When the MOVE method has finished, it MUST have created a consistent namespace at both the source and the destination (see section 5.1 for the definition of namespace consistency) ๐Ÿซถ But if an error happens while moving an internal collection, the server MUST NOT move any resources identified by members of the failed collection. The server has to skip the error-causing subtree, because that would create an inconsistent namespace ๐Ÿ˜ญ After detecting the error, the move operation SHOULD try to finish as much of the original move as possible. The server should still attempt to move other subtrees and the resources identified by their members, as long as they aren't descendants of an error-causing collection. For example, if an infinite depth move runs on collection /a/, which contains collections /a/b/ and /a/c/, and an error happens moving /a/b/, an attempt should still be made to move /a/c/ ๐ŸŒธ Similarly, if there's an error moving a non-collection resource as part of an infinite depth move, the server SHOULD try to finish as much of the original move operation as possible ๐Ÿงš

If an error occurs with a resource other than the one identified in the Request-URI, the response MUST be a 207 (Multi-Status) ๐ŸŽ€

Same energy as COPY: the 424 (Failed Dependency) status code SHOULD NOT be returned in the 207 (Multi-Status) response from a MOVE method. Those errors can be safely left out, because the client will already know that a resource's progeny couldn't be moved when it gets an error for the parent ๐Ÿ™ƒ Also, 201 (Created) and 204 (No Content) responses SHOULD NOT be returned as values in 207 (Multi-Status) responses from a MOVE. They can be safely left out too, since they're the default success codes ๐Ÿ’…

8.9.3 MOVE and the Overwrite Header

Okay so if something's already sitting at the destination and the Overwrite header is "T", the server MUST perform a DELETE with "Depth: infinity" on the destination resource before it does the move ๐Ÿงนโœจ. If Overwrite is set to "F" instead, the whole operation fails ๐Ÿ™…โ€โ™€๏ธ no exceptions, bestie.

8.9.4 Status Codes

201 (Created) - The source resource got moved and a brand-new resource was made at the destination ๐ŸŽ€

204 (No Content) - The source resource got moved onto a destination resource that already existed ๐ŸŒธ

403 (Forbidden) _ The source and destination URIs are the same. ๐Ÿ’€ you can't move something onto itself, that's just not it.

409 (Conflict) _ A resource cannot be created at the destination until one or more intermediate collections have been created. ๐Ÿ™ˆ the folders have to exist first, sis.

412 (Precondition Failed) - The server couldn't keep the properties listed in the propertybehavior XML element alive, OR the Overwrite header is "F" and the destination resource's state is non-null. Big vibes of "nope, not happening" ๐Ÿ˜ญ

423 (Locked) - The source or the destination resource was locked ๐Ÿ”’

502 (Bad Gateway) - This can happen when the destination lives on another server and that server refuses to accept the resource ๐ŸŒˆ

8.9.5 Example - MOVE of a Non-Collection

Okay this one is so cute ๐Ÿฆ‹. We're moving http://www.ics.uci.edu/~fielding/index.html over to http://www.ics.uci.edu/users/f/fielding/index.html. If the destination had something in it, that stuff would've been overwritten. But there was nothing there, so the response is 201 (Created) โœจ

>>Request

MOVE /~fielding/index.html HTTP/1.1
Host: www.ics.uci.edu
Destination: http://www.ics.uci.edu/users/f/fielding/index.html

>>Response

HTTP/1.1 201 Created
Location: http://www.ics.uci.edu/users/f/fielding/index.html

8.9.6 Example - MOVE of a Collection

>>Request

MOVE /container/ HTTP/1.1
Host: www.foo.bar
Destination: http://www.foo.bar/othercontainer/
Overwrite: F
If: (<opaquelocktoken:fe184f2e-6eec-41d0-c765-01adc56e6bb4>)
    (<opaquelocktoken:e454f3f3-acdc-452a-56c7-00a5c91e4b77>)
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx
<?xml version="1.0" encoding="utf-8" ?>
<d:propertybehavior xmlns:d='DAV:'>
  <d:keepalive>*</d:keepalive>
</d:propertybehavior>

>>Response

HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<d:multistatus xmlns:d='DAV:'>
  <d:response>
       <d:href>http://www.foo.bar/othercontainer/C2/</d:href>
       <d:status>HTTP/1.1 423 Locked</d:status>
  </d:response>
</d:multistatus>

So in this example the client sent a bunch of lock tokens with the request ๐Ÿ”‘. You need a lock token for every resource, source and destination both, anywhere in the scope of the method, that's locked. Here the right token wasn't sent for http://www.foo.bar/othercontainer/C2/, so /container/C2/ couldn't be moved ๐Ÿ™…โ€โ™€๏ธ. Because copying /container/C2/ errored, none of /container/C2/'s members got copied. But no errors are listed for those members, thanks to the error minimization rules given in section 8.8.3. And user agent authentication already happened through a mechanism outside the scope of the HTTP protocol, in an underlying transport layer ๐Ÿงš


8.10 LOCK Method

The next sections are all about the LOCK method, which takes out a lock of any access type ๐Ÿ”. They only cover the stuff that's specific to LOCK and don't depend on which access type is being requested, so it's giving focus.

Any resource that supports the LOCK method MUST, at minimum, support the XML request and response formats defined here ๐Ÿ“œ.

8.10.1 Operation

A LOCK invocation creates the lock described by the lockinfo XML element on the Request-URI ๐ŸŽฏ. LOCK requests SHOULD have an XML request body with an owner XML element for this lock request, unless it's a refresh request. The LOCK request may also have a Timeout header โฐ.

Clients MUST assume locks can vanish at any time, no matter what the Timeout header says ๐Ÿ˜ณ. The Timeout header only tells you what the server does when nothing "extraordinary" happens. For example, an admin could remove a lock whenever they want, or the system could crash in a way that wipes out its record of the lock ever existing ๐Ÿ’€. The response MUST contain the value of the lockdiscovery property in a prop XML element.

To show which lock token belongs to a brand-new lock, a Lock-Token response header MUST be included in the response for every successful LOCK request that creates a new lock ๐Ÿชช. Heads up, the Lock-Token header won't come back on a successful refresh LOCK request, because no new lock was made ๐Ÿ”„.

8.10.2 The Effect of Locks on Properties and Collections

A lock covers the entire state of the resource, including its body and its associated properties ๐Ÿซถ. So a lock on a resource MUST also lock that resource's properties.

For collections, a lock also changes whether you can add or remove members ๐Ÿ“. How it plays out depends on the type of access control involved.

8.10.3 Locking Replicated Resources

A resource can be reachable through more than one URI ๐ŸŒ. But locks apply to resources, not URIs, so a LOCK request on a resource MUST NOT succeed if it can't be honored by all the URIs that resource is addressable through ๐Ÿ™…โ€โ™€๏ธ.

8.10.4 Depth and Locking

The Depth header may be used with the LOCK method ๐Ÿงญ. Any value other than 0 or infinity MUST NOT be used with the Depth header on a LOCK method. Every resource that supports LOCK MUST support the Depth header too.

A Depth header of 0 just locks the resource on the Request-URI ๐Ÿ”’.

If Depth is set to infinity, the resource on the Request-URI plus all of its internal members, all the way down the hierarchy, get locked ๐ŸŒณ. A successful result MUST return a single lock token that represents all of the locked resources. If an UNLOCK succeeds on that token, every associated resource gets unlocked. If the lock can't be granted to all the resources, a 409 (Conflict) status code MUST be returned, with a response entity body containing a multistatus XML element that describes which resource(s) blocked the lock. So partial success isn't an option ๐Ÿšซ. Either the whole hierarchy gets locked or nothing does ๐Ÿ’….

If a LOCK request has no Depth header, the request MUST act as if a "Depth:infinity" had been submitted ๐Ÿซง.

8.10.5 Interaction with other Methods

How a LOCK interacts with other methods depends on the lock type ๐ŸŽญ. But no matter the lock type, a successful DELETE of a resource MUST cause all of its locks to be removed ๐Ÿ—‘๏ธ.

8.10.6 Lock Compatibility Table

This table shows what happens when a lock request is made on a resource ๐Ÿ“Š.

Current lock state/  |   Shared Lock   |   Exclusive
Lock request         |                 |   Lock
=====================+=================+==============
None                 |   True          |   True
---------------------+-----------------+--------------
Shared Lock          |   True          |   False
---------------------+-----------------+--------------
Exclusive Lock       |   False         |   False*
------------------------------------------------------

Legend: True = lock may be granted. False = lock MUST NOT be granted. *=It is illegal for a principal to request the same lock twice ๐Ÿ™ˆ.

The current lock state of a resource is in the leftmost column, and the lock requests are in the top row. Where a row and column meet, you get the result of that request ๐ŸŽ€. For example, if a shared lock is held on a resource and someone asks for an exclusive lock, the entry is "false", which means the lock must not be granted (lowercase vibes, but the rule's the same: it's a no) ๐Ÿ’€.

8.10.7 Status Codes

200 (OK) - The lock request worked, and the value of the lockdiscovery property is in the body โœจ

412 (Precondition Failed) - The lock token that was included couldn't be enforced on this resource, or the server couldn't satisfy the request in the lockinfo XML element ๐Ÿ˜ญ

423 (Locked) - The resource is locked, so the method got rejected ๐Ÿ”’

8.10.8 Example - Simple Lock Request

>>Request

LOCK /workspace/webdav/proposal.doc HTTP/1.1
Host: webdav.sb.aol.com
Timeout: Infinite, Second-4100000000
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx
Authorization: Digest username="ejw",
   realm="ejw@webdav.sb.aol.com", nonce="...",
   uri="/workspace/webdav/proposal.doc",
   response="...", opaque="..."

<?xml version="1.0" encoding="utf-8" ?>
<D:lockinfo xmlns:D='DAV:'>
  <D:lockscope><D:exclusive/></D:lockscope>
  <D:locktype><D:write/></D:locktype>
  <D:owner>
       <D:href>http://www.ics.uci.edu/~ejw/contact.html</D:href>
  </D:owner>
</D:lockinfo>

>>Response

HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:prop xmlns:D="DAV:">
  <D:lockdiscovery>
       <D:activelock>
            <D:locktype><D:write/></D:locktype>
            <D:lockscope><D:exclusive/></D:lockscope>
            <D:depth>Infinity</D:depth>
            <D:owner>
                 <D:href>
                      http://www.ics.uci.edu/~ejw/contact.html
                 </D:href>
            </D:owner>
            <D:timeout>Second-604800</D:timeout>
            <D:locktoken>
                 <D:href>
            opaquelocktoken:e71d4fae-5dec-22d6-fea5-00a0c91e6be4
                 </D:href>
            </D:locktoken>
       </D:activelock>
  </D:lockdiscovery>
</D:prop>

This example shows a successful exclusive write lock on http://webdav.sb.aol.com/workspace/webdav/proposal.doc ๐Ÿ”. The resource http://www.ics.uci.edu/~ejw/contact.html has contact info for the lock owner. The server runs an activity-based timeout policy on this resource, so the lock automatically gets removed after 1 week (604800 seconds) โณ. Also, the nonce, response, and opaque fields haven't been calculated in the Authorization request header, so don't panic when you see the placeholders ๐Ÿซถ.

8.10.9 Example - Refreshing a Write Lock โœจ

Request
LOCK /workspace/webdav/proposal.doc HTTP/1.1
Host: webdav.sb.aol.com
Timeout: Infinite, Second-4100000000
If: (<opaquelocktoken:e71d4fae-5dec-22d6-fea5-00a0c91e6be4>)
Authorization: Digest username="ejw",
   realm="ejw@webdav.sb.aol.com", nonce="...",
   uri="/workspace/webdav/proposal.doc",
   response="...", opaque="..."
Response
HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:prop xmlns:D="DAV:">
  <D:lockdiscovery>
       <D:activelock>
            <D:locktype><D:write/></D:locktype>
            <D:lockscope><D:exclusive/></D:lockscope>
            <D:depth>Infinity</D:depth>
            <D:owner>
                 <D:href>
                 http://www.ics.uci.edu/~ejw/contact.html
                 </D:href>
            </D:owner>
            <D:timeout>Second-604800</D:timeout>
            <D:locktoken>
                 <D:href>
            opaquelocktoken:e71d4fae-5dec-22d6-fea5-00a0c91e6be4
                 </D:href>
            </D:locktoken>
       </D:activelock>
  </D:lockdiscovery>
</D:prop>

okay so this request is a lock refresh ๐Ÿ”„ it resets any timeouts and keeps the lock alive, bestie ๐Ÿ’– notice that the client asked for an infinite timeout, but the server chose to ignore that ๐Ÿ™ˆ and in this example the nonce, response, and opaque fields haven't been calculated in the Authorization request header ๐Ÿ’…

8.10.10 Example - Multi-Resource Lock Request โœจ

Request
LOCK /webdav/ HTTP/1.1
Host: webdav.sb.aol.com
Timeout: Infinite, Second-4100000000
Depth: infinity
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx
Authorization: Digest username="ejw",
   realm="ejw@webdav.sb.aol.com", nonce="...",
   uri="/workspace/webdav/proposal.doc",
   response="...", opaque="..."

<?xml version="1.0" encoding="utf-8" ?>
<D:lockinfo xmlns:D="DAV:">
  <D:locktype><D:write/></D:locktype>
  <D:lockscope><D:exclusive/></D:lockscope>
  <D:owner>
       <D:href>http://www.ics.uci.edu/~ejw/contact.html</D:href>
  </D:owner>
</D:lockinfo>
Response
HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:">
  <D:response>
       <D:href>http://webdav.sb.aol.com/webdav/secret</D:href>
       <D:status>HTTP/1.1 403 Forbidden</D:status>
  </D:response>
  <D:response>
       <D:href>http://webdav.sb.aol.com/webdav/</D:href>
       <D:propstat>
            <D:prop><D:lockdiscovery/></D:prop>
            <D:status>HTTP/1.1 424 Failed Dependency</D:status>
       </D:propstat>
  </D:response>
</D:multistatus>

this one is a whole vibe ๐Ÿงš the client wants an exclusive write lock on a collection AND all its children ๐Ÿ‘‘ it asks for an infinite-length lock if that's available, otherwise a timeout of 4.1 billion seconds, if available. The request entity body holds the contact info for whoever is taking out the lock, here a web page URL ๐ŸŒธ

the error is a 403 (Forbidden) response on http://webdav.sb.aol.com/webdav/secret ๐Ÿ’€ and because that resource couldn't be locked, none of the resources got locked. Also, the lockdiscovery property for the Request-URI is included, as required ๐ŸŽ€ here it's empty, which means there are no outstanding locks on the resource.

again, the nonce, response, and opaque fields haven't been calculated in the Authorization request header ๐Ÿซถ

8.11 UNLOCK Method

The UNLOCK method removes the lock identified by the lock token in the Lock-Token request header from the Request-URI, and from all other resources included in the lock ๐Ÿฆ‹ if all the resources locked under the submitted lock token can't be unlocked, then the UNLOCK request MUST fail ๐Ÿ˜ญ

Any DAV compliant resource which supports the LOCK method MUST support the UNLOCK method ๐Ÿ’œ

8.11.1 Example - UNLOCK โœจ

Request
UNLOCK /workspace/webdav/info.doc HTTP/1.1
Host: webdav.sb.aol.com
Lock-Token: <opaquelocktoken:a515cfa4-5da4-22e1-f5b5-00a0451e6bf7>
Authorization: Digest username="ejw",
   realm="ejw@webdav.sb.aol.com", nonce="...",
   uri="/workspace/webdav/proposal.doc",
   response="...", opaque="..."
Response
HTTP/1.1 204 No Content

in this example, the lock identified by the lock token "opaquelocktoken:a515cfa4-5da4-22e1-f5b5-00a0451e6bf7" is successfully removed from the resource http://webdav.sb.aol.com/workspace/webdav/info.doc โœ… if that lock covered more than one resource, it gets removed from all of them ๐Ÿ”“ the 204 (No Content) status code is used instead of 200 (OK) because there's no response entity body ๐Ÿ“

again, the nonce, response, and opaque fields haven't been calculated in the Authorization request header ๐Ÿ’…

9 HTTP Headers for Distributed Authoring โœจ

9.1 DAV Header

DAV = "DAV" ":" "1" ["," "2"] ["," 1#extend]

this header tells you the resource supports the DAV schema and protocol as specified ๐ŸŒˆ All DAV compliant resources MUST return the DAV header on all OPTIONS responses ๐Ÿ’–

The value is a list of every compliance class the resource supports. Heads up: above, a comma has already been added before the 2 ๐Ÿ™ˆ that's because a resource can't be level 2 compliant unless it's also level 1 compliant. Check section 15 for more details ๐Ÿ“– generally though, supporting one compliance class doesn't mean you support any other one ๐Ÿซถ

9.2 Depth Header

Depth = "Depth" ":" ("0" | "1" | "infinity")

The Depth header is used with methods run on resources that could potentially have internal members ๐Ÿงš it tells the method whether to apply only to the resource ("Depth: 0"), to the resource and its immediate children ("Depth: 1"), or to the resource and all its progeny ("Depth: infinity") ๐ŸŒณ

The Depth header is only supported if a method's definition explicitly provides for that support ๐ŸŽ€

These rules are the default behaviour for any method that supports the Depth header ๐Ÿ’… A method can override them by defining different behaviour in its own definition ๐Ÿฆ‹

Methods that support the Depth header may choose not to support every value of the header, and may define, case by case, what happens when there's no Depth header at all ๐Ÿ™ƒ for example, the MOVE method only supports "Depth: infinity", and if there's no Depth header it acts as if a "Depth: infinity" header had been applied ๐ŸŒธ

Clients MUST NOT rely on methods executing on members of their hierarchies in any particular order, or on the execution being atomic, unless the particular method explicitly guarantees it ๐Ÿ˜ญ

When executed, a method with a Depth header does as much of its assigned task as it can, then returns a response saying what it managed to accomplish and what it failed to do ๐Ÿ“

So, for example, an attempt to COPY a hierarchy might end up with some members copied and some not ๐Ÿ’€

Any headers on a method that has a defined interaction with the Depth header MUST be applied to all resources in the scope of the method, unless alternative behaviour is explicitly defined ๐Ÿ‘‘ for example, an If-Match header has its value applied against every resource in the method's scope, and it'll make the method fail if the header doesn't match ๐Ÿ™ˆ

If a resource (source or destination) in the scope of a method with a Depth header is locked in a way that stops the method from succeeding, then the lock token for that resource MUST be submitted with the request in the If request header ๐Ÿ”

The Depth header only specifies how the method behaves with regard to internal children ๐Ÿ’œ if a resource doesn't have internal children, then the Depth header MUST be ignored ๐Ÿซง

Please note, though, that it's always an error to submit a Depth header value the method's definition doesn't allow โš ๏ธ so submitting "Depth: 1" on a COPY gets you a 400 (Bad Request), even if the resource has no internal members ๐Ÿ’€ the method should fail not because the resource lacks internal members, but because of the illegal value in the header ๐Ÿ™…โ€โ™€๏ธ

9.3 Destination Header

Destination = "Destination" ":" absoluteURI

The Destination header specifies the URI that identifies a destination resource for methods like COPY and MOVE, which take two URIs as parameters ๐Ÿฆ‹ Note that the absoluteURI production is defined in [RFC2396] ๐Ÿ“š

9.4 If Header

If = "If" ":" ( 1*No-tag-list | 1*Tagged-list)
No-tag-list = List
Tagged-list = Resource 1*List
Resource = Coded-URL
List = "(" 1*(["Not"](State-token | "[" entity-tag "]")) ")"
State-token = Coded-URL
Coded-URL = "<" absoluteURI ">"

The If header is meant to work a lot like the If-Match header defined in section 14.25 of [RFC2068] ๐Ÿ’– but the If header works with any URI that represents state information about a resource (a state token), as well as ETags โœจ a classic example of a state token is a lock token, and lock tokens are the only state tokens defined in this specification ๐Ÿ”

All DAV compliant resources MUST honor the If header ๐Ÿซถ

The If header describes a series of state lists ๐ŸŒˆ if the state of the resource the header applies to doesn't match any of the specified state lists, then the request MUST fail with a 412 (Precondition Failed) ๐Ÿ˜ญ if one of the described state lists does match the resource's state, then the request may succeed ๐ŸŽ‰

Note that the absoluteURI production is defined in [RFC2396] ๐Ÿ“š

9.4.1 No-tag-list Production

The No-tag-list production describes a series of state tokens and ETags ๐Ÿงƒ if you use multiple No-tag-list productions, then only one of them needs to match the resource's state for the method to be allowed to continue ๐Ÿ’…

If a method is applied to multiple resources because of a Depth or Destination header, then the No-tag-list production MUST be applied to each resource the method is applied to ๐Ÿ‘‘

9.4.1.1 Example - No-tag-list If Header

If: (<locktoken:a-write-lock-token> ["I am an ETag"]) (["I am another
ETag"])

the If header above would require that any resources within the scope of the method must either be locked with the specified lock token and be in the state identified by the "I am an ETag" ETag, or be in the state identified by the second ETag, "I am another ETag" ๐Ÿฆ‹ to put it more plainly, you can think of the header above as being in the form (or (and <locktoken:a-write-lock-token> ["I am an ETag"]) (and ["I am another ETag"])) ๐Ÿง โœจ

9.4.2 Tagged-list Production ๐ŸŽ€

okay so the tagged-list production is basically a scope thing ๐Ÿ’… it says the list productions after a resource spec only apply to THAT resource. the scope starts at the list right after the resource production and ends when the next resource production shows up (if there is one) โœจ

when the If header gets applied to a particular resource, the tagged-list productions MUST be searched to see if any of the listed resources match the operand resource(s) for the current method. if none of the resource productions match the current resource, then the header MUST be ignored ๐Ÿ™ˆ but if one of them does match the name of the resource being checked, then the list productions after that resource production MUST be applied to it, the way the previous section described ๐Ÿซถ

and the same URI MUST NOT appear more than once in a resource production in an If header. no duplicates, bestie ๐Ÿ’€

9.4.2.1 Example - Tagged List If header ๐Ÿฆ‹

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"])

okay this one is giving main character energy ๐Ÿ‘‘ we're copying http://www.foo.bar/resource1 over to http://www.foo.bar/resource2. when the method first hits http://www.foo.bar/resource1, that resource has to be in the state "(<locktoken:a-write-lock-token> [W/"A weak ETag"]) (["strong ETag"])" ๐Ÿ˜ญ which means it either has to be locked with the lock token "locktoken:a-write-lock-token" AND have the weak entity tag W/"A weak ETag", OR it has to have the strong entity tag "strong ETag". either one works ๐ŸŒธ

that's the only success condition, because http://www.bar.bar/random never gets the method applied to it (it's the only other resource in the If header), and http://www.foo.bar/resource2 isn't even listed in the If header ๐Ÿงš

9.4.3 not Production ๐Ÿ’œ

every state token or ETag is either current, which means it describes the state of a resource, or it's not current, which means it doesn't ๐Ÿ™ƒ so matching a state token or ETag against the resource's current state always comes out as true or false. the not production is the thing that flips that value โœจ and its scope is just the state-token or entity-tag right after it.

If: (Not <locktoken:write1> <locktoken:write2>)

when this is submitted with a request, it means all the operand resources must not be locked with locktoken:write1 and must be locked with locktoken:write2 ๐Ÿ”ฅ

9.4.4 Matching Function ๐ŸŒˆ

when you're doing If header processing, here's how a matching state token or entity tag is defined:

Matching entity tag: where the entity tag matches an entity tag associated with that resource.

Matching state token: where there is an exact match between the state token in the If header and any state token on the resource.

9.4.5 If Header and Non-DAV Compliant Proxies ๐Ÿ“

ngl this one is a little sad ๐Ÿฅบ non-DAV compliant proxies won't honor the If header, because they won't understand it, and HTTP says headers you don't understand have to be ignored. so when you're talking to HTTP/1.1 proxies, the Cache-Control: no-cache request header MUST be used so the proxy doesn't wrongly try to answer the request from its cache ๐Ÿ™…โ€โ™€๏ธ and for HTTP/1.0 proxies, the Pragma: no-cache request header MUST be used for the same reason ๐Ÿ’–

9.5 Lock-Token Header ๐Ÿ”

Lock-Token = "Lock-Token" ":" Coded-URL

the Lock-Token request header is used with the UNLOCK method to identify the lock to be removed. the lock token in the Lock-Token request header MUST identify a lock that contains the resource identified by Request-URI as a member โœจ

the Lock-Token response header is used with the LOCK method to show the lock token that got created when a LOCK request successfully made a new lock ๐ŸŽ‰

9.6 Overwrite Header ๐Ÿซง

Overwrite = "Overwrite" ":" ("T" | "F")

the Overwrite header says whether the server should overwrite the state of a non-null destination resource during a COPY or MOVE ๐Ÿ’… a value of "F" means the server must not perform the COPY or MOVE if the destination's state is non-null. if the overwrite header isn't included in a COPY or MOVE request, the resource MUST treat the request as if it had an overwrite header with the value "T" โœจ now, the Overwrite header kinda seems to do the same thing as the If-Match: * header from HTTP/1.1, but If-Match only applies to the Request-URI, not to the Destination of a COPY or MOVE. so they're not the same, periodt ๐Ÿ’€

if a COPY or MOVE doesn't happen because of the Overwrite header's value, the method MUST fail with a 412 (Precondition Failed) status code ๐Ÿ™ˆ

all DAV compliant resources MUST support the Overwrite header ๐Ÿซถ

9.7 Status-URI Response Header ๐Ÿฆ‹

the Status-URI response header can be used with the 102 (Processing) status code to tell the client how a method is going ๐Ÿงš

Status-URI = "Status-URI" ":" *(Status-Code Coded-URL) ; Status-Code
is defined in 6.1.1 of [RFC2068]

the URIs in the header are source resources that the outstanding method has affected. the status code shows the outcome of the method on that resource. so for example, if a MOVE on a collection is still going and a 102 (Processing) response comes back with a Status-URI header, the URIs included will show which resources had a move attempted on them and what happened ๐ŸŒธ

9.8 Timeout Request Header โฐ

TimeOut = "Timeout" ":" 1#TimeType
TimeType = ("Second-" DAVTimeOutVal | "Infinite" | Other)
DAVTimeOutVal = 1*digit
Other = "Extend" field-value   ; See section 4.2 of [RFC2068]

clients can include Timeout headers in their LOCK requests ๐Ÿ’– but the server isn't required to honor or even consider them. clients MUST NOT submit a Timeout request header with any method other than a LOCK method ๐Ÿ™…โ€โ™€๏ธ

a Timeout request header MUST contain at least one TimeType, and it can contain multiple TimeType entries. listing several is how the client says which values and value types it's okay with, and the client lists them in order of preference ๐Ÿ“

Timeout response values MUST use a Second value, Infinite, or a TimeType the client has shown it knows about. the server may assume a client is familiar with any TimeType submitted in a Timeout header โœจ

the "Second" TimeType is the number of seconds that will pass between the lock being granted at the server and the lock being automatically removed. the timeout value for TimeType "Second" MUST NOT be greater than 2^32-1 ๐Ÿ”ข

the timeout counter SHOULD restart any time a lock owner sends a method to any member of the lock, including unsupported methods or methods that are unsuccessful ๐Ÿ”„ however, the lock MUST be refreshed if a refresh LOCK method is successfully received ๐Ÿ’…

if the timeout expires, the lock may be lost. specifically, if the server wants to harvest the lock when it times out, the server SHOULD act as if it ran an UNLOCK method on the resource using the lock token of the timed-out lock, with its override authority ๐Ÿ˜ค so logs should get updated with what happened to the lock, notifications should get sent, and so on, just like they would for an UNLOCK request ๐Ÿ“‹

servers should pay close attention to the values clients submit, because they say a lot about what kind of activity the client plans to do ๐Ÿ‘€ for example, an applet running in a browser may need to lock a resource, but since the environment it's running in is unstable, the applet might get turned off without warning. so it'll probably ask for a pretty small timeout, so that if the applet dies the lock can be harvested quickly ๐Ÿซ  a document management system, on the other hand, will probably ask for an extremely long timeout, because its user might be planning to go offline ๐Ÿ“š

a client MUST NOT assume that just because the timeout has expired, the lock has been lost ๐Ÿ™ˆ

10 Status Code Extensions to HTTP/1.1 โœจ

the following status codes are added to the ones defined in HTTP/1.1 [RFC2068] ๐ŸŒˆ

10.1 102 Processing โณ

the 102 (Processing) status code is an interim response that tells the client the server has accepted the complete request, but hasn't finished it yet ๐Ÿ’… this status code SHOULD only be sent when the server reasonably expects the request to take a significant amount of time. as a guideline, if a method is taking longer than 20 seconds (a reasonable but arbitrary value) to process, the server SHOULD return a 102 (Processing) response ๐Ÿ•ฐ๏ธ the server MUST send a final response once the request has been completed โœจ

methods can take a really long time to process, especially methods that support the Depth header ๐Ÿ˜ญ in those cases the client may time out the connection while it's waiting for a response. to prevent that, the server may return a 102 (Processing) status code to tell the client it's still working on the method ๐Ÿซถ

10.2 207 Multi-Status ๐ŸŽ€

the 207 (Multi-Status) status code gives the status for multiple independent operations (check section 11 for more info) ๐Ÿงš

10.3 422 Unprocessable Entity ๐Ÿ™ƒ

the 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (so a 415 (Unsupported Media Type) status code would be wrong), and the syntax of the request entity is correct (so a 400 (Bad Request) status code would be wrong too), but it couldn't process the instructions inside ๐Ÿค” for example, this can happen if an XML request body is well-formed (syntactically correct) but has semantically wrong XML instructions ๐Ÿ’€

10.4 423 Locked ๐Ÿ”’

the 423 (Locked) status code means the source or destination resource of a method is locked ๐Ÿ”

10.5 424 Failed Dependency ๐Ÿ“

the 424 (Failed Dependency) status code means the method couldn't be performed on the resource because the requested action depended on another action, and that other action failed ๐Ÿ˜ค for example, if a command in a PROPPATCH method fails, then at minimum the rest of the commands will also fail with 424 (Failed Dependency) ๐Ÿ’”

10.6 507 Insufficient Storage ๐Ÿ’พ

the 507 (Insufficient Storage) status code means the method couldn't be performed on the resource because the server can't store the representation it needs to finish the request ๐Ÿ˜ฉ this condition is considered temporary. if the request that got this status code was the result of a user action, the request MUST NOT be repeated until a separate user action asks for it ๐Ÿซ 

11 Multi-Status Response ๐ŸŒธ

the default 207 (Multi-Status) response body is a text/xml or application/xml HTTP entity ๐Ÿ“„ it contains a single XML element called multistatus, which holds a set of XML elements called response. those contain the 200, 300, 400, and 500 series status codes generated during the method invocation โœจ 100 series status codes SHOULD NOT be recorded in a response XML element ๐Ÿ’…

12. XML Element Definitions โœจ

okay bestie, this is the XML vocab section ๐Ÿ’… Each section ends with its element type declaration in the [REC-XML] format, and the Value bit (when there is one) is extra restrictions on what the element can hold, written in BNF. So it's basically the rules for each little XML tag ๐Ÿงš

12.1. activelock XML Element

  • Name: activelock
  • Namespace: DAV:
  • Purpose: this is the lock itself, the "hands off, I'm editing this rn" sign on a resource ๐Ÿ”’
<!ELEMENT activelock (lockscope, locktype, depth, owner?, timeout?,
locktoken?) >

12.1.1. depth XML Element

  • Name: depth
  • Namespace: DAV:
  • Purpose: the value of the Depth header ๐ŸŒธ
  • Value: "0" | "1" | "infinity"
<!ELEMENT depth (#PCDATA) >

12.1.2. locktoken XML Element

  • Name: locktoken
  • Namespace: DAV:
  • Purpose: the lock token attached to a lock ๐ŸŽ€
  • Description: the href holds one or more opaque lock token URIs, and they all point at the same lock (aka the OpaqueLockToken-URI production in section 6.4). It's giving "many keys, one door" ๐Ÿ—๏ธ
<!ELEMENT locktoken (href+) >

12.1.3. timeout XML Element

  • Name: timeout
  • Namespace: DAV:
  • Purpose: the timeout attached to a lock โฐ
  • Value: TimeType ;Defined in section 9.8
<!ELEMENT timeout (#PCDATA) >

12.2. collection XML Element

  • Name: collection
  • Namespace: DAV:
  • Purpose: marks the resource as a collection ๐Ÿ“ A collection resource's resourcetype property MUST have this value, no exceptions bestie ๐Ÿ‘‘
<!ELEMENT collection EMPTY >

12.3. href XML Element

  • Name: href
  • Namespace: DAV:
  • Purpose: says "the content of this element is a URI" ๐Ÿ”—
  • Value: URI ; See section 3.2.1 of [RFC2068]
<!ELEMENT href (#PCDATA)>
  • Name: link
  • Namespace: DAV:
  • Purpose: marks a property as a link and carries its source and destination ๐Ÿฆ‹
  • Description: the link element gives the sources and destinations of a link. The name of the property holding it tells you the type of link. Link is multi-valued, so you can stack several links together to show several links of the same type. The href values inside the src and dst elements of a link MUST NOT be rejected if they point at resources that don't exist, so don't be picky about ghosts ๐Ÿ‘ป
<!ELEMENT link (src+, dst+) >

12.4.1. dst XML Element

  • Name: dst
  • Namespace: DAV:
  • Purpose: the destination of a link ๐ŸŽฏ
  • Value: URI
<!ELEMENT dst (#PCDATA) >

12.4.2. src XML Element

  • Name: src
  • Namespace: DAV:
  • Purpose: the source of a link ๐ŸŒฑ
  • Value: URI
<!ELEMENT src (#PCDATA) >

12.5. lockentry XML Element

  • Name: lockentry
  • Namespace: DAV:
  • Purpose: lists the kinds of locks you're allowed to use on a resource ๐Ÿงพ
<!ELEMENT lockentry (lockscope, locktype) >

12.6. lockinfo XML Element

  • Name: lockinfo
  • Namespace: DAV:
  • Purpose: goes along with the LOCK method so the client can say what kind of lock they want created ๐Ÿ™
<!ELEMENT lockinfo (lockscope, locktype, owner?) >

12.7. lockscope XML Element

  • Name: lockscope
  • Namespace: DAV:
  • Purpose: says whether a lock is exclusive or shared ๐Ÿค
<!ELEMENT lockscope (exclusive | shared) >

12.7.1. exclusive XML Element

  • Name: exclusive
  • Namespace: DAV:
  • Purpose: specifies an exclusive lock, the "only me, periodt" kind ๐Ÿ’œ
<!ELEMENT exclusive EMPTY >

12.7.2. shared XML Element

  • Name: shared
  • Namespace: DAV:
  • Purpose: specifies a shared lock, the "we can all be in here together" kind ๐ŸŒˆ
<!ELEMENT shared EMPTY >

12.8. locktype XML Element

  • Name: locktype
  • Namespace: DAV:
  • Purpose: specifies the access type of a lock. For now there's only one lock type defined, the write lock โœ๏ธ
<!ELEMENT locktype (write) >

12.8.1. write XML Element

  • Name: write
  • Namespace: DAV:
  • Purpose: specifies a write lock ๐Ÿ–Š๏ธ
<!ELEMENT write EMPTY >

12.9. multistatus XML Element

  • Name: multistatus
  • Namespace: DAV:
  • Purpose: holds multiple response messages, a whole group chat of replies ๐Ÿ’ฌ
  • Description: the responsedescription at the top level is a general message about the overall vibe of the response. If it's there, an application can show that instead of showing each individual response description inside the responses โœจ
<!ELEMENT multistatus (response+, responsedescription?) >

12.9.1. response XML Element

  • Name: response
  • Namespace: DAV:
  • Purpose: holds one response describing what a method did to a resource and/or its properties ๐Ÿ“ฌ
  • Description: a particular href MUST NOT appear more than once as a child of a response element under a multistatus element. This rule keeps the processing cost of a response linear, because nobody has to go hunting to group all the responses by href ๐Ÿƒโ€โ™€๏ธ There are no requirements about ordering based on href values, so order is free real estate ๐ŸŒธ
<!ELEMENT response (href, ((href*, status)|(propstat+)),
responsedescription?) >

12.9.1.1. propstat XML Element

  • Name: propstat
  • Namespace: DAV:
  • Purpose: groups together a prop element and a status element that go with a particular href element ๐ŸŽ€
  • Description: the propstat element MUST contain one prop element and one status element. The contents of the prop element MUST only list the names of the properties that the result in the status element applies to. Only the names, bestie, not the whole vibe ๐Ÿซถ
<!ELEMENT propstat (prop, status, responsedescription?) >

12.9.1.2. status XML Element

  • Name: status
  • Namespace: DAV:
  • Purpose: holds a single HTTP status-line ๐Ÿšฆ
  • Value: status-line ;status-line defined in [RFC2068]
<!ELEMENT status (#PCDATA) >

12.9.2. responsedescription XML Element

  • Name: responsedescription
  • Namespace: DAV:
  • Purpose: holds a message that can be shown to a user, explaining what kind of response this is ๐Ÿ’ญ
  • Description: this element has info that's fine to show a real human ๐Ÿ™Œ
<!ELEMENT responsedescription (#PCDATA) >

12.10. owner XML Element

  • Name: owner
  • Namespace: DAV:
  • Purpose: info about the principal who took out a lock ๐Ÿง‘โ€๐ŸŽค
  • Description: the owner element gives enough info to either contact that principal directly (like a phone number or an Email URI) or find them (like the URL of a homepage). Basically, so you can slide into their DMs about the lock ๐Ÿ“ฑ
<!ELEMENT owner ANY>

12.11. prop XML element

  • Name: prop
  • Namespace: DAV:
  • Purpose: holds properties related to a resource ๐Ÿ—‚๏ธ
  • Description: the prop element is a generic container for properties defined on resources. Every element inside a prop element MUST define a property related to the resource. No other elements may be used inside a prop element, so keep the guest list tight ๐Ÿ’…
<!ELEMENT prop ANY>

12.12. propertybehavior XML element

  • Name: propertybehavior
  • Namespace: DAV:
  • Purpose: says how properties get handled during a COPY or MOVE ๐Ÿฆข
  • Description: the propertybehavior element specifies how properties are handled during a COPY or MOVE. If it's not in the request body, the server is expected to act the way the default property handling of that method says. All WebDAV compliant resources MUST support the propertybehavior element, no skipping ๐ŸŒŸ
<!ELEMENT propertybehavior (omit | keepalive) >

12.12.1. keepalive XML element

  • Name: keepalive
  • Namespace: DAV:
  • Purpose: sets the requirements for copying or moving live properties ๐Ÿ’–
  • Description: if a list of URIs is included as the value of keepalive, the named properties MUST be "live" after they're copied (or moved) to the destination resource of a COPY (or MOVE). If the value "*" is given, that means all live properties on the source resource MUST be live on the destination. If the requirements in the keepalive element can not be honored, the method MUST fail with a 412 (Precondition Failed). That's a big no from the server, so be ready ๐Ÿ˜ญ All DAV compliant resources MUST support the keepalive element for use with the COPY and MOVE methods.
<!ELEMENT keepalive (#PCDATA | href+) >
  • Value: "*" ; #PCDATA value can only be "*"

12.12.2. omit XML element

  • Name: omit
  • Namespace: DAV:
  • Purpose: tells the server to do its best to copy properties, but a failure to copy a property MUST NOT cause the method to fail. It's the chill option ๐Ÿง˜โ€โ™€๏ธ
  • Description: the default for a COPY or MOVE is to copy or move all the properties, or fail the whole method. But sometimes it's just not possible, like when a server copies a resource over another protocol such as FTP. Then any attempt to copy or move over FTP would always have to fail, because properties couldn't be moved over, not even dead properties ๐Ÿ’€ All DAV compliant resources MUST support the omit element on COPY and MOVE methods.
<!ELEMENT omit EMPTY >

12.13. propertyupdate XML element

  • Name: propertyupdate
  • Namespace: DAV:
  • Purpose: holds a request to change the properties on a resource โœ๏ธ
  • Description: this element is a container for all the info needed to modify the properties on the resource. It's multi-valued, so you can have a bunch of them ๐Ÿ“
<!ELEMENT propertyupdate (remove | set)+ >

12.13.1. remove XML element

  • Name: remove
  • Namespace: DAV:
  • Purpose: lists the DAV properties that should be removed from a resource ๐Ÿ—‘๏ธ
  • Description: remove says the properties listed in prop should be removed. Asking to remove a property that doesn't exist is not an error, so no drama ๐Ÿ™ˆ All the XML elements in a prop element inside a remove element MUST be empty, since only the names of the properties to remove are needed.
<!ELEMENT remove (prop) >

12.13.2. set XML element

  • Name: set
  • Namespace: DAV:
  • Purpose: lists the DAV property values to be set on a resource ๐ŸŒท
  • Description: the set element MUST contain only a prop element. The elements inside that prop element MUST specify the name and value of the properties that get set on the resource identified by Request-URI. If a property already exists, its value gets replaced, new era unlocked ๐Ÿ‘‘ Language tagging info in the property's value (in the "xml:lang" attribute, if it's present) MUST be persistently stored along with the property, and MUST be subsequently retrievable using PROPFIND. It's giving memory that doesn't forget ๐Ÿง โœจ
<!ELEMENT set (prop) >

12.14. propfind XML Element

  • Name: propfind
  • Namespace: DAV:
  • Purpose: specifies which properties get returned from a PROPFIND method. There are two special elements for this, allprop and propname. If prop is used inside propfind, it MUST only contain property names, not values ๐Ÿ”
<!ELEMENT propfind (allprop | propname | prop) >

12.14.1. allprop XML Element

  • Name: allprop
  • Namespace: DAV:
  • Purpose: says that all property names and values on the resource should come back, the full glow-up ๐ŸŒˆ
<!ELEMENT allprop EMPTY >

12.14.2. propname XML Element

  • Name: propname
  • Namespace: DAV:
  • Purpose: says that only a list of property names on the resource should come back, no values, just the menu ๐Ÿ“‹
<!ELEMENT propname EMPTY >

13 DAV Properties โœจ

Okay bestie, so for DAV properties the property's name is also the name of the XML element that holds its value. Super neat, right? ๐ŸŽ€ Each section ends with an element type declaration written in the [REC-XML] format. Where there's a "Value" field, it adds BNF rules that narrow down what's allowed inside that element (basically, it restricts the PCDATA contents). ๐Ÿฆ‹

13.1 creationdate Property

Name: creationdate Namespace: DAV: Purpose: Records when the resource was created, date and time both. ๐Ÿ“… Value: date-time ; See Appendix 2 Description: The creationdate property should be defined on all DAV compliant resources. If it's present, it holds a timestamp for the exact moment the resource was created, meaning the moment it first had non-null state. โฐ

<!ELEMENT creationdate (#PCDATA) >

13.2 displayname Property

Name: displayname Namespace: DAV: Purpose: Gives the resource a name that's nice to show a human. ๐Ÿ’– Description: The displayname property should be defined on all DAV compliant resources. If it's present, it holds a description of the resource that's suitable for showing to a user. โœจ

<!ELEMENT displayname (#PCDATA) >

13.3 getcontentlanguage Property

Name: getcontentlanguage Namespace: DAV: Purpose: Holds the Content-Language header that comes back from a GET without accept headers. ๐ŸŒˆ Description: The getcontentlanguage property MUST be defined on any DAV compliant resource that returns the Content-Language header on a GET. ๐Ÿซถ Value: language-tag ;language-tag is defined in section 14.13 of [RFC2068]

<!ELEMENT getcontentlanguage (#PCDATA) >

13.4 getcontentlength Property

Name: getcontentlength Namespace: DAV: Purpose: Holds the Content-Length header that comes back from a GET without accept headers. ๐Ÿ“ Description: The getcontentlength property MUST be defined on any DAV compliant resource that returns the Content-Length header in response to a GET. ๐Ÿ’… Value: content-length ; see section 14.14 of [RFC2068]

<!ELEMENT getcontentlength (#PCDATA) >

13.5 getcontenttype Property

Name: getcontenttype Namespace: DAV: Purpose: Holds the Content-Type header that comes back from a GET without accept headers. ๐ŸŽ€ Description: This getcontenttype property MUST be defined on any DAV compliant resource that returns the Content-Type header in response to a GET. ๐Ÿ“ Value: media-type ; defined in section 3.7 of [RFC2068]

<!ELEMENT getcontenttype (#PCDATA) >

13.6 getetag Property

Name: getetag Namespace: DAV: Purpose: Holds the ETag header that comes back from a GET without accept headers. ๐Ÿท๏ธ Description: The getetag property MUST be defined on any DAV compliant resource that returns the Etag header. ๐Ÿฆ‹ Value: entity-tag ; defined in section 3.11 of [RFC2068]

<!ELEMENT getetag (#PCDATA) >

13.7 getlastmodified Property

Name: getlastmodified Namespace: DAV: Purpose: Holds the Last-Modified header that comes back from a GET method without accept headers. ๐Ÿ•ฐ๏ธ Description: Okay, this one's a plot twist ๐Ÿ˜ญ. The last-modified date on a resource can change because of any part of the resource's state, not only a change to what the GET method sends back. For example, changing a property can make the last-modified date move. The getlastmodified property MUST be defined on any DAV compliant resource that returns the Last-Modified header in response to a GET. ๐Ÿ”ฅ Value: HTTP-date ; defined in section 3.3.1 of [RFC2068]

<!ELEMENT getlastmodified (#PCDATA) >

13.8 lockdiscovery Property

Name: lockdiscovery Namespace: DAV: Purpose: Describes the active locks on a resource. ๐Ÿ”’ Description: The lockdiscovery property gives you a list of who holds a lock, what kind of lock it is, the timeout type and how much time is left on that timeout, plus the associated lock token. The server is free to hide any or all of this info if the requesting principal doesn't have enough access rights to see it. ๐Ÿ™ˆ

<!ELEMENT lockdiscovery (activelock)* >

13.8.1 Example - Retrieving the lockdiscovery Property

>>Request

PROPFIND /container/ HTTP/1.1
Host: www.foo.bar
Content-Length: xxxx
Content-Type: text/xml; charset="utf-8"

<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D='DAV:'>
  <D:prop><D:lockdiscovery/></D:prop>
</D:propfind>

>>Response

HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D='DAV:'>
  <D:response>
       <D:href>http://www.foo.bar/container/</D:href>
       <D:propstat>
            <D:prop>
                 <D:lockdiscovery>
                      <D:activelock>
                           <D:locktype><D:write/></D:locktype>
                           <D:lockscope><D:exclusive/></D:lockscope>
                           <D:depth>0</D:depth>
                           <D:owner>Jane Smith</D:owner>
                           <D:timeout>Infinite</D:timeout>
                           <D:locktoken>

                                <D:href>
            opaquelocktoken:f81de2ad-7f3d-a1b2-4f3c-00a0c91a9d76
                                </D:href>
                           </D:locktoken>
                      </D:activelock>
                 </D:lockdiscovery>
            </D:prop>
            <D:status>HTTP/1.1 200 OK</D:status>
       </D:propstat>
  </D:response>
</D:multistatus>

So this resource has one exclusive write lock on it, and that lock never times out. ๐Ÿ”โœจ

13.9 resourcetype Property

Name: resourcetype Namespace: DAV: Purpose: Says what kind of resource this is. ๐Ÿงš Description: The resourcetype property MUST be defined on all DAV compliant resources. The default value is empty. ๐Ÿซง

<!ELEMENT resourcetype ANY >

13.10 source Property

Name: source Namespace: DAV: Purpose: The destination of a source link points to the resource that holds the unprocessed source of the link's source. ๐Ÿ”— Description: The source of the link (src) is usually the URI of the output resource where the link is defined. There's usually only one destination (dst) for the link, which is the URI where the unprocessed source of the resource can be accessed. When a link has more than one destination, this specification doesn't set any policy on ordering. ๐Ÿคทโ€โ™€๏ธ

<!ELEMENT source (link)* >

13.10.1 Example - A source Property

<?xml version="1.0" encoding="utf-8" ?>
<D:prop xmlns:D="DAV:" xmlns:F="http://www.foocorp.com/Project/">
  <D:source>
       <D:link>
            <F:projfiles>Source</F:projfiles>
            <D:src>http://foo.bar/program</D:src>
            <D:dst>http://foo.bar/src/main.c</D:dst>
       </D:link>
       <D:link>
            <F:projfiles>Library</F:projfiles>
            <D:src>http://foo.bar/program</D:src>
            <D:dst>http://foo.bar/src/main.lib</D:dst>
       </D:link>
       <D:link>
            <F:projfiles>Makefile</F:projfiles>
            <D:src>http://foo.bar/program</D:src>
            <D:dst>http://foo.bar/src/makefile</D:dst>
       </D:link>
  </D:source>
</D:prop>

Here the resource http://foo.bar/program has a source property with three links. ๐Ÿฆ‹ Each link has three elements. Two of them, src and dst, are part of the DAV schema in this document. The third one comes from the schema http://www.foocorp.com/project/ (that's Source, Library, and Makefile). A client that only implements the DAV elements won't understand the foocorp ones, so it ignores them and still sees the expected source and destination links. ๐Ÿ™Œ A smarter client might know about the foocorp elements and show the user extra info about the links. This example is a great look at the power of XML markup: you can add more info to element values without breaking older clients. ๐Ÿ’œ

13.11 supportedlock Property

Name: supportedlock Namespace: DAV: Purpose: Lists the lock capabilities this resource supports. ๐Ÿ” Description: The supportedlock property of a resource returns a list of the combinations of scope and access types that can be specified in a lock request on the resource. Keep in mind the actual contents are controlled by access controls too, so a server is not required to provide info the client isn't authorized to see. ๐Ÿ‘€

<!ELEMENT supportedlock (lockentry)* >

13.11.1 Example - Retrieving the supportedlock Property

>>Request

PROPFIND  /container/ HTTP/1.1
Host: www.foo.bar
Content-Length: xxxx
Content-Type: text/xml; charset="utf-8"

<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
  <D:prop><D:supportedlock/></D:prop>
</D:propfind>

>>Response

HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"
Content-Length: xxxx

<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:">
  <D:response>
       <D:href>http://www.foo.bar/container/</D:href>
       <D:propstat>
            <D:prop>
                 <D:supportedlock>
                      <D:lockentry>
                           <D:lockscope><D:exclusive/></D:lockscope>
                           <D:locktype><D:write/></D:locktype>
                      </D:lockentry>
                      <D:lockentry>
                           <D:lockscope><D:shared/></D:lockscope>
                           <D:locktype><D:write/></D:locktype>
                      </D:lockentry>
                 </D:supportedlock>
            </D:prop>
            <D:status>HTTP/1.1 200 OK</D:status>
       </D:propstat>
  </D:response>
</D:multistatus>

14 Instructions for Processing XML in DAV ๐Ÿง 

All DAV compliant resources MUST ignore any unknown XML element and all its children they run into while processing a DAV method that uses XML as its command language. ๐Ÿ™…โ€โ™€๏ธ Unknown stuff gets tuned out, periodt.

This rule also covers clients processing DAV property values, where unknown XML elements SHOULD be ignored unless the property's schema says otherwise. ๐Ÿ’…

This rule does not apply to setting dead DAV properties on the server. There, the server MUST record unknown XML elements. ๐Ÿ“

The rule also doesn't apply to XML used as the content type of the entity body, like when XML is the body of a PUT. ๐ŸŽ€

Since XML can be sent as text/xml or application/xml, a DAV server MUST accept DAV method requests with XML parameters sent as either text/xml or application/xml, and a DAV client MUST accept XML responses using either text/xml or application/xml. ๐Ÿฆ‹โœจ

15 DAV Compliance Classes ๐Ÿ’…โœจ

Okay bestie, so a DAV compliant resource can pick from two classes of compliance ๐ŸŽ€. Clients can figure out which classes a resource is in by sending OPTIONS to it and checking the DAV header that comes back ๐Ÿ‘€.

Since this doc extends HTTP/1.1, basically every DAV compliant resource, client, and proxy MUST be compliant with [RFC2068] ๐Ÿซถ. No cap, that's the baseline.

Compliance classes aren't necessarily sequential ๐Ÿฆ‹. A class 2 resource must also be class 1 compliant. But if more classes get defined later, a resource that's class 1, 2, and 4 might not be class 3 compliant. Also, identifiers other than numbers may be used as compliance class identifiers ๐ŸŒˆ.

15.1 Class 1 ๐ŸŒธ

A class 1 compliant resource MUST meet all "MUST" requirements in all sections of this document ๐Ÿ’–.

Class 1 compliant resources MUST return, at minimum, the value 1 in the DAV header on all responses to the OPTIONS method โœจ.

15.2 Class 2 ๐Ÿ“

A class 2 compliant resource MUST meet all class 1 requirements and support the LOCK method, the supportedlock property, the lockdiscovery property, the Time-Out response header and the Lock-Token request header ๐Ÿ”. A class "2" compliant resource SHOULD also support the Time-Out request header and the owner XML element ๐Ÿซถ.

Class 2 compliant resources MUST return, at minimum, the values 1 and 2 in the DAV header on all responses to the OPTIONS method ๐Ÿ‘‘.

16 Internationalization Considerations ๐ŸŒ๐Ÿ’œ

In the realm of internationalization, this specification complies with the IETF Character Set Policy [RFC2277] ๐ŸŒ. Human-readable fields can show up either in the value of a property, or in an error message returned in a response entity body. In both cases, the human-readable content is encoded using XML, which has explicit provisions for character set tagging and encoding, and requires that XML processors read XML elements encoded, at minimum, using the UTF-8 [UTF-8] encoding of the ISO 10646 multilingual plane ๐Ÿง . XML examples in this spec demonstrate use of the charset parameter of the Content-Type header, as defined in [RFC2376], plus the XML "encoding" attribute. Together those give charset identification info for MIME and XML processors ๐ŸŽ€.

XML also has language tagging, so you can specify the language of a particular element's contents ๐Ÿ—ฃ๏ธ. XML uses either IANA registered language tags (see [RFC1766]) or ISO 639 language tags [ISO-639] in the xml:lang attribute to identify the language of an element's content and attributes ๐Ÿ’….

WebDAV applications MUST support the character set tagging, character set encoding, and the language tagging functionality of the XML specification ๐Ÿซถ. Implementors are strongly encouraged to read "XML Media Types" [RFC2376] for guidance on which MIME media type to use for XML transport, and on using the charset parameter of the Content-Type header ๐Ÿ“š.

Names used in this spec fall into three categories: names of protocol elements like methods and headers, names of XML elements, and names of properties ๐Ÿงฉ. Protocol element names follow the precedent of HTTP, using English names encoded in USASCII for methods and headers. Since these protocol elements aren't visible to users (they're basically long token identifiers), they don't need to support encoding in multiple character sets ๐Ÿ™ˆ. Similarly, the XML element names in this spec are English names encoded in UTF-8, but since users never see them, they don't need multiple character set encodings either.

The name of a property defined on a resource is a URI ๐Ÿ”—. Some apps (like a generic property viewer) will display property URIs directly to their users. But it's expected that the typical app will use a fixed set of properties and map the property name URI to a human-readable field when showing the property name to a user. Only when the set of properties isn't known ahead of time does an app need to show a property name URI to a user. We recommend that applications provide human-readable property names wherever feasible ๐Ÿ“.

For error reporting, we follow the HTTP/1.1 status code convention, including a short, English description of the code with each status code (e.g., 423 (Locked)) ๐Ÿšซ. A poorly crafted user agent might show that message to a user, but internationalized apps will ignore it and display an appropriate message in the user's language and character set ๐ŸŒธ.

Since interoperation of clients and servers doesn't require locale information, this spec doesn't specify any mechanism for transmitting it ๐Ÿคทโ€โ™€๏ธ.

17 Security Considerations ๐Ÿ”๐Ÿ’€

This section is here to detail security issues that WebDAV apps need to be aware of ๐Ÿ‘€. All of the security considerations of HTTP/1.1 (discussed in [RFC2068]) and XML (discussed in [RFC2376]) also apply to WebDAV. On top of that, the security risks of remote authoring require stronger authentication tech, bring in several new privacy concerns, and may increase the hazards from poor server design. These issues are detailed below ๐Ÿ˜ญ.

17.1 Authentication of Clients ๐Ÿ”‘

Because WebDAV is all about authoring, WebDAV servers need to use authentication tech to protect not just access to a network resource, but the integrity of the resource too ๐Ÿ›ก๏ธ. Also, adding locking functionality means you need authentication support ๐Ÿ”’.

A password sent in the clear over an insecure channel is not enough to protect the accessibility and integrity of a resource, since the password can be intercepted ๐Ÿ™…โ€โ™€๏ธ. Basic authentication for HTTP/1.1 basically sends the password as clear text, so Basic authentication MUST NOT be used to authenticate a WebDAV client to a server unless the connection is secure ๐Ÿšจ. Furthermore, a WebDAV server MUST NOT send Basic authentication credentials in a WWW-Authenticate header unless the connection is secure ๐Ÿ’…. Examples of secure connections include a Transport Layer Security (TLS) connection using a strong cipher suite with mutual authentication of client and server, or a connection over a network that's physically secure, like an isolated network in a building with restricted access ๐Ÿข.

Basic auth over an unsecured connection is a hard no, bestie ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’€

WebDAV applications MUST support the Digest authentication scheme [RFC2069] ๐Ÿ’œ. Digest authentication verifies that both parties know a shared secret (a password) without having to send that secret in the clear. So it avoids the security problems of Basic authentication while still giving a level of authentication that's useful in a wide range of scenarios ๐Ÿฆ‹.

17.2 Denial of Service ๐Ÿ’ฅ

Denial of service attacks are a special concern for WebDAV servers ๐Ÿ˜ฌ. WebDAV plus HTTP enables denial of service attacks on every part of a system's resources, honestly so scary ๐Ÿ™ˆ.

The underlying storage can be attacked by PUTting extremely large files ๐Ÿ“ฆ. Asking for recursive operations on large collections can attack processing time โณ. Making multiple pipelined requests on multiple connections can attack network connections ๐ŸŒ. WebDAV servers need to be aware of the possibility of a denial of service attack at all levels ๐Ÿšจ.

17.3 Security through Obscurity ๐Ÿ™ˆ

WebDAV provides, through the PROPFIND method, a mechanism for listing the member resources of a collection ๐Ÿ“‹. This greatly weakens security or privacy techniques that rely only on how hard it is to discover the names of network resources ๐Ÿ˜ต. Users of WebDAV servers are encouraged to use access control techniques to prevent unwanted access to resources, rather than depending on how obscure their resource names are ๐Ÿ”’โœจ.

17.4 Privacy Issues Connected to Locks ๐Ÿ—๏ธ

When submitting a lock request, a user agent may also submit an owner XML field with contact info for the person taking out the lock (for cases where a person, rather than a robot, is taking out the lock) ๐Ÿง‘โ€๐Ÿ’ป. That contact info gets stored in a lockdiscovery property on the resource, and other collaborators can use it to start negotiating access to the resource ๐Ÿค. But in lots of cases this contact info can be super private, so it should not be widely disseminated ๐Ÿคซ. Servers SHOULD limit read access to the lockdiscovery property as appropriate ๐Ÿ”. Furthermore, user agents SHOULD provide control over whether contact information gets sent at all, and if it does get sent, control over exactly what information is included ๐ŸŽ€.

17.5 Privacy Issues Connected to Properties ๐Ÿงพ

Property values are typically used to hold stuff like the author of a document, so privacy concerns could pop up from widespread access to a resource's property data ๐Ÿ‘€. To reduce the risk of accidentally leaking private info through properties, servers are encouraged to build access control mechanisms that separate read access to the resource body from read access to the resource's properties ๐Ÿงฑ. That way a user can control who sees their property data without overly restricting access to the resource's contents ๐Ÿ’–.

HTTP/1.1 warns against giving read access to script code, because it may contain sensitive info ๐Ÿซฃ. Yet WebDAV, through its source link facility, can potentially provide a URI for script resources so they can be authored โœ๏ธ. For HTTP/1.1, a server could reasonably block access to source resources, since read-only access is the usual case there ๐Ÿ”. WebDAV, though, puts its emphasis on authoring. It encourages read and write access to source resources, and provides the source link facility to identify the source ๐Ÿ’…. That cuts down the security benefit of blocking access to source resources ๐Ÿ˜ญ. Users and administrators of WebDAV servers should be very cautious when allowing remote authoring of scripts, limiting read and write access to the source resources to authorized principals ๐Ÿšจ๐Ÿซถ.

17.7 Implications of XML External Entities ๐Ÿงš

okay so XML has this thing called "external entities" (defined in section 4.2.2 of [REC-XML]) ๐Ÿ’… which basically tells an XML processor to go fetch some XML sitting at a particular URI and inline-include it right into the doc. ๐Ÿซถ An external XML entity can be used to append or modify the document type declaration (DTD) associated with an XML document. It can also pull XML into the content of the document itself โœจ

for non-validating XML, like the XML used in this specification, including an external XML entity is not required by [REC-XML]. ๐ŸŒธ BUT [REC-XML] does say that an XML processor may, at its discretion, include the external XML entity. so it's optional, but it's allowed, periodt ๐Ÿ’€

external XML entities have no inherent trustworthiness ๐Ÿšจ they're subject to all the attacks that are endemic to any HTTP GET request. ๐Ÿ˜ญ it's also possible for an external XML entity to modify the DTD, which changes the final form of the XML document. in the worst case that can significantly modify its semantics, or expose the XML processor to the security risks discussed in [RFC2376]. so implementers must be aware that external XML entities should be treated as untrustworthy. no cap, this is a big deal ๐Ÿ™ˆ

there's also a scalability risk when a widely deployed application uses external XML entities ๐Ÿ“ˆ it's possible there would be significant numbers of requests for one external XML entity, which could potentially overload any server that fields requests for the resource containing the external XML entity. overloaded server, not it ๐Ÿ’€


17.8 Risks Connected with Lock Tokens ๐Ÿ”

this one's giving "hidden tracking" energy, so pay attention ๐Ÿ‘€ this specification, in section 6.4, requires the use of Universal Unique Identifiers (UUIDs) for lock tokens, so that their uniqueness is guaranteed across space and time. ๐Ÿฆ‹ UUIDs, as defined in [ISO-11578], contain a "node" field which "consists of the IEEE address, usually the host address. For systems with multiple IEEE 802 nodes, any available node address can be used." Since a WebDAV server will issue many locks over its lifetime, the implication is that it will also be publicly exposing its IEEE 802 address. that's the plot twist ๐Ÿ˜ณ

there are several risks associated with exposure of IEEE 802 addresses. Using the IEEE 802 address:

  • It is possible to track the movement of hardware from subnet to subnet.
  • It may be possible to identify the manufacturer of the hardware running a WebDAV server.
  • It may be possible to determine the number of each type of computer running WebDAV.

section 6.4.1 of this specification details an alternate mechanism for generating the "node" field of a UUID without using an IEEE 802 address ๐ŸŒˆ that alleviates the risks associated with exposure of IEEE 802 addresses by using an alternate source of uniqueness. โœจ iconic workaround, honestly


18 IANA Considerations ๐Ÿ“‹

this document defines two namespaces: the namespace of property names, and the namespace of WebDAV-specific XML elements used within property values. ๐Ÿ“

URIs are used for both names, and there are a few reasons why ๐Ÿงš assignment of a URI doesn't require a request to a central naming authority, so WebDAV property names and XML elements can be quickly defined by any WebDAV user or application. URIs also provide a unique address space, which means the distributed users of WebDAV won't run into collisions among the property names and XML elements they create. main character energy for URIs, fr ๐Ÿ’œ

this specification defines a distinguished set of property names and XML elements that are understood by all WebDAV applications. The property names and XML elements in this specification are all derived from the base URI DAV: by adding a suffix to it. for example, DAV:creationdate is the "creationdate" property. โญ

this specification also defines a URI scheme for the encoding of lock tokens, the opaquelocktoken URI scheme described in section 6.4. ๐Ÿ”‘

to ensure correct interoperation based on this specification, IANA must reserve the URI namespaces starting with DAV: and with opaquelocktoken: for use by this specification, its revisions, and related WebDAV specifications. ๐Ÿซถ reserved, sealed, done ๐Ÿ‘‘


19 Intellectual Property โš–๏ธ

the following notice is copied from RFC 2026 [RFC2026], section 10.4, and describes the position of the IETF concerning intellectual property claims made against this document. ๐Ÿ“œ

the IETF takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use other technology described in this document, or the extent to which any license under such rights might or might not be available. neither does it represent that it has made any effort to identify any such rights. information on the IETF's procedures with respect to rights in standards-track and standards-related documentation can be found in BCP-11. copies of claims of rights made available for publication, and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the IETF Secretariat. ๐Ÿงพ

the IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to practice this standard. please address the information to the IETF Executive Director. ๐Ÿ“ฎ


20 Acknowledgements ๐Ÿ’–

a specification like this thrives on piercing critical review, and withers from apathetic neglect ๐Ÿฅน the authors gratefully acknowledge the contributions of the following people, whose insights were so valuable at every stage of the work. the list goes like this ๐ŸŽ€

Terry Allen, Harald Alvestrand, Jim Amsden, Becky Anderson, Alan Babich, Sanford Barr, Dylan Barrell, Bernard Chester, Tim Berners-Lee, Dan Connolly, Jim Cunningham, Ron Daniel, Jr., Jim Davis, Keith Dawson, Mark Day, Brian Deen, Martin Duerst, David Durand, Lee Farrell, Chuck Fay, Wesley Felter, Roy Fielding, Mark Fisher, Alan Freier, George Florentine, Jim Gettys, Phill Hallam-Baker, Dennis Hamilton, Steve Henning, Mead Himelstein, Alex Hopmann, Andre van der Hoek, Ben Laurie, Paul Leach, Ora Lassila, Karen MacArthur, Steven Martin, Larry Masinter, Michael Mealling, Keith Moore, Thomas Narten, Henrik Nielsen, Kenji Ota, Bob Parker, Glenn Peterson, Jon Radoff, Saveen Reddy, Henry Sanders, Christopher Seiwald, Judith Slein, Mike Spreitzer, Einar Stefferud, Greg Stein, Ralph Swick, Kenji Takahashi, Richard N. Taylor, Robert Thau, John Turner, Sankar Virdhagriswaran, Fabio Vitali, Gregory Woodhouse, and Lauren Wood.

two from this list deserve special mention ๐ŸŒŸ the contributions by Larry Masinter have been invaluable, both in helping form the working group and in patiently coaching the authors along the way. he set standards the rest of the team has been working hard to meet ๐Ÿซก the contributions of Judith Slein in clarifying the requirements, and in patiently reviewing draft after draft, both improved this specification and expanded everyone's minds on document management. ๐Ÿง โœจ

we would also like to thank John Turner for developing the XML DTD. ๐Ÿ™Œ


21 References ๐Ÿ“š

21.1 Normative References

[RFC1766]       Alvestrand, H., "Tags for the Identification of
                Languages", RFC 1766, March 1995.

[RFC2277]       Alvestrand, H., "IETF Policy on Character Sets and
                Languages", BCP 18, RFC 2277, January 1998.

[RFC2119]       Bradner, S., "Key words for use in RFCs to Indicate
                Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC2396]       Berners-Lee, T., Fielding, R. and L. Masinter,
                "Uniform Resource Identifiers (URI): Generic Syntax",
                RFC 2396, August 1998.

[REC-XML]       T. Bray, J. Paoli, C. M. Sperberg-McQueen,
                "Extensible Markup Language (XML)." World Wide Web
                Consortium Recommendation REC-xml-19980210.
                http://www.w3.org/TR/1998/REC-xml-19980210.

[REC-XML-NAMES] T. Bray, D. Hollander, A. Layman, "Namespaces in
                XML". World Wide Web Consortium Recommendation REC-
                xml-names-19990114.  http://www.w3.org/TR/1999/REC-
                xml-names-19990114/

[RFC2069]       Franks, J., Hallam-Baker, P., Hostetler, J., Leach,
                P, Luotonen, A., Sink, E. and L. Stewart, "An
                Extension to HTTP :  Digest Access Authentication",
                RFC 2069, January 1997.

[RFC2068]       Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and
                T. Berners-Lee, "Hypertext Transfer Protocol --
                HTTP/1.1", RFC 2068, January 1997.

[ISO-639]       ISO (International Organization for Standardization).
                ISO 639:1988. "Code for the representation of names
                of languages."

[ISO-8601]      ISO (International Organization for Standardization).
                ISO 8601:1988. "Data elements and interchange formats
                - Information interchange - Representation of dates
                and times."

[ISO-11578]     ISO (International Organization for Standardization).
                ISO/IEC 11578:1996. "Information technology - Open
                Systems Interconnection - Remote Procedure Call
                (RPC)"

[RFC2141]       Moats, R., "URN Syntax", RFC 2141, May 1997.

[UTF-8]         Yergeau, F., "UTF-8, a transformation format of
                Unicode and ISO 10646", RFC 2279, January 1998.

21.2 Informational References

[RFC2026]  Bradner, S., "The Internet Standards Process - Revision
           3", BCP 9, RFC 2026, October 1996.

[RFC1807]  Lasher, R. and D. Cohen, "A Format for Bibliographic
           Records", RFC 1807, June 1995.

[WF]       C. Lagoze, "The Warwick Framework: A Container
           Architecture for Diverse Sets of Metadata", D-Lib
           Magazine, July/August 1996.
           http://www.dlib.org/dlib/july96/lagoze/07lagoze.html

[USMARC]   Network Development and MARC Standards, Office, ed. 1994.
           "USMARC Format for Bibliographic Data", 1994. Washington,
           DC: Cataloging Distribution Service, Library of Congress.

[REC-PICS] J. Miller, T. Krauskopf, P. Resnick, W. Treese, "PICS
           Label Distribution Label Syntax and Communication
           Protocols" Version 1.1, World Wide Web Consortium
           Recommendation REC-PICS-labels-961031.
           http://www.w3.org/pub/WWW/TR/REC-PICS-labels-961031.html.

[RFC2291]  Slein, J., Vitali, F., Whitehead, E. and D. Durand,
           "Requirements for Distributed Authoring and Versioning
           Protocol for the World Wide Web", RFC 2291, February 1998.

[RFC2413]  Weibel, S.,  Kunze, J., Lagoze, C. and M. Wolf, "Dublin
           Core Metadata for Resource Discovery", RFC 2413, September
           1998.

[RFC2376]  Whitehead, E. and M. Murata, "XML Media Types", RFC 2376,
           July 1998.

22. Authors' Addresses ๐Ÿ’Œ

Here's where you can find the authors. Their names, companies, and emails are all exactly as written ๐Ÿซถ

Y. Y. Goland
Microsoft Corporation
One Microsoft Way
Redmond, WA 98052-6399

EMail: yarong@microsoft.com
E. J. Whitehead, Jr.
Dept. Of Information and Computer Science
University of California, Irvine
Irvine, CA 92697-3425

EMail: ejw@ics.uci.edu
A. Faizi
Netscape
685 East Middlefield Road
Mountain View, CA 94043

EMail: asad@netscape.com
S. R. Carter
Novell
1555 N. Technology Way
M/S ORM F111
Orem, UT 84097-2399

EMail: srcarter@novell.com
D. Jensen
Novell
1555 N. Technology Way
M/S ORM F111
Orem, UT 84097-2399

EMail: dcjensen@novell.com

23 Appendices ๐ŸŽ€

Okay, the appendices are where the nitty-gritty lives, so grab a snack ๐Ÿ“

23.1 Appendix 1 - WebDAV Document Type Definition ๐Ÿ“œ

This part gives you a document type definition โœจ It follows the rules in [REC-XML] and describes the XML elements used in the protocol stream and in the values of properties. It basically gathers up all the element definitions from sections 12 and 13 into one neat spot ๐Ÿ’–

<!DOCTYPE webdav-1.0 [

<!--============ XML Elements from Section 12 ==================-->

<!ELEMENT activelock (lockscope, locktype, depth, owner?, timeout?,
locktoken?) >

<!ELEMENT lockentry (lockscope, locktype) >
<!ELEMENT lockinfo (lockscope, locktype, owner?) >

<!ELEMENT locktype (write) >
<!ELEMENT write EMPTY >

<!ELEMENT lockscope (exclusive | shared) >
<!ELEMENT exclusive EMPTY >
<!ELEMENT shared EMPTY >

<!ELEMENT depth (#PCDATA) >

<!ELEMENT owner ANY >

<!ELEMENT timeout (#PCDATA) >

<!ELEMENT locktoken (href+) >

<!ELEMENT href (#PCDATA) >

<!ELEMENT link (src+, dst+) >
<!ELEMENT dst (#PCDATA) >
<!ELEMENT src (#PCDATA) >

<!ELEMENT multistatus (response+, responsedescription?) >

<!ELEMENT response (href, ((href*, status)|(propstat+)),
responsedescription?) >
<!ELEMENT status (#PCDATA) >
<!ELEMENT propstat (prop, status, responsedescription?) >
<!ELEMENT responsedescription (#PCDATA) >
<!ELEMENT prop ANY >

<!ELEMENT propertybehavior (omit | keepalive) >
<!ELEMENT omit EMPTY >

<!ELEMENT keepalive (#PCDATA | href+) >

<!ELEMENT propertyupdate (remove | set)+ >
<!ELEMENT remove (prop) >
<!ELEMENT set (prop) >

<!ELEMENT propfind (allprop | propname | prop) >
<!ELEMENT allprop EMPTY >
<!ELEMENT propname EMPTY >

<!ELEMENT collection EMPTY >

<!--=========== Property Elements from Section 13 ===============-->
<!ELEMENT creationdate (#PCDATA) >
<!ELEMENT displayname (#PCDATA) >
<!ELEMENT getcontentlanguage (#PCDATA) >
<!ELEMENT getcontentlength (#PCDATA) >
<!ELEMENT getcontenttype (#PCDATA) >
<!ELEMENT getetag (#PCDATA) >
<!ELEMENT getlastmodified (#PCDATA) >
<!ELEMENT lockdiscovery (activelock)* >
<!ELEMENT resourcetype ANY >
<!ELEMENT source (link)* >
<!ELEMENT supportedlock (lockentry)* >
]>

23.2 Appendix 2 - ISO 8601 Date and Time Profile ๐Ÿ—“๏ธ

The creationdate property uses the ISO 8601 date format [ISO-8601] โœจ This section sets out a profile of that format for use with this spec. The profile is quoted from an Internet-Draft by Chris Newman, and it's mentioned here so his work gets proper credit ๐Ÿ™Œ

date-time       = full-date "T" full-time

full-date       = date-fullyear "-" date-month "-" date-mday
full-time       = partial-time time-offset

date-fullyear   = 4DIGIT
date-month      = 2DIGIT  ; 01-12
date-mday       = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on
month/year
time-hour       = 2DIGIT  ; 00-23
time-minute     = 2DIGIT  ; 00-59
time-second     = 2DIGIT  ; 00-59, 00-60 based on leap second rules
time-secfrac    = "." 1*DIGIT
time-numoffset  = ("+" / "-") time-hour ":" time-minute
time-offset     = "Z" / time-numoffset

partial-time    = time-hour ":" time-minute ":" time-second
                 [time-secfrac]

Numeric offsets are calculated as local time minus UTC (Coordinated Universal Time) ๐ŸŒ So to find the UTC equivalent, you subtract the offset from the local time. For example, 18:50:00-04:00 is the same time as 22:58:00Z ๐Ÿฆ‹

If the time in UTC is known but the offset to local time isn't, you can show that with an offset of "-00:00". This is different from an offset of "Z", which implies that UTC is the preferred reference point for the specified time ๐Ÿงš

23.3 Appendix 3 - Notes on Processing XML Elements ๐Ÿงฉ

23.3.1 Notes on Empty XML Elements

XML has two ways to say an element has no content ๐ŸŒธ The first is to write it as <A></A>. The second is to write it as <A/>. Both are semantically identical, so they mean the same thing โœจ

Using the <A></A> form is a violation of the XML specification if the associated DTD declares the element to be EMPTY (for example, <!ELEMENT A EMPTY>) ๐Ÿ™ˆ If that declaration is there, the empty element format <A/> must be used. If the element isn't declared to be EMPTY, then either <A></A> or <A/> may be used for empty elements ๐Ÿ’…

23.3.2 Notes on Illegal XML Processing

XML is a super flexible format, which makes it really easy to send data that looks legal but actually isn't ๐Ÿ‘€ The philosophy of "Be flexible in what you accept and strict in what you send" still applies, but it must not be applied inappropriately. XML is extremely flexible about white space, element ordering, inserting new elements, and so on. That flexibility doesn't stretch to cover extensions, especially not when it comes to the meaning of elements ๐ŸŽ€

There is no kindness in accepting illegal combinations of XML elements. At best it causes an unwanted result, and at worst it can cause real damage ๐Ÿ’€

Accepting illegal XML is not being nice. It's how things quietly break โš ๏ธ

23.3.2.1 Example - XML Syntax Error ๐Ÿ™…โ€โ™€๏ธ

The following request body for a PROPFIND method is illegal ๐Ÿšซ

<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
  <D:allprop/>
  <D:propname/>
</D:propfind>

The propfind element only allows for the allprop or the propname element, not both. So the above is an error and must be responded to with a 400 (Bad Request) ๐Ÿ˜ค

Now imagine a server that wanted to be "kind" and decided to pick the allprop element as the true element and respond to it. A client running over a bandwidth-limited line who meant to run a propname would be in for a big surprise if the server treated the command as an allprop ๐Ÿ˜ญ

And if a server were lenient and decided to reply to this request anyway, the results would vary randomly from server to server. Some servers would execute the allprop directive, and others would execute the propname directive. That reduces interoperability rather than increasing it ๐Ÿ™ƒ

23.3.2.2 Example - Unknown XML Element ๐Ÿ”

The previous example was illegal because it had two elements that were explicitly banned from appearing together in the propfind element. But XML is an extensible language, so you can imagine new elements being defined for use with propfind โœจ Below is the request body of a PROPFIND. Like the previous example, it must be rejected with a 400 (Bad Request) by a server that doesn't understand the expired-props element ๐Ÿซ 

<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:"
xmlns:E="http://www.foo.bar/standards/props/">
  <E:expired-props/>
</D:propfind>

To understand why a 400 (Bad Request) comes back, let's look at the request body the way a server unfamiliar with expired-props sees it ๐Ÿ•ต๏ธโ€โ™€๏ธ

<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:"
            xmlns:E="http://www.foo.bar/standards/props/">
</D:propfind>

According to the WebDAV-specific XML processing rules in section 14, a server that doesn't understand the expired-props element must ignore it. So the server sees an empty propfind, and by the definition of the propfind element, that's illegal ๐Ÿ˜ต

Please note that if the extension had been additive, it wouldn't necessarily have resulted in a 400 (Bad Request) ๐Ÿ’– For example, imagine the following request body for a PROPFIND:

<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:"
            xmlns:E="http://www.foo.bar/standards/props/">

  <D:propname/>
  <E:leave-out>*boss*</E:leave-out>
</D:propfind>

The previous example contains a made-up element called leave-out ๐Ÿฆ„ Its purpose is to stop any property whose name matches the submitted pattern from being returned. If that example were sent to a server that doesn't know leave-out, the only result is that leave-out gets ignored and a propname gets executed ๐ŸŒˆ

23.4 Appendix 4 -- XML Namespaces for WebDAV ๐ŸŒ

23.4.1 Introduction

All DAV compliant systems MUST support the XML namespace extensions as specified in [REC-XML-NAMES] ๐Ÿ’œ

23.4.2 Meaning of Qualified Names

[Note to the reader: This section does not appear in [REC-XML-NAMES], but is necessary to avoid ambiguity for WebDAV XML processors.] ๐Ÿ‘€

WebDAV compliant XML processors MUST interpret a qualified name as a URI constructed by appending the LocalPart to the namespace name URI โœจ Here's an example:

<del:glider xmlns:del="http://www.del.jensen.org/">
  <del:glidername>
       Johnny Updraft
  </del:glidername>
  <del:glideraccidents/>
</del:glider>

In this example, the qualified element name "del:glider" is interpreted as the URL "http://www.del.jensen.org/glider" ๐Ÿช‚

<bar:glider xmlns:del="http://www.del.jensen.org/">
  <bar:glidername>
       Johnny Updraft
  </bar:glidername>
  <bar:glideraccidents/>
</bar:glider>

This one looks different from the previous example, but it means exactly the same thing ๐Ÿ’… Each instance of the namespace name "bar" is replaced with "http://www.del.jensen.org/" and then appended to the local name for each element tag. So the resulting tag names match the previous example exactly ๐Ÿซถ

<foo:r xmlns:foo="http://www.del.jensen.org/glide">
  <foo:rname>
       Johnny Updraft
  </foo:rname>
  <foo:raccidents/>
</foo:r>

This example is semantically identical to the two before it. Each instance of the namespace name "foo" is replaced with "http://www.del.jensen.org/glide", which is then appended to the local name for each element tag. The resulting tag names are identical to the ones in the previous examples ๐ŸŒธ

Copyright (C) The Internet Society (1999). All Rights Reserved. ๐ŸŽ€

okay so this document and translations of it can be copied and furnished to others ๐Ÿ“„ and derivative works that comment on or explain it, or help with implementing it, can be prepared, copied, published and distributed ๐Ÿš€, in whole or in part, without restriction of any kind. the one condition is that the above copyright notice and this paragraph are included on all of those copies and derivative works ๐Ÿซถ

BUT (and this is a big but ๐Ÿ™…โ€โ™€๏ธ) this document itself may not be modified in any way. so no removing the copyright notice, and no removing references to the Internet Society or other Internet organizations. the exceptions are: when it's needed for developing Internet standards, in which case the procedures for copyrights defined in the Internet Standards process must be followed ๐Ÿ“š, or when it's being translated into languages other than English ๐ŸŒ

the limited permissions above are perpetual ๐Ÿ’œ and they will not be revoked by the Internet Society or its successors or assigns. forever and ever, bestie โœจ

๐Ÿ’€ the disclaimer, which is not something to skip:

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. ๐Ÿฆ‹


and that's the whole document!! ๐Ÿงš you made it through all 18 parts, bestie. we are SO done ๐Ÿ˜ญ๐Ÿ‘‘

๐Ÿ“ฆ where this page comes from