RFC 4825
The Extensible Markup Language (XML) Configuration Access Protocol (XCAP)
The Extensible Markup Language (XML) Configuration Access Protocol (XCAP) ๐
Okay bestie, this is RFC 4825 ๐, and it's a Standards Track document, so it's an actual Internet standard. J. Rosenberg from Cisco wrote it, it came out in May 2007, and it's part of the Network Working Group. The title block doesn't list anything it obsoletes or updates, so there's nothing to chase there. โจ
Status of This Memo
This document is an Internet standards track protocol for the Internet community ๐ฆ, and it's asking for discussion and suggestions for improvements. If you want the current standardization state and status of this protocol, check the current edition of the "Internet Official Protocol Standards" (STD 1) ๐. Distribution of this memo is unlimited ๐.
Copyright Notice
Copyright (C) The IETF Trust (2007). ๐
Abstract
Okay so this spec defines the Extensible Markup Language (XML) Configuration Access Protocol (XCAP) ๐ง. XCAP lets a client read, write, and modify application configuration data that's stored in XML format on a server. The main move is that XCAP maps XML document sub-trees and element attributes to HTTP URIs, so these pieces can be accessed directly by HTTP. It's giving direct access, no cap ๐ .
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4
2. Overview of Operation . . . . . . . . . . . . . . . . . . . . 5
3. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 5
4. Definitions . . . . . . . . . . . . . . . . . . . . . . . . . 6
5. Application Usages . . . . . . . . . . . . . . . . . . . . . . 7
5.1. Application Unique ID (AUID) . . . . . . . . . . . . . . . 7
5.2. Default Document Namespace . . . . . . . . . . . . . . . . 8
5.3. Data Validation . . . . . . . . . . . . . . . . . . . . . 9
5.4. Data Semantics . . . . . . . . . . . . . . . . . . . . . . 10
5.5. Naming Conventions . . . . . . . . . . . . . . . . . . . . 11
5.6. Resource Interdependencies . . . . . . . . . . . . . . . . 11
5.7. Authorization Policies . . . . . . . . . . . . . . . . . . 12
5.8. Data Extensibility . . . . . . . . . . . . . . . . . . . . 12
5.9. Documenting Application Usages . . . . . . . . . . . . . . 13
5.10. Guidelines for Creating Application Usages . . . . . . . . 13
6. URI Construction . . . . . . . . . . . . . . . . . . . . . . . 15
6.1. XCAP Root . . . . . . . . . . . . . . . . . . . . . . . . 15
6.2. Document Selector . . . . . . . . . . . . . . . . . . . . 16
6.3. Node Selector . . . . . . . . . . . . . . . . . . . . . . 18
6.4. Namespace Bindings for the Selector . . . . . . . . . . . 23
7. Client Operations . . . . . . . . . . . . . . . . . . . . . . 24
7.1. Create or Replace a Document . . . . . . . . . . . . . . . 26
7.2. Delete a Document . . . . . . . . . . . . . . . . . . . . 26
7.3. Fetch a Document . . . . . . . . . . . . . . . . . . . . . 26
7.4. Create or Replace an Element . . . . . . . . . . . . . . . 26
7.5. Delete an Element . . . . . . . . . . . . . . . . . . . . 29
7.6. Fetch an Element . . . . . . . . . . . . . . . . . . . . . 30
7.7. Create or Replace an Attribute . . . . . . . . . . . . . . 30
7.8. Delete an Attribute . . . . . . . . . . . . . . . . . . . 31
7.9. Fetch an Attribute . . . . . . . . . . . . . . . . . . . . 31
7.10. Fetch Namespace Bindings . . . . . . . . . . . . . . . . . 32
7.11. Conditional Operations . . . . . . . . . . . . . . . . . . 32
8. Server Behavior . . . . . . . . . . . . . . . . . . . . . . . 34
8.1. POST Handling . . . . . . . . . . . . . . . . . . . . . . 35
8.2. PUT Handling . . . . . . . . . . . . . . . . . . . . . . . 35
8.2.1. Locating the Parent . . . . . . . . . . . . . . . . . 35
8.2.2. Verifying Document Content . . . . . . . . . . . . . . 36
8.2.3. Creation . . . . . . . . . . . . . . . . . . . . . . . 37
8.2.4. Replacement . . . . . . . . . . . . . . . . . . . . . 41
8.2.5. Validation . . . . . . . . . . . . . . . . . . . . . . 42
8.2.6. Conditional Processing . . . . . . . . . . . . . . . . 43
8.2.7. Resource Interdependencies . . . . . . . . . . . . . . 44
8.3. GET Handling . . . . . . . . . . . . . . . . . . . . . . . 44
8.4. DELETE Handling . . . . . . . . . . . . . . . . . . . . . 45
8.5. Managing Etags . . . . . . . . . . . . . . . . . . . . . . 46
9. Cache Control . . . . . . . . . . . . . . . . . . . . . . . . 47
10. Namespace Binding Format . . . . . . . . . . . . . . . . . . . 47
11. Detailed Conflict Reports . . . . . . . . . . . . . . . . . . 47
11.1. Document Structure . . . . . . . . . . . . . . . . . . . . 48
11.2. XML Schema . . . . . . . . . . . . . . . . . . . . . . . . 50
12. XCAP Server Capabilities . . . . . . . . . . . . . . . . . . . 53
12.1. Application Unique ID (AUID) . . . . . . . . . . . . . . . 54
12.2. XML Schema . . . . . . . . . . . . . . . . . . . . . . . . 54
12.3. Default Document Namespace . . . . . . . . . . . . . . . . 56
12.4. MIME Type . . . . . . . . . . . . . . . . . . . . . . . . 56
12.5. Validation Constraints . . . . . . . . . . . . . . . . . . 56
12.6. Data Semantics . . . . . . . . . . . . . . . . . . . . . . 56
12.7. Naming Conventions . . . . . . . . . . . . . . . . . . . . 56
12.8. Resource Interdependencies . . . . . . . . . . . . . . . . 56
12.9. Authorization Policies . . . . . . . . . . . . . . . . . . 56
13. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
14. Security Considerations . . . . . . . . . . . . . . . . . . . 59
15. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 60
15.1. XCAP Application Unique IDs . . . . . . . . . . . . . . . 60
15.2. MIME Types . . . . . . . . . . . . . . . . . . . . . . . . 61
15.2.1. application/xcap-el+xml MIME Type . . . . . . . . . . 61
15.2.2. application/xcap-att+xml MIME Type . . . . . . . . . . 62
15.2.3. application/xcap-ns+xml MIME Type . . . . . . . . . . 63
15.2.4. application/xcap-error+xml MIME Type . . . . . . . . . 64
15.2.5. application/xcap-caps+xml MIME Type . . . . . . . . . 64
15.3. URN Sub-Namespace Registrations . . . . . . . . . . . . . 65
15.3.1. urn:ietf:params:xml:ns:xcap-error . . . . . . . . . . 65
15.3.2. urn:ietf:params:xml:ns:xcap-caps . . . . . . . . . . . 66
15.4. XML Schema Registrations . . . . . . . . . . . . . . . . . 67
15.4.1. XCAP Error Schema Registration . . . . . . . . . . . . 67
15.4.2. XCAP Capabilities Schema Registration . . . . . . . . 67
16. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 67
17. References . . . . . . . . . . . . . . . . . . . . . . . . . . 67
17.1. Normative References . . . . . . . . . . . . . . . . . . . 67
17.2. Informative References . . . . . . . . . . . . . . . . . . 69
1. Introduction โจ
Picture this ๐ธ: lots of communications apps, like Voice over IP, instant messaging, and presence, need network servers to look up per-user information while they're handling a request. That info lives inside the network, but the end user is the one managing it. And they can manage it from a bunch of places: the web, a wireless handset, or a PC app. Main character energy ๐.
There are so many examples of per-user info ๐. One is presence [20] authorization policy, which sets the rules for which watchers are allowed to subscribe to a presentity and what info they can access. Another is presence lists, which are the lists of users a watcher wants presence for [26]. One way to get presence for a list is to subscribe to a resource that represents that list [21]. In that case, the Resource List Server (RLS) needs access to the list so it can handle a SIP [16] SUBSCRIBE [28] request for it. Another option is for a watcher to subscribe to each user one by one. For that route, it's really handy to have a server store the list, so when the client boots up it just fetches the list from the server ๐ฆ. That way a user can reach their resource lists from different clients, which is so iconic ๐.
So this spec describes a protocol for manipulating that per-user data ๐ . It's called the Extensible Markup Language (XML) Configuration Access Protocol (XCAP) ๐ง. XCAP is a set of conventions for mapping XML documents and document components into HTTP URIs. It also has rules for how changing one resource affects another, data validation constraints, and authorization policies tied to access to those resources. Because of this structure, normal HTTP primitives can be used to manipulate the data, which is lowkey genius ๐ฅ. XCAP is heavily based on ideas borrowed from the Application Configuration Access Protocol (ACAP) [25], but it is not an extension of ACAP, and it doesn't depend on it at all ๐. Like ACAP, XCAP is meant to support the configuration needs of many applications, not just one ๐.
XCAP was not designed as a general purpose XML search protocol, an XML database update protocol, or a general purpose XML-based configuration protocol for network elements. Don't come for it with those expectations ๐.
2. Overview of Operation ๐ฆ
Every application (an application here means a use case that implies a collection of data and its associated semantics) that uses XCAP specifies an application usage (Section 5). That application usage defines the XML schema [2] for the data the application uses, plus other key info ๐. The main job of XCAP is letting clients read, write, modify, create, and delete pieces of that data. These operations run over HTTP/1.1 [6] ๐.
An XCAP server acts as a repository for collections of XML documents ๐. There are documents stored for each application, and within each application there are documents stored for each user. Each user can have multiple documents for a particular application ๐. To get at some component of one of those documents, XCAP defines an algorithm for building a URI that references that component. Components means any element or attribute inside the document. So the HTTP URIs used by XCAP can point to a whole document, or to pieces that are way more fine-grained than the XML document itself โจ. An HTTP resource that follows the naming conventions and validation constraints defined here is called an XCAP resource ๐ซถ.
Since XCAP resources are also HTTP resources, you can use HTTP methods on them ๐ธ. Reading an XCAP resource is done with HTTP GET, creating or modifying one is done with HTTP PUT, and removing one is done with an HTTP DELETE ๐ . XCAP resources don't represent processing scripts, so POST operations to HTTP URIs that represent XCAP resources are not defined ๐. Properties that HTTP attaches to resources, like entity tags, also apply to XCAP resources. Entity tags are honestly the MVP here ๐, because they allow a bunch of conditional operations to be performed โญ.
Here's a tricky bit ๐ง: XML documents that are equivalent for the purposes of many applications can still look different in their physical representation. For XCAP resources, the canonical form with comments [19] of an XML document decides the logical equivalence. In other words, the canonical specification determines how significant whitespace MUST be processed ๐ฅ. It also means that, for example, newly inserted attributes can show up in any order in the physical representation ๐.
Part 1 of 16 is done ๐ฆ more parts coming, don't leave me hanging bestie ๐
3. Terminology โจ
okay so bestie, this bit is the rulebook for the key words. When this doc says "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL", it's using them the way RFC 2119 [7] describes, and they mark requirement levels for compliant implementations ๐๐ฅ
4. Definitions ๐
these are the terms the whole doc leans on, so lock them in ๐
XCAP Resource: An HTTP resource representing an XML document, an element within an XML document, or an attribute of an element within an XML document that follows the naming and validation constraints of XCAP.
XCAP Server: An HTTP server that understands how to follow the naming and validation constraints defined in this specification.
XCAP Client: An HTTP client that understands how to follow the naming and validation constraints defined in this specification.
Application: A collection of software components within a network whose operation depends on data managed and stored on an XCAP server.
Application Usage: Detailed information on the interaction of an application with the XCAP server.
Application Unique ID (AUID): A unique identifier within the namespace of application unique IDs created by this specification that differentiates XCAP resources accessed by one application from XCAP resources accessed by another.
Naming Conventions: The part of an application usage that specifies well-known URIs used by an application, or more generally, specifies the URIs that are typically accessed by an application during its processing.
XCAP User Identifier (XUI): The XUI is a string, valid as a path element in an HTTP URI, that is associated with each user served by the XCAP server.
XCAP Root: A context that contains all the documents across all application usages and users that are managed by the server.
Document Selector: A sequence of path segments, with each segment being separated by a "/", that identify the XML document within an XCAP root that is being selected.
Node Selector: A sequence of path segments, with each segment being separated by a "/", that identify the XML node (element or attribute) being selected within a document.
Node Selector Separator: A single path segment equal to two tilde characters ~~ that is used to separate the document selector from the node selector within an HTTP URI.
Document URI: The HTTP URI containing the XCAP root and document selector, resulting in the selection of a specific document. As a result, performing a GET against the document URI would retrieve the document.
Node URI: The HTTP URI containing the XCAP root, document selector, node selector separator, and node selector, resulting in the selection of a specific XML node.
XCAP Root URI: An HTTP URI that represents the XCAP root. Although a syntactically valid URI, the XCAP Root URI does not correspond to an actual resource on an XCAP server. Actual resources are created by appending additional path information to the XCAP Root URI.
Global Tree: A URI that represents the parent for all global documents for a particular application usage within a particular XCAP root.
Home Directory: A URI that represents the parent for all documents for a particular user for a particular application usage within a particular XCAP root.
Positional Insertion: A PUT operation that results in the insertion of a new element into a document such that its position, relative to other children of the same parent, is set by the client.
5. Application Usages ๐
every XCAP resource on a server is tied to an application, and for an application to actually use those resources, somebody has to write down the app-specific rules ๐ that includes the XML schema for the data's structure and constraints, the well-known URIs used to bootstrap access to the data, and so on. all of that stuff gets defined in the application usage ๐ฆ
5.1. Application Unique ID (AUID) ๐ชช
each application usage gets a name called an Application Unique ID (AUID). this name uniquely identifies the application usage within the namespace of application usages, and it's different from the AUIDs used by other applications โจ AUIDs live in one of two namespaces. the first is the IETF namespace, which holds a set of tokens that are each registered with IANA. those registrations happen when standards track RFCs get published [27], following the guidelines in Section 15. the second is the vendor-proprietary namespace. every AUID in there starts with the reverse domain name of the organization creating it, then a period, then whatever vendor-defined token they want ๐ข so as an example, the example.com domain can make an AUID with the value "com.example.foo" but NOT "org.example.foo" ๐ โโ๏ธ (that "org" one isn't theirs to make!). AUIDs in the vendor namespace don't need to be registered with IANA, and that namespace is also meant for lab environments where nobody needs a central registry ๐งช the syntax for AUIDs, written in ABNF [12] (and borrowing some of the BNF from RFC 3986 [13]), looks like this:
AUID = global-a-uid / vendor-a-uid
global-a-uid = a-uid
a-uid = 1*a-uid-char
vendor-a-uid = rev-hostname "." a-uid
rev-hostname = toplabel *( "." domainlabel )
domainlabel = alphanum
/ alphanum *( alphanum / "-" ) alphanum
toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum
a-uid-char = a-uid-unreserved / pct-encoded / sub-delims
/ ":" / "@"
;pct-encoded from RFC 3986
;sub-delims from RFC 3986
alphanum = ALPHA / DIGIT
;DIGIT from RFC 4234
;ALPHA from RFC 4234
a-uid-unreserved = ALPHA / DIGIT / "-" / "_" / "~"
the allowed characters for the auid production are a subset of the pchar production from RFC 3986 ๐ซ the big difference is that it leaves out the ".", which is what lets the auid stay separate from the reverse hostname ๐ซถ
5.2. Default Document Namespace ๐ธ
so the XCAP server needs to match a URI to an element or attribute of a document, and any XML namespace prefixes inside the URI have to get expanded [3]. that expansion needs a namespace binding context ๐ง that context maps namespace prefixes to namespace URIs, and it also defines a default namespace for elements in the URI that don't have a prefix. the binding context comes from two places. first, the prefix-to-URI mapping comes from the URI itself (see Section 6.4). the default document namespace, though, is defined by the application usage, and it applies to every URI pointing at resources inside that application usage. every application usage MUST define a namespace URI for the default document namespace, to be used when evaluating URIs ๐ the default document namespace doesn't apply to elements or attributes inside the documents themselves -- it only applies to evaluating URIs within that application usage. "default document namespace" and "default namespace" are NOT the same thing ๐ the latter has its standard XML meaning, while the former is the default used when evaluating XCAP URIs. XCAP doesn't change in any way how XML documents work out their default namespace. but if a document contains a URI for an XCAP resource, the default document namespace from the application usage applies to that URI too ๐
5.3. Data Validation ๐
one of the jobs of an XCAP server is to validate the content of each XCAP resource whenever an XCAP client tries to modify one ๐ก๏ธ this happens through two mechanisms. first, all application usages MUST describe their document contents using XML schema [2]. the application usage MUST also identify the MIME type for documents that comply with that schema.
ngl, XML schemas can't express every kind of constraint ๐ญ for example, one element might hold an integer that sets the maximum number of instances of another element. a schema can't represent that, but the constraint can still matter to the application usage. so the application usage defines any extra constraints beyond what's in the schema.
uniqueness constraints are a HUGE deal ๐ a lot of the time an application needs only one instance of some element or attribute within a particular scope. each uniqueness constraint has to spell out which field, or combination of fields, must be unique, and then which scope that uniqueness applies to. one typical scope is all the elements of a certain name inside the same parent. another is all the URIs valid within a particular domain. in some cases, XML schema can express these constraints, since it provides the <unique> element for exactly that. other uniqueness constraints, like URI uniqueness across a domain, can't be expressed by schema at all. either way, whether or not the schema covers some of them, the application usage MUST specify all uniqueness requirements when it defines its data validation needs โจ
for example, the resource lists application usage [22] requires that each <list> element have a unique value for the name attribute within a single parent ๐ and the RLS services application usage [22] requires that the value of the uri attribute of the <service> element be a URI that is unique within the domain of the URI ๐
URI constraints are another kind of constraint. these are rules about the scheme or structure of the scheme-specific part of the URI. XML schema can't express these either, so if they matter to an application usage, they need to be explicitly called out ๐ฃ
referential integrity is another big one ๐ it matters when the name or value of an element or attribute is used as a key to select another element or attribute. an application usage MAY specify referential integrity constraints. however, XCAP servers are NOT a replacement for Relational Database Management Systems (RDBMS), so clients MUST NOT depend on servers to maintain referential integrity ๐ โโ๏ธ XCAP clients are responsible for making all the right changes to documents to keep referential integrity intact.
character encoding is the last one ๐ค XML lets documents use several different character sets. but this specification mandates that all documents used with XCAP MUST be encoded using UTF-8, and an application usage can't change that ๐
the data validation info gets used by both sides. clients use it to make sure the requests they build will be accepted by the server. servers use it to validate the constraints when they receive a request (except for referential integrity constraints, which the server doesn't validate) ๐ซง
5.4. Data Semantics โจ
Okay, so every application usage has its own meaning for the data in the XML document, and that meaning is what makes it all make sense ๐ง ๐ The application usage spells out that semantic so a client knows how to build a document that gets the result it wants. The server doesn't care about any of this ๐ It's purposefully unaware of what the data means and just manages it. The application usage explains the semantics in plain English prose ๐
One super important semantic is the base URI used to resolve any relative URI references pointing at XCAP resources ๐ธ And here's the tea: those relative references can't be resolved using the retrieval URI as the base URI ๐ So it's up to the application usage to say what the base URI is ๐ซถ
5.5. Naming Conventions ๐บ๏ธ
Besides defining what the document means for a specific application, an application usage also has to explain how applications find the documents they need ๐ง Like, it needs to define any well-known URIs used for bootstrapping, and document any other rules about the URIs an application uses. It should also document how documents reference each other ๐ All of these rules together are called naming conventions ๐
For a lot of application usages, users only need a single document ๐ In that case, it is RECOMMENDED that the application usage require the document to be called "index" and to live in the user's home directory ๐ก
Here's an example. The RLS services application usage lets an RLS get the contents of a resource list when it receives a SUBSCRIBE request for a SIP URI that identifies an RLS service ๐ฆ The application usage says the list of service definitions lives in a specific document with a specific name inside the global tree ๐ That means the RLS can make one single XCAP request to fetch the service definition for whatever service the SIP URI in the SUBSCRIBE request is tied to โจ
Naming conventions are used by XCAP clients to build their URIs ๐ซง The XCAP server doesn't use them at all ๐
5.6. Resource Interdependencies ๐ธ๏ธ
When a user changes an XCAP resource, a bunch of other resources can be affected too ๐ญ For example, if a user deletes an XML element in a document, they do it by sending a DELETE request to the URI for that element's resource ๐๏ธ But deleting that element also deletes all of its child elements and their attributes, and each of those is also an XCAP resource ๐คฏ So changing one resource can change the state of other resources, no cap ๐ง
Mostly, these interdependencies are fully spelled out by the XML schema the application usage uses ๐ But sometimes the server needs to link resources together, and a schema can't describe that kind of relationship ๐ โโ๏ธ That happens when a change in one document affects another document ๐ซ It's usually the case when an application usage defines a document that acts as a collection of information from other documents ๐
Here's an example. When a user creates a new RLS service (so, makes a new <service> element inside an RLS services document), the server adds that element to a read-only global list of services it keeps in the global tree ๐ The RLS reads that read-only global list when it processes a SIP SUBSCRIBE request ๐
Resource interdependencies are used by both XCAP clients and servers ๐ซถ
5.7. Authorization Policies ๐
By default, every user can access (read, modify, and delete) all the documents below their home directory, and any user can read documents in the global directory ๐ But only trusted users, the ones explicitly provisioned into the server, can modify global documents ๐ก๏ธ
An application usage can set a different authorization policy that applies to all the documents tied to that application usage โจ It can also say whether another application usage gets used to define the authorization policies ๐ฏ An application usage for setting authorization policies can even be defined after the main application usage is already defined ๐ฐ๏ธ In that case, the main application usage only needs to say that such a usage will be defined in the future ๐ฎ
If an application usage doesn't want to change the default authorization policy, it can just say the default policy is used ๐
The authorization policies the application usage defines are used by the XCAP server while it's operating ๐ฅ๏ธ
5.8. Data Extensibility ๐งฉ
An XCAP server MUST understand an application usage in order to process an HTTP request made against a resource for that particular application usage ๐ฏ It's not required for the server to understand everything inside a document used by an application usage ๐ The server does need to understand the baseline schema the application usage defines ๐ But those schemas can include points of extensibility where new content from other namespaces and their schemas can be added ๐ท Sometimes the server understands those namespaces, so it has access to their schemas, and sometimes it doesn't ๐คทโโ๏ธ
A server MUST allow documents that contain elements from namespaces it doesn't know ๐ซง In that case, the server can't check that the content is schema compliant, so it only verifies that the XML is well-formed โ
If a client wants to make sure a server supports a particular namespace before it operates on a resource, it can ask the server for its capabilities using the XCAP Capabilities application usage, which is discussed in Section 12 ๐
5.9. Documenting Application Usages ๐
Application usages are documented in specifications that convey all the information described above ๐ In particular, an application usage specification MUST provide the following information:
- Application Unique ID (AUID): If the application usage is meant for general use on the Internet, the application usage MUST register the AUID into the IETF tree using the IANA procedures defined in Section 15 ๐
- XML Schema ๐
- Default Document Namespace ๐ท๏ธ
- MIME Type ๐
- Validation Constraints โ
- Data Semantics ๐ง
- Naming Conventions ๐บ๏ธ
- Resource Interdependencies ๐ธ๏ธ
- Authorization Policies ๐
5.10. Guidelines for Creating Application Usages ๐จ
The main design task when you create a new application usage is to define the schema ๐ XCAP works with any XML document, but smart schema design makes the document way more efficient and useful when you manipulate it with XCAP โจ
XCAP gives you three basic ways to pick elements among a set of siblings: by the element's expanded name, by its position, or by the value of a specific attribute ๐ฏ Positional selection always lets a client get exactly what it wants ๐ฏ But it means the client has to cache a copy of the document so it can build the predicate ๐ฆ And if a client does a PUT, it has to rebuild the PUT processing a server would follow just to update its local cached copy ๐ต Otherwise, the client has to re-GET the document after every PUT, which is inefficient ๐ So it's a good idea to design schemas where common operations can happen without the client caching a copy of the document ๐ซถ
Without positional selection, a client can pick an element at each step by its expanded name or by the value of an attribute ๐ Lots of schemas have elements that can repeat within a parent (often minOccurs is zero or one, and maxOccurs is unbounded) ๐ So all of those elements share the same name, which leaves the attribute value as the only way to select one ๐ซ Because of that, if an application usage expects users to manipulate elements or attributes that are descendants of a repeatable element, that element SHOULD include, in its schema, an attribute that can be suitably used as a unique index ๐ And the naming conventions the application usage defines SHOULD specify that uniqueness constraint explicitly ๐ฃ
URIs often make a great choice for a unique index ๐ They have fundamental uniqueness properties, and they usually carry semantic meaning in the application usage too ๐ง But you have to be careful when you use a URI as an attribute value โ ๏ธ URI equality is usually complicated ๐ฎโ๐จ Attribute equality, though, is performed by the server using XML rules, which are based on case-sensitive string comparison ๐ค So XCAP matches URIs based on lexical equality, not functional equality ๐ง In those cases, an application usage SHOULD consider these implications carefully ๐ค
XCAP lets a client operate on a single element, attribute, or document at a time ๐งฑ Because of that, common operations a client wants to do might need a sequence of multiple requests ๐ข That's inefficient, and it opens the door to failures when another client changes the document in the middle of the sequence ๐ฑ In that situation, the client has to detect it using entity tags (discussed below in Section 7.11) and undo its earlier changes ๐ฉ That's very difficult ๐
So the schemas SHOULD be defined so that common operations generally need only a single request to perform ๐ Let's look at an example ๐ Say an application usage defines permissions for users to perform certain operations ๐ The schema can be designed in two ways ๐ธ In the first, the top level of the tree identifies users, and within each user there are the permissions associated with that user ๐ค In the alternative design, the top level of the tree identifies each permission, and within each permission there's the set of users who have it ๐
Now, if it's common in this application usage to change a user's permission from one value to another, the former schema design is better for xcap ๐ It only takes a single PUT to make that change ๐ In the latter case, either the entire document has to be replaced (which is a single operation), or two PUT operations have to happen: one to remove the user from the old permission, and one to add the user to the new permission ๐ค
Naming conventions are another key part of designing an application usage ๐๏ธ The application usage should make sure XCAP clients know where to "start" when they retrieve and modify documents of interest ๐งญ Usually this means specifying a well-known document at a well-known URI ๐ That document can contain references to other documents the client needs to read or modify ๐โจ
6. URI Construction ๐
okay so to actually touch an XCAP resource, the data has to be wrapped up as an HTTP URI ๐ XCAP has a specific naming convention for building these, and it goes like this: you glue the XCAP root onto the document selector, then the node selector separator, then a percent-encoded version of the node selector ๐ After all that, you can optionally tack on a query component that sets up the namespace bindings used to evaluate the URI โจ
the XCAP root is the enclosing context where every XCAP resource lives ๐ the document selector is a path that finds a document inside that root ๐ the node selector separator is a path segment whose value is ~~ ๐ฆ it SHOULD NOT be percent-encoded, which matches the advice in Section 2.3 of RFC 3986 [13] ๐ธ URIs containing %7E%7E should be normalized to ~~ before comparing, because they mean the same thing ๐ซถ
the node selector separator is basically syntactic sugar ๐ it's the thing that splits the document selector from the node selector ๐
the node selector is an expression that points at a piece of the document, like an element or an attribute ๐ง and here's the plot twist: ~~ can also show up inside the node selector itself ๐ญ so when that happens, the first ~~ in the URI is the one that counts as the separator ๐
the sections below go deeper into each of these pieces ๐
6.1. XCAP Root ๐ธ
the root of the XCAP hierarchy is called the XCAP root ๐ณ it's the context in which every other resource exists โจ the XCAP root is written as an HTTP URI, called the XCAP Root URI ๐ it's a totally valid HTTP URI, but it doesn't point at any resource that actually exists on the server ๐ its whole job is to name the root of the tree inside the domain where all the XCAP documents are stored ๐
it can be any valid HTTP URI, but it MUST NOT contain a query component ๐ซ (a full XCAP URI can have a query component, but that's not part of the XCAP root URI, so don't mix them up ๐) it is RECOMMENDED that it be equal to xcap.domain, where domain is the domain of the provider ๐ for example, http://xcap.example.com could be the XCAP root URI within the example.com domain ๐ usually the XCAP root URI gets provisioned straight into client devices ๐ฑ if it isn't explicitly provisioned, clients SHOULD assume the form xcap.domain, where domain is the domain of their service provider (for SIP, that's the domain part of their Address-of-Record (AOR)) ๐ง
a server or domain MAY support multiple XCAP root URIs ๐ฆ when it does, it's basically acting like it's serving separate domains ๐ and there is never any information carryover or interaction between resources living under different XCAP root URIs ๐ โโ๏ธ no drama, no mixing ๐
when a client sends an HTTP request to a URI that identifies an XCAP resource, the RFC 2616 procedures for building the Request-URI apply ๐จ in particular, the authority component may not be present in the Request-URI if the request goes straight to the origin server ๐ธ
the XCAP root URI can also be a relative HTTP URI ๐งญ it's the application usage's job to specify the base URI for any HTTP URI representing an XCAP resource that shows up inside a document defined by that application usage ๐ and generally speaking, using the retrieval URI as the base URI is unsafe ๐ฌ why? any URI pointing at an ancestor of a particular element or attribute can carry content that includes that element or attribute ๐ if that element or attribute contained a relative URI reference, it would get resolved against whatever was used to retrieve the content, which often won't be the base URI the application usage defined ๐ so be careful, bestie ๐ซถ
6.2. Document Selector ๐
every document inside the XCAP root is identified by its document selector ๐ it's a sequence of path segments separated by a slash ("/") ๐ช those segments set up a hierarchy for organizing documents within any XCAP root ๐ฐ the first path segment MUST be the XCAP AUID ๐ so, continuing the example from before, all the documents used by the resource lists application would live under http://xcap.example.com/resource-lists ๐
- Implementors making use of HTTP servlets should be aware that XCAP may require them to get authorization from the server administrator to place resources within this specific subset of the URI namespace. ๐จ
it's assumed that each application will have data that's set by users, and/or global data that applies to all users ๐ so beneath each AUID there are two sub-trees ๐ณ one is called "users", which holds documents that apply to specific users ๐ค the other is called "global", which holds documents that apply to everyone ๐ the sub-tree beneath "global" is called the global tree ๐ง the path segment right after the AUID MUST be either "global" or "users" ๐
inside the "users" tree there are zero or more sub-trees, and each one identifies documents for a specific user ๐ฏโโ๏ธ every user the server knows about is tied to a username, called the XCAP User Identifier (XUI) ๐ชช an endpoint is usually provisioned with its XUI value ๐ฒ for systems that support SIP applications, it is RECOMMENDED that the XUI be equal to the user's Address-of-Record (AOR), like sip:joe@example.com ๐ since SIP endpoints generally know their AOR, they'll know their XUI too ๐ง so if no XUI is explicitly provisioned, a SIP User Agent SHOULD assume it's equal to their AOR ๐ this XUI MUST be used as the path segment beneath the "users" segment ๐
here's the tricky bit ๐ญ the SIP URI allows characters that HTTP URI path segments don't (like the '?' and '/' characters, which are allowed in the user part of a SIP URI) ๐ so any such characters MUST be percent encoded ๐ the sub-tree beneath an XUI for a particular user is called their home directory ๐ก and "user" should be read loosely here, since a user might correspond to a device, for example ๐ฑโจ
XCAP doesn't itself define what it means for documents to "apply" to a user ๐คทโโ๏ธ beyond a baseline authorization policy (described below in Section 8) ๐ก๏ธ each application usage can add its own authorization policies that depend on the data the application uses ๐ซถ
the rest of the document selector (the path following "global" or the XUI) points at specific documents for that application usage ๐ subdirectories are permitted, but they're NOT RECOMMENDED ๐ฌ XCAP doesn't give you any way to create sub-directories or list their contents, so they're not super useful ๐ if you do use subdirectories, there MUST NOT be a document in a directory with the same name as a sub-directory ๐ซ
the final path segment in the document selector identifies the actual document ๐ฏ it's basically a filename, except XCAP doesn't require document resources to be stored as files in a file system ๐พ the term "filename" is still used to describe that final path segment anyway ๐ท๏ธ in traditional filesystems, a filename would have an extension, like .xml ๐ nothing in this specification requires or prevents extensions in the filename ๐ค some application usages will specify a naming convention for documents, and those conventions may or may not specify a file extension ๐งฉ for example, in the RLS services application usage [22], documents in the user's home directory with the filename "index" are used by the server to compute the global index, which is also a document with the filename "index" ๐ barring specific guidelines in the application usage, if a user has a single document for a particular application usage, it SHOULD be called "index" โจ
when the naming conventions in an application usage don't constrain filenames (or, more generally, the document selector), an application still knows the filename (or the document selector) because it's included as a reference in a document the client accessed ๐ as another example, inside the index document defined by RLS services, the <service> element has a child element called <resource-list> whose content is a URI pointing at a resource list in the user's home directory ๐
so if a user creates a new document and then references it from a well-known document (like the index document above), it doesn't matter whether or not they include an extension in the filename ๐ as long as they're consistent and keep referential integrity ๐ซถ๐
for example, the path segment "/resource-lists/users/sip:joe@example.com/index" is a document selector ๐ concatenating the XCAP root URI with the document selector gives the HTTP URI http://xcap.example.com/resource-lists/users/sip:joe@example.com/index ๐ in this URI, the AUID is "resource-lists", and the document lives in the user tree with the XUI "sip:joe@example.com" and the filename "index" ๐
6.3. Node Selector ๐ฆ
the node selector specifies the particular nodes of the XML document that are going to be accessed ๐ฏ a node can be an XML element, an attribute of an element, or a set of namespace bindings ๐งฉ the node selector is an expression that identifies an element, an attribute, or a set of namespace bindings ๐ its grammar is:
node-selector = element-selector ["/" terminal-selector]
terminal-selector = attribute-selector / namespace-selector /
extension-selector
element-selector = step *( "/" step)
step = by-name / by-pos / by-attr / by-pos-attr /
extension-selector
by-name = NameorAny
by-pos = NameorAny "[" position "]"
position = 1*DIGIT
attr-test = "@" att-name "=" att-value
by-attr = NameorAny "[" attr-test "]"
by-pos-attr = NameorAny "[" position "]" "[" attr-test "]"
NameorAny = QName / "*" ; QName from XML Namespaces
att-name = QName
att-value = AttValue ; from XML specification
attribute-selector = "@" att-name
namespace-selector = "namespace::*"
extension-selector = 1*( %x00-2e / %x30-ff ) ; anything but "/"
the QName grammar is defined in the XML namespaces [3] specification ๐ and the AttValue grammar is defined in the XML specification, XML 1.0 [1] ๐ง
the extension-selector is there for extensibility ๐ฑ it can be composed of any character except the slash, which is the delimiter between steps ๐ช any characters in an extension that can't be represented in a URI MUST be percent-encoded before they go into a URI ๐
heads up, bestie ๐จ the double quote, left square bracket and right square bracket characters are meaningful to XCAP, but they can't be directly represented in an HTTP URI ๐ญ so they get percent-encoded when they're placed inside the HTTP URI ๐ on top of those, an apostrophe (') can be used as a delimiter within XPath expressions ๐ and since XML allows non-ASCII characters, the names of elements and attributes may not be directly representable in a URI ๐ any such characters MUST be represented by converting them to an octet sequence matching their UTF-8 representation, and then percent-encoding that sequence of octets ๐ซถโจ
Okay so now we're getting into the XML side of things, and bestie, it's giving detailed ๐๐
The QName production handles element and attribute names, and AttValue handles attribute values. ngl, the catch is that these productions allow some characters that pchar (the set of characters allowed in URI path segments) doesn't. AttValue lets through a lot of US-ASCII characters, including the space, and those characters MUST be percent-encoded when placed in the URI. ๐
QName and AttValue also allow plenty of Unicode characters beyond US-ASCII. When those need to go into the HTTP URI, they get percent-encoded too. The process is: first encode the data as octets using UTF-8 [18], then percent-encode only the octets that don't correspond to characters in the pchar set. Some examples: the character A stays as "A", LATIN CAPITAL LETTER A WITH GRAVE becomes "%C3%80", and KATAKANA LETTER A becomes "%E3%82%A2" ๐ฆโจ
So the grammar above describes the expressions the XCAP server works with internally, after it has decoded the URI. The on-the-wire format is set by RFC 3986 [13] ๐ In the discussions and examples below, when a node selector isn't part of an HTTP URI, it's shown in its internal format before encoding. If an example has a node selector inside an HTTP URI, it's shown in its percent-encoded form ๐ธ
The node selector is based on the concepts in XPath [10]. Honestly, before it gets percent-encoded for the HTTP URI, the node selector expression just happens to be a valid XPath expression ๐ But XPath does way more than we need here, and all that extra breadth would add a lot of unneeded complexity to XCAP ๐ญ
To figure out which XML element, attribute, or namespace bindings a node selector picks, processing starts at the root node of the XML document. Then the first step in the element selector gets taken. Each step chooses a single XML element within the current document context. The document context is the point in the XML document a specific step gets evaluated from, and it starts at the root node of the document. When a step finds an element inside that context, that element becomes the new context for the next step. Each step can select an element by its name (expanded), by a mix of name and attribute value, by name and position, or by name, position and attribute. In every case the name can be wildcarded, so that all elements get selected ๐ง
Here's how the selection works. Inside the current document context, the children of that context get listed in document order. If the context is the root node of the document, its child element is the root element of the document. If the context is an element, its children are all of that element's children (naturally ๐ ). Next, any elements whose name doesn't match NameorAny get thrown out. An element name is a match if NameorAny is the wildcard, or if NameorAny isn't a wildcard and the element name matches it. Matching is covered below. What's left is an ordered list of elements ๐
Then the predicates filter that list. Predicates are the expressions in square brackets that come after NameorAny. Each predicate trims the current ordered list further, and they get evaluated in order. If the predicate's content is a position, the element at that position gets selected (basically treat "position" as a variable and grab the element whose position equals it), and everything else is discarded. If the list has fewer elements than the position value, the result is a no-match ๐ญ
If the predicate's content is an attribute name and value, every element that has an attribute with that name and value gets selected, and the rest get discarded. Heads up though: even if a document has namespace declarations inside elements, those elements can't be selected by using a namespace declaration as a predicate. So a step like el-name[@xmlns='namespace'] will never match an element, even if an element in the list declares a default namespace of "namespace". In other words, a namespace node is NOT an attribute ๐ If you need the namespaces in scope for an element, you can select them with the namespace selector described below. If no elements have attributes with the given name and value, the result is a no-match ๐
Once the predicates have been applied, the result is either a no-match, one element, or multiple elements. If there are multiple elements, the node selector is invalid. Each step in a node selector MUST produce a single element to form the context for the next step. That's stricter than general XPath expressions, which let a context hold multiple nodes ๐ If the result is a no-match, the node selector is invalid too. The node selector is only valid when a single element was selected, and that element becomes the context for evaluating the next step in the node selector expression ๐ฅ
The last location step is either the element selector we just described or a "terminal selector". If the terminal selector is an attribute selector, the server checks whether the current element context has an attribute with the same expanded name. If it doesn't, the result is a no-match. Otherwise, that attribute gets selected โจ If the terminal selector is a namespace selector, the result is the set of namespace bindings in scope for the element, including the possible default namespace declaration. This specification defines a syntax for representing namespace bindings, so they can be sent back to the client in an HTTP response ๐
So once the whole node selector has been evaluated against the document, the result will be one of these: a no-match, invalid, a single element, a single attribute, or a set of namespace bindings. Slay, that's the full menu ๐
Matching element names works like this. The element being compared in the step has its name expanded as described in XML namespaces [3]. The element name in the step gets expanded too. That expansion means converting any namespace prefix into its namespace URI, which needs a set of bindings from prefixes to namespace URIs. That set of bindings comes from the query component of the URI (see Section 6.4). If the QName's prefix on an element is empty, the URI becomes the default document namespace URI defined by the application usage, or null if none is defined. Then comparisons get done as described in XML namespaces [3]. Also, the namespace prefix expansions here are different from the ones in the XPath 1.0 specification, but they're closer to what the XPath 2.0 specification [24] currently defines ๐ฆ
Matching attribute names is pretty similar. The attribute in the document has its name expanded as described in XML namespaces [3]. If the attribute name in the attribute selector has a namespace prefix, it gets expanded using the namespace bindings from the query component of the URI. An unprefixed attribute QName is in no namespace ๐ธ
Comments, text content (including whitespace), and processing instructions can all be in a document, but the expressions defined here can't select them. Still, if that kind of information is in a document and a user selects an XML element enclosing it, that information gets included in a resulting GET, for example ๐ซถ Whitespace also matters in XCAP. If a client PUTs an element or document containing whitespace, the server keeps that whitespace and sends the element or document back with exactly the same whitespace โจ Similarly, when an element is inserted, no extra whitespace gets added around it, and it gets inserted at a very specific spot relative to any whitespace, comments, or processing instructions around it. Section 8.2.3 describes where the insertion happens ๐
Here's an example XML document to play with ๐
<?xml version="1.0"?>
<watcherinfo xmlns="urn:ietf:params:xml:ns:watcherinfo"
version="0" state="full">
<watcher-list resource="sip:professor@example.net"
package="presence">
<watcher status="active"
id="8ajksjda7s"
duration-subscribed="509"
event="approved">sip:userA@example.net</watcher>
<watcher status="pending"
id="hh8juja87s997-ass7"
display-name="Mr. Subscriber"
event="subscribe">sip:userB@example.org</watcher>
</watcher-list>
</watcherinfo>
Figure 3: Example XML Document
Assuming the default document namespace for this application usage is "urn:ietf:params:xml:ns:watcherinfo", the node selector watcherinfo/watcher-list/watcher[@id="8ajksjda7s"] selects this XML element ๐ฆ
<watcher status="active"
id="8ajksjda7s"
duration-subscribed="509"
event="approved">sip:userA@example.net</watcher>
6.4. Namespace Bindings for the Selector ๐
okay so, to expand the namespace prefixes in the node selector, you need a set of bindings that map each prefix to a namespace URI ๐ those bindings live in the query component of the URI โจ if there's no query component, only the default document namespace (the one the application usage identifies) is defined ๐ธ
the query component is formatted as a valid xpointer expression [5] after suitable URI encoding, as defined in Section 4.1 of the Xpointer framework ๐ฆ this xpointer expression SHOULD only contain expressions from the xmlns() scheme [4] ๐ a server compliant to this specification MUST ignore any xpointer expressions that aren't from the xmlns() scheme ๐ the xmlns() xpointer expressions define the set of namespace bindings used for evaluating the URI
note that xpointer expressions were originally designed for fragment identifiers in URIs ๐ง within XCAP, though, they get used in query components instead โจ
here's a more complex matching example, this time with namespace bindings involved ๐ take this document:
<?xml version="1.0"?>
<foo xmlns="urn:test:default-namespace">
<ns1:bar xmlns:ns1="urn:test:namespace1-uri"
xmlns="urn:test:namespace1-uri">
<baz/>
<ns2:baz xmlns:ns2="urn:test:namespace2-uri"/>
</ns1:bar>
<ns3:hi xmlns:ns3="urn:test:namespace3-uri">
<there/>
</ns3:hi>
</foo>
say this document has the document URI "http://xcap.example.com/test/users/sip:joe@example.com/index", where "test" is the application usage ๐ that application usage defines a default document namespace of "urn:test:default-namespace" ๐ this XCAP URI:
http://xcap.example.com/test/users/sip:joe@example.com/index/
~~/foo/a:bar/b:baz?xmlns(a=urn:test:namespace1-uri)
xmlns(b=urn:test:namespace1-uri)
will select the first <baz> child element of the <bar> element in the document ๐ญ and this one:
http://xcap.example.com/test/users/sip:joe@example.com/index/
~~/foo/a:bar/b:baz?xmlns(a=urn:test:namespace1-uri)
xmlns(b=urn:test:namespace2-uri)
will select the second <baz> child element of the <bar> element in the document ๐ฅ and this XCAP URI will also select that second <baz> child element of the <bar> element:
http://xcap.example.com/test/users/sip:joe@example.com/index/
~~/d:foo/a:bar/b:baz?xmlns(a=urn:test:namespace1-uri)
xmlns(b=urn:test:namespace2-uri)
xmlns(d=urn:test:default-namespace)
the same element, three different ways to get there ๐ง iconic behaviour, honestly ๐
7. Client Operations โจ
okay, the XCAP client is an HTTP/1.1 compliant client ๐ซถ specific data manipulation tasks happen by invoking the right set of HTTP methods with the right set of headers on the server ๐ this section breaks all of that down ๐
in every case where the client modifies a document, by deleting or inserting a document, element or attribute resource, the client SHOULD verify that, if the operation were to succeed, the resulting document would meet the data constraints defined by the application usage, including schema validation โจ for example, if the client does a PUT to http://xcap.example.com/rls-services/users/sip:joe@example.com/mybuddies, then rls-services is the application unique ID, and the constraints it defines SHOULD be followed ๐ฆ
the client knows which URI to use from the naming conventions the application usage describes ๐ธ
if the document doesn't meet the data constraints after modification, the server rejects it with a 409 ๐ the 409 response MAY contain an XML body, formatted according to the schema in Section 11.2, giving more info on what went wrong ๐ the client MAY use that info to change the request so it might work this time ๐ the client SHOULD NOT just retry the request without changing some aspect of it, bestie ๐ค
sometimes the application usage sets a uniqueness constraint the client can't guarantee on its own ๐ฅบ one example: a URI has to be unique within a domain, and the client usually doesn't own the domain, so it can't be sure a URI is unique ๐ in that case, the client can either generate a sufficiently random identifier, or pick a "vanity" identifier and hope nobody else took it ๐ either way, if the identifier isn't unique, the server rejects the request with a 409 and suggests alternatives the client can use to try again ๐ซ if the server doesn't suggest alternatives, the client SHOULD attempt to use random identifiers with increasing amounts of randomness ๐ฒ
HTTP also says PUT and DELETE requests are idempotent ๐ง that means if a PUT on a document succeeds, the client can do the same PUT again and the resulting document will look the same ๐ similarly, if a DELETE succeeds, a later DELETE to the same URI generates a 404, because the resource was already removed by the previous DELETE ๐ชฆ to keep this property, the client SHOULD construct its URIs so that, after the change, the URI in the request points to the resource just inserted for a PUT (the body of the request), and points to nothing for a DELETE ๐ฏ when this holds, a GET to the URI in the PUT returns the same content, meaning GET(PUT(X)) == x ๐ that property implies idempotency โจ a request can still be idempotent without it, but XCAP does not permit such requests ๐ซ if the client's request doesn't have this property, the server rejects it with a 409 and indicates a cannot-insert error condition ๐ฌ
if a PUT comes back with a 200 or 201 response, the operation was successful ๐ any other response codes, like a redirection, are processed as per RFC 2616 [6] ๐ซถ
7.1. Create or Replace a Document ๐
to create or replace a document, the client builds a URI pointing to where the document should go ๐บ๏ธ this URI MUST be a document URI, so it has to include the XCAP root and document selector ๐ then the client invokes a PUT method on that URI ๐
the MIME content type MUST be the type the application usage defines ๐ for example, it'd be application/rls-services+xml for an RLS services [22] document, not plain application/xml ๐
โโ๏ธ
if the Request-URI identifies a document that already exists on the server, the PUT replaces that document with the content of the request ๐ if the Request-URI doesn't identify an existing document, the document gets created on the server at that exact URI ๐ฑ
7.2. Delete a Document ๐๏ธ
to delete a document, the client builds a URI that references the document to be deleted ๐ฏ this URI MUST be a document URI ๐ then the client invokes a DELETE operation on that URI to delete the document ๐
7.3. Fetch a Document ๐ฅ
as you'd expect, fetching a document is super easy ๐ฅฐ you just perform an HTTP GET request with the Request URI set to the document URI โจ
7.4. Create or Replace an Element โจ
okay so bestie, to create or replace an XML element inside a document that already exists, the client builds a URI whose document selector points at the doc being changed. The node selector MUST be in the URI, separated from the document selector by the node selector separator ๐ . The query component MUST be there if the node selector uses namespace prefixes, and the xmlns() expressions in the query component MUST define those prefixes ๐. To create the element, the node selector has to be a no-match against the current document. But if the element in the request body got added the way the client wants, the node selector would select it โจ. To replace an element, the node selector has to match the element that's currently there AND match the new element in the PUT body that's replacing it ๐ฆ.
Sometimes the client wants to slot an element into a certain spot among its siblings. This is called a positional insertion ๐ง. It usually happens because the schema says where the element is allowed to go, or because the order of elements matters inside the schema. The node selector for this looks like:
parent/*[position][unique-attribute-value]
Here's what each piece means:
- "parent" is an expression for the parent of the element being inserted.
- "position" is the spot amongst the existing child elements of that parent where the new element goes.
- "unique-attribute-value" is an attribute name and value for the element being inserted. It has to be different from the current element in "position".
That second predicate is what keeps the whole expression a no-match when it's checked against the current children. Without it, the PUT would just replace whatever is already sitting in that position ๐. Also, in addition to the wildcard "*", a QName can be used as the node test. The insert logic gets more detail in Section 8.2.3, so go check that out if you want the full tea โ.
Let's look at the example document in Figure 3. The client wants to insert a new <watcher> element as the second element underneath <watcher-list>. But it can't just PUT to watcherinfo/watcher-list/*[2], because that node selector would select the existing second child element of <watcher-list> and replace it ๐. So the PUT has to go to a URI with watcherinfo/watcher-list/*[2][@id="hhggff"] as the node selector, where "hhggff" is the value of the "id" attribute on the new element. That node selector is a no-match against the current document, but it would be a match against the new element if it got inserted as the second child element of <watcher-list> ๐ญ.
The "*" means all element children of <watcher-info> get counted when the position for insertion is worked out. If there's an element name (QName) in place of the *, the expression above would insert the new element as the position-th element among the ones with the same expanded name (again, see Section 8.2.3 for the insertion rules).
Once the client has built the URI, it invokes the HTTP PUT method. The content in the request MUST be an XML element. Specifically, it's the element starting with the opening bracket of its begin tag, including its attributes and content (text or other child elements), and ending with the closing bracket of its end tag. The MIME type in the request MUST be application/xcap-el+xml, which is defined in Section 15.2.1 ๐ธ. If the node selector is a no-match when evaluated against the current document, the server does a creation. If the node selector is a match for an element in the current document, the server replaces that element with the content of the PUT request. This replacement is complete, so the old element (its attributes, namespace declarations and content: text, element, comment and processing instruction nodes) gets removed, and the new one (with its own attributes, namespace declarations and content) goes right in its place โจ.
Bestie, the GET(PUT(x))==x property is the whole vibe for element insertions. To make sure it holds, the client can check that the attribute predicates in the final path segment of the URI match the attributes of the element in the request body ๐ซถ.
Here's an example of a request that would NOT have this property, so it wouldn't be idempotent ๐. (URIs are line-folded for readability.)
PUT
/rls-services/users/sip:bill@example.com/index/~~/rls-services/
service%5b@uri=%22sip:good-friends@example.com%22%5d
HTTP/1.1
Content-Type:application/xcap-el+xml
Host: xcap.example.com
<service uri="sip:mybuddies@example.com">
<resource-list>http://xcap.example.com/resource-lists/users
/sip:joe@example.com/index/~~/resource-lists/list%5b@name=%22l1%22%5d
</resource-list>
<packages>
<package>presence</package>
</packages>
</service>
This request will fail with a 409 ๐ โโ๏ธ. The Request URI has a final path segment with an attribute-based predicate: @uri="sip:good-friends@example.com". But that won't match the value of the "uri" attribute in the element in the body (sip:mybuddies@example.com). Not it, bestie.
The GET(PUT(x))==x property also puts some limits on what operations are possible. It won't be possible to replace an element with one that has a new value for an attribute that is the sole unique element identifier, if the URI had a node selector that used the previous value of that attribute to select the element. That's exactly what happens in the example above ๐ญ. To get around this, the selection can be done by position instead of by attribute value. Or the client can select the parent of the element being replaced, and then the body of the PUT operation would contain the parent, the child being replaced, and all the other siblings ๐.
7.5. Delete an Element ๐๏ธ
To delete an element from a document, the client builds a URI whose document selector points at the document that contains the element being deleted. The node selector MUST identify a single element. The node selector MUST be present following the node selector separator, and it has to identify the specific element to be deleted. On top of that, the node selector MUST match no element after the deletion of the target element. This is required to keep the idempotency property of HTTP deletions, which is a big deal ๐. The query component MUST be present if the node selector uses namespace prefixes, and in that case the xmlns() expressions in the query component MUST define those prefixes ๐.
If the client wants to delete an element in a specific position, that's called a positional deletion ๐. Just like a positional insertion, the node selector has this form:
parent/*[position][unique-attribute-value]
Where:
- "parent" is an expression for the parent of the element being deleted.
- "position" is the position of the element being deleted amongst the existing child elements of that parent.
- "unique-attribute-value" is an attribute name and value for the element being deleted, where this attribute name and value are different from any of the siblings of the element.
Positional deletions without a unique attribute name and value are possible, but only in limited cases where idempotency is guaranteed ๐. Specifically, if a DELETE operation refers to an element by name and position alone (parent/elname[n]), that's only allowed when the element being deleted is the last element amongst all its siblings with that name. And if a DELETE operation refers to an element by position alone (parent/*[n]), that's only allowed when the element being deleted is the last amongst all sibling elements, no matter the name.
Then the client invokes the HTTP DELETE method. The server removes the element from the document, including its attributes, namespace declarations, and its descendant nodes (like any children) ๐ .
7.6. Fetch an Element ๐ท
To fetch an element of a document, the client builds a URI whose document selector points at the document that contains the element to be fetched. The node selector MUST be present following the node selector separator, and must identify the element to be fetched. The query component MUST be present if the node selector uses namespace prefixes, and in that case the xmlns() expressions in the query component MUST define those prefixes โจ.
The client then invokes the GET method. The 200 OK response will contain that XML element. Specifically, it contains the content of the XML document, starting with the opening bracket of the begin tag for that element and ending with the closing bracket of the end tag for that element. Because of that, you get everything: all attributes, namespace declarations and descendant nodes (elements, comments, text, and processing instructions) of that element ๐ฆ๐
7.7. Create or Replace an Attribute โจ
okay so to create or replace an attribute ๐ in an existing element, the client builds a URI whose document selector points at the doc being changed. The node selector, right after the node selector separator, MUST be present ๐ It also MUST be built so that, if the attribute got created or replaced exactly how you want, the node selector would pick out that attribute ๐ฆ If the node selector hits nothing when checked against the current document, it's a creation. If it matches an existing attribute, it's a replacement ๐ซถ The query component MUST be present if the node selector uses namespace prefixes, and in that case the xmlns() expressions in the query component MUST define those prefixes ๐
Then the client invokes the HTTP PUT method ๐ธ The content of the request MUST be the value of the attribute, following the AttValue grammar from XML 1.0 [1]. Note that, unlike when AttValue shows up in the URI, the body is not percent-encoded ๐ This request MUST be sent with the Content-Type of "application/xcap-att+xml", as defined in Section 15.2.2 โจ The server adds the attribute so that, when the node selector gets evaluated on the resulting document, it returns the attribute from the request ๐ง
To make sure attribute insertions keep the GET(PUT(x))==x property ๐ the client can check that any attribute predicate in the path segment selecting the element being inserted into matches a different attribute than the one this request is inserting. Here's an example of a request that doesn't have that property, so it isn't idempotent ๐ (URIs are line-folded so they're readable):
PUT
/rls-services/users/sip:bill@example.com/index/~~/rls-services
/service%5b@uri=%22sip:good-friends@example.com%22%5d/@uri
HTTP/1.1
Content-Type:application/xcap-att+xml
Host: xcap.example.com
"sip:bad-friends@example.com"
This request will fail with a 409 ๐ญ
Same deal as with element insertions and replacements: keeping GET(PUT(x))==x puts limits on attribute replacements too ๐ You can't replace the value of an attribute when that attribute is the only unique element identifier AND the URI has a node selector that uses the attribute's previous value to select the element. That's exactly what's going on in the example above ๐ฅบ Instead, you can select the element by position, or replace its entire parent ๐
7.8. Delete an Attribute ๐งน
To delete an attribute from a document, the client builds a URI whose document selector points at the doc containing the attribute. The node selector MUST be present right after the node selector separator, and it has to evaluate to an attribute in the document being deleted ๐ The query component MUST be present if the node selector uses namespace prefixes, and then the xmlns() expressions in the query component MUST define those prefixes โจ
Next, the client invokes the HTTP DELETE method, and the server removes the attribute from the document ๐
7.9. Fetch an Attribute ๐
To fetch an attribute, the client builds a URI whose document selector points at the doc containing that attribute. The node selector MUST be present right after the node selector separator, containing an expression that identifies the attribute whose value you want ๐ฆ The query component MUST be present if the node selector uses namespace prefixes, and the xmlns() expressions in the query component MUST define those prefixes ๐
The client then invokes the GET method ๐ท The 200 OK response contains an "application/xcap-att+xml" document with the specified attribute, formatted according to the AttValue grammar in the XML 1.0 specifications ๐ซถ
7.10. Fetch Namespace Bindings ๐
Okay, so if a client wants to insert an element or attribute into a document, and that element or attribute belongs to a namespace declared somewhere else in the document, the client needs the namespace bindings to build the XML content for the request ๐ If the client has a cached copy of the whole document, it already knows the bindings ๐ง But if it doesn't have the whole thing cached, it's super useful to fetch just the bindings that are in scope for an element, so it can build a follow-up PUT request ๐ง
To get those bindings, the client builds a URI whose document selector points at the doc containing the element whose bindings you want. The node selector MUST be present right after the node selector separator, containing an expression that identifies the namespace bindings you're after โจ The query component MUST be present if the node selector uses namespace prefixes, and the xmlns() expressions in the query component MUST define those prefixes ๐
The client then invokes the GET method ๐ธ The 200 OK response contains an "application/xcap-ns+xml" document with the namespace definitions, and the format for that document is defined in Section 10 ๐ฆ
Here's the important bit ๐จ A client can't set the namespace prefixes that are in scope for an element. So a node selector that identifies namespace prefixes MUST NOT appear in a PUT or DELETE request ๐ โโ๏ธ
7.11. Conditional Operations ๐ฏ
The HTTP specification defines several header fields that let a client make a request conditional ๐ซ The big ones are If-None-Match and If-Match, which let a client make the request depend on the current value of the entity tag for the resource ๐ฅ These conditional operations are especially handy for XCAP resources ๐
For example, clients will often want to cache the current version of a document ๐๏ธ So when the client starts up, it fetches the current document from the server and stores it.
When it does, the GET response contains the entity tag for the document resource ๐ท๏ธ Every resource inside a document the server maintains shares the same entity tag value ๐ซถ So the entity tag the server returns for the document resource also applies to the element and attribute resources inside it โจ
Say the client wants to insert or modify an element or attribute, but it needs to be sure the document hasn't changed since it last touched it ๐ง It can include an If-Match header field in the request, holding the entity tag value the client knows for all resources in the document. If the document has changed, the server rejects the request with a 412 response ๐ญ Then the client has to flush its cached copy, fetch the entire document, and store the new entity tag from the 200 OK to that GET request ๐ After that it can retry, putting the new entity tag in the If-Match header field ๐ If that works, the Etag header field in the PUT response holds the entity tag for the resource that was just inserted or modified ๐ Since every resource in a document shares the same entity tag value, that value can be used for modifying other resources too ๐
Clients can also conditionally delete elements or attributes by including an If-Match header field in DELETE requests ๐๏ธ Heads up: the 200 OK responses to a DELETE carry an Etag header field containing the entity tag for all the other resources in the document, even though the resource the DELETE targeted is gone now ๐ซ
When a client does conditional PUT and DELETE operations, it can apply those changes to its local cached copy and update the entity tag for that copy based on the Etag header field in the response ๐ง As long as no other clients are modifying the document, the client can keep doing conditional operations without ever doing separate GETs to sync the document and its entity tags ๐ฆ If another client changes the document, the conditional mechanisms catch it, and the client needs to do a GET to resync its copy, unless it has some other way of learning about the change ๐
If a client does an unconditional operation but had a cached copy, that cached copy becomes invalid once the operation runs (honestly, it might have gone stale even before that) ๐ Clients should only do unconditional operations when knowing the entire document doesn't matter for the operation to succeed ๐
As another example ๐ when a client fetches a document and there's an older version cached, it's useful to send a conditional GET to cut down on network usage if the cached copy is still valid ๐ธ To do that, the client includes an If-None-Match header field in the GET request, with a value equal to the current etag the client holds for the document. The server only generates a 200 OK response if the etag the server holds differs from the one the client holds ๐ซถ If it doesn't differ, the server responds with a 304 response ๐
8. Server Behavior โจ
okay so an XCAP server is an HTTP/1.1 compliant origin server ๐ the behaviors this spec mandates are all about how the HTTP URI gets interpreted and how the content gets built ๐
An XCAP server MUST be explicitly aware of the application usage that requests are being made against ๐ bestie, that means the server has to be explicitly configured to handle URIs for each specific application usage, and it has to know the constraints that application usage imposes ๐ซถ
When the server gets a request, what happens depends on the URI ๐ฆ If the URI refers to an application usage the server doesn't understand, the server MUST reject the request with a 404 (Not Found) response. If the URI refers to a user (identified by an XUI) the server doesn't recognize, it MUST reject the request with a 404 (Not Found). If the URI includes extension-selectors the server doesn't understand, it MUST reject the request with a 404 (Not Found) ๐
Next up, the server authenticates the request ๐ All XCAP servers MUST implement HTTP Digest [11]. Servers MUST also implement HTTP over TLS, RFC 2818 [14]. It is RECOMMENDED that administrators use an HTTPS URI as the XCAP root URI, so that the digest client authentication happens over TLS ๐ธ
Then the server works out whether the client is allowed to do the requested operation on the resource ๐ง The application usage defines the authorization policies. An application usage may say that the default is used, and that default is described in Section 5.7.
Next, the server makes sure it can properly evaluate the request URI โจ The server MUST separate the document selector from the node selector by splitting the URI at the first instance of the node selector separator (~~). The server MUST check the node selector in the request URI, if one is present. If any qualified names use a namespace prefix, and that prefix isn't defined in an xmlns() expression in the query component of the request URI, the server MUST reject the request with a 400 response ๐
After checking the namespace prefix definitions, the specific behavior depends on the method and on what the URI refers to ๐
8.1. POST Handling
XCAP resources do not represent processing scripts, so POST operations to HTTP URIs representing XCAP resources are not defined ๐
โโ๏ธ A server that gets such a request for an XCAP resource SHOULD return a 405.
8.2. PUT Handling
okay this is the big one ๐ซถ The behavior of a server that receives a PUT request is as specified in HTTP/1.1, Section 9.6. In plain terms, the content of the request gets placed at the specified location ๐ฆ This section defines what "placement" and "specified location" mean in the context of XCAP resources ๐
If the request URI contained a namespace-selector, the server MUST reject the request with a 405 (Method Not Allowed) and MUST include an Allow header field that includes the GET method ๐ซ
8.2.1. Locating the Parent
First thing the server does is find the parent ๐บ๏ธ That's whether it's a directory or an element where the resource is going to be placed. To do that, the server removes the last path segment from the URI, and what's left refers to the parent. The parent can be a document, an element, or a prefix of a document selector (this is called a directory, even though this specification doesn't require documents to actually be stored in a filesystem ๐). This URI is called the parent URI. The path segment that got removed is called the target selector, and the node (element, document, or attribute) it describes is called the target node ๐ฏ
If the parent URI has no node selector separator, it's referring to the directory the document should be inserted into. In normal XCAP operations, that'll be either the user's home directory or the global directory, and those will always exist on the server ๐ However, if an application usage makes use of subdirectories (even though that's not recommended), the directory the document should go into might not exist. In that case, the server MUST return a 409 response, and SHOULD include a detailed conflict report containing the <no-parent> element. Detailed conflict reports are discussed in Section 11. If the directory does exist, the server checks whether there's a document with the same filename as the target node. If there is, the operation is the replacement operation, discussed in Section 8.2.4. If not, it's the creation operation, discussed in Section 8.2.3 โจ
If the parent URI has a node selector separator, the document selector gets extracted and that document gets retrieved ๐ If the document doesn't exist, the server MUST return a 409 response, and SHOULD include a detailed conflict report containing the <no-parent> element. If it does exist, the node selector gets extracted and decoded (remember, the node selector is percent-encoded ๐ซง). The node selector is applied to the document using the matching operations discussed in Section 6.3. If the result is a no-match or invalid, the server MUST return a 409 response, and SHOULD include a detailed conflict report containing the <no-parent> element ๐
If the node-selector is valid, the server looks at the target selector and evaluates it within the context of the parent node ๐ If the target node already exists within the parent, the operation is a replacement, as described in Section 8.2.4. If it doesn't exist, it's the creation operation, discussed in Section 8.2.3 ๐
Before the replacement or creation happens (based on all the logic above), the server validates the content of the request as described in Section 8.2.2 ๐
8.2.2. Verifying Document Content
okay content check time ๐ง
If the PUT request is for a document (the request URI had no node selector separator), the content of the request body has to be a well-formed XML document. If it isn't, the server MUST reject the request with a 409 response code. That response SHOULD include a detailed conflict report containing the <not-well-formed> element. If the document is well-formed but not UTF-8 encoded, the server MUST reject the request with a 409 response code. That response SHOULD include a detailed conflict report containing the <not-utf-8> element. If the MIME type in the Content-Type header field of the request isn't equal to the MIME type defined for the application usage, the server MUST reject the request with a 415 ๐
If the PUT request is for an element, the content of the request body has to be a well-balanced region of an XML document, also known as an XML fragment body in The XML Fragment Interchange [23] specification, and it can only include a single element ๐งฉ If it isn't, the server MUST reject the request with a 409 response code. That response SHOULD include a detailed conflict report containing the <not-xml-frag> element. If the fragment body is well-balanced but contains characters outside of the UTF-8 character set, the server MUST reject the request with a 409 response code. That response SHOULD include a detailed conflict report containing the <not-utf-8> element. If the MIME type in the Content-Type header field of the request isn't equal to "application/xcap-el+xml", the server MUST reject the request with a 415 ๐
If the PUT request is for an attribute, the content of the request body has to be a sequence of characters that complies with the grammar for AttValue as defined above ๐ If it doesn't, the server MUST reject the request with a 409 response code. That response SHOULD include a detailed conflict report containing the <not-xml-att-value> element. If the attribute value is valid but contains characters outside of the UTF-8 character set, the server MUST reject the request with a 409 response code. That response SHOULD include a detailed conflict report containing the <not-utf-8> element. If the MIME type in the Content-Type header field of the request isn't equal to "application/xcap-att+xml", the server MUST reject the request with a 415 ๐ธ
8.2.3. Creation ๐
okay so this section is for when the PUT is creating something brand new ๐ซถ (a document, an element, or an attribute). These steps only kick in for that situation, so pay attention โจ
If the PUT is for a document, the content of the request body gets placed into the directory, and its filename gets associated with the target node, which is a document ๐
If the PUT is for an element, the server inserts the content of the request body as a new child element of the parent element selected in Section 8.2.1. The insertion is done so that the request URI, when evaluated, would now point to the element that was inserted. There exist three possible ways in which new elements are positioned ๐
First, if there were no other sibling elements with the same expanded name, and the insertion is not positionally constrained, the new element is inserted so that it is the last element amongst all element siblings. Furthermore, if there were comment, text, or processing instruction nodes after the former last element, they MUST occur prior to the insertion of the new element. This case occurs when one of the following are true:
- The element name in the target selector is not wildcarded. There could be an attribute selector (in which case, it would have to match an attribute of the element being inserted), and the position in the target selector will either be absent or have a value of 1 (a value greater than 1 would always result in rejection of the request, since this is the first element with the given name underneath the parent).
- The element name in the target selector is wildcarded, but there are no other elements underneath the same parent. There could be an attribute selector (in which case, it would have to match an attribute of the element being inserted), and the position in the target selector will either be absent or have a value of 1 (a value greater than 1 would always result in rejection of the request, since this is the first element underneath the parent).
- The element name in the target selector is wildcarded, and there are other elements underneath the same parent. However, there is an attribute selector that matches none of the attributes in the other sibling elements underneath the parent, but does match an attribute of the element to be inserted. The position in the target selector is absent.
Secondly, if there were sibling elements with the same name already in the document, but the insertion is positionally unconstrained, the server MUST insert the element so that it is in the "earliest last" position. "Earliest last" means that the new element MUST be inserted so that there are no elements after it with the same expanded name, and for all insertion positions where this is true, it is inserted so that as many sibling nodes (element, comment, text, or processing instruction) appear after it as possible. This case occurs when the target selector is defined by a by-name or by-attr production, and there is no position indicated. ๐ธ
Lastly, if the element is positionally constrained, the server MUST insert the element so that it is in the "earliest nth" position. When n>1 and NameofAny is not a wildcard, the element MUST be inserted so that there are n-1 sibling elements before it with the same expanded name. If there are not n-1 sibling elements with the same expanded name, the request will fail. When n>1 and NameorAny is a wildcard, the element MUST be inserted so that there are n-1 sibling elements before it, each of which can have any expanded name. If there are not n-1 sibling elements in the document, the request will fail. In both of these cases, the new element is inserted so that as many sibling nodes appear after it as possible. When n=1 and NameorAny is not a wildcard, the insertion is positionally constrained when an element with the same expanded name already appears as a child of the same parent. In this case, the new element MUST appear just before the existing first element with this same expanded name. When n=1 and NameorAny is wildcarded, the insertion is positionally constrained when there is also an attribute selector that didn't match the first sibling of the parent (if it did match, or was absent, this wouldn't have been an insertion). In this case, the new element MUST appear just before all existing elements, regardless of their expanded name. ๐ง
In practice, this insertion logic keeps elements with the same expanded names closely together. This simplifies the application logic when the content model is described by XML schema with <sequence> rules and maxOccurs="unbounded" cardinalities, like:
<xs:element name="foobar">
<xs:complexType>
<xs:sequence>
<xs:element ref="foo" maxOccurs="unbounded" />
<xs:element ref="bar" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
Based on this schema, the document contains some number of <foo> elements followed by some number of <bar> elements. Either <bar> or <foo> elements may easily be added without wildcards and positional constraints. Note that if "minOccurs" cardinality of <foo> element were zero and <foo> elements do not yet exist, a positional predicate with the * wildcard must be used. ๐
The whole insert logic is best described by complete examples. Consider the following document:
<?xml version="1.0"?>
<root>
<el1 att="first"/>
<el1 att="second"/>
<!-- comment -->
<el2 att="first"/>
</root>
A PUT request whose content is <el1 att="third"/> and whose node selector is root/el1[@att="third"] would result in the following document:
<?xml version="1.0"?>
<root>
<el1 att="first"/>
<el1 att="second"/><el1 att="third"/>
<!-- comment -->
<el2 att="first"/>
</root>
Notice how it has been inserted as the third <el1> element in the document, and just before the comment and whitespace nodes. It would have been inserted in exactly the same place if the node selector had been root/el1[3][@att="third"] or root/*[3][@att="third"]. ๐ฆ
If the content of the request had been <el3 att="first"/> and the node selector was root/el3, it would result in the following document:
<?xml version="1.0"?>
<root>
<el1 att="first"/>
<el1 att="second"/>
<!-- comment -->
<el2 att="first"/>
<el3 att="first"/></root>
A PUT request whose content is <el2 att="2"/> and whose node selector is root/el2[@att="2"] would result in the following document:
<?xml version="1.0"?>
<root>
<el1 att="first"/>
<el1 att="second"/>
<!-- comment -->
<el2 att="first"/><el2 att="2"/>
</root>
It would have been inserted in exactly the same place if the node selector had been root/el2[2][@att="2"]. However, a selector root/*[2][@att="2"] would result in the following document:
<?xml version="1.0"?>
<root>
<el1 att="first"/><el2 att="2"/>
<el1 att="second"/>
<!-- comment -->
<el2 att="first"/>
</root>
Lastly, if the node selector had been root/el2[1][@att="2"] the result would be:
<?xml version="1.0"?>
<root>
<el1 att="first"/>
<el1 att="second"/>
<!-- comment -->
<el2 att="2"/><el2 att="first"/>
</root>
It is possible that the element cannot be inserted so that the request URI, when evaluated, returns the content provided in the request. Such a request is not allowed for PUT. This happens when the element in the body is not described by the expression in the target selector. An example of this case is described in Section 7.4. If this happens, the server MUST NOT perform the insertion, and MUST reject the request with a 409 response. The body of the response SHOULD contain a detailed conflict report containing the <cannot-insert> element. โ ๏ธ
It is important to note that schema compliance does not play a role while performing the insertion. That is, the decision of where the element gets inserted is dictated entirely by the structure of the request-URI, the current document, and the rules in this specification. ๐
If the element being inserted (or any of its children) contain namespace declarations, those declarations are retained when the element is inserted, even if those same declarations exist in a parent element after insertion. The XCAP server MUST NOT remove redundant namespace declarations or otherwise change the namespace declarations that were present in the element being inserted. ๐
If the PUT request is for an attribute, the server inserts the content of the request body as the value of the attribute. The name of the attribute is equal to the att-name from the attribute-selector in the target selector. ๐
Assuming that the insertion can be accomplished, the server verifies that the insertion results in a document that meets the constraints of the application usage. This is discussed in Section 8.2.5. ๐ซถ
8.2.4. Replacement ๐ฆ
okay now the replacement side ๐ these steps happen when the PUT is going to replace an existing document, element, or attribute with the contents of the request.
If the PUT is for a document, the content of the request body gets placed into the directory, replacing the document with the same filename.
If the PUT is for an element, the server replaces the target node with the content of the request body. Just like in the creation case, it's possible that after replacement, the request URI doesn't select the element that was just inserted. If this happens, the server MUST NOT perform the replacement, and MUST reject the request with a 409 response. The body of the response SHOULD contain a detailed conflict report containing the <cannot-insert> element. ๐
As with creation, replacement of an element does not result in the changing or elimination of namespace declarations within the newly modified element. ๐
If the PUT is for an attribute, the server sets the value of the selected attribute to the content of the request body. It's possible in the replacement case (but not in the creation case) that, after replacement of the attribute, the request URI no longer selects the attribute that was just replaced. The scenario in which this can happen is discussed in Section 7.7. If this is the case, the server MUST NOT perform the replacement, and MUST reject the request with a 409 response. The body of the response SHOULD contain a detailed conflict report containing the <cannot-insert> element. ๐
8.2.5. Validation โจ
okay so once the document, element, or attribute has been tentatively inserted, the server needs to double-check that the result still meets the data constraints the application usage lays out ๐
First up, the schema check ๐ The server checks that the final document is compliant with the schema. If it isn't, the server MUST NOT perform the insertion. It MUST reject the request with a 409 response. That response SHOULD contain a detailed conflict report containing the <schema-validation-error> element ๐ญ If a schema allows for elements or attributes from other namespaces, and the new document contains elements or attributes from an unknown namespace, the server MUST allow the change. In other words, an XCAP server doesn't have to understand every namespace and its schemas inside a document, as long as the schema itself allows those elements or attributes to be included ๐ฆ Of course, those unknown namespaces wouldn't be advertised by the server in its XCAP capabilities document, which we get to in Section 12.
If the final document has elements or attributes from a namespace the server does understand (and has therefore advertised in its XCAP capabilities document), but the server doesn't have the schema for that particular element or attribute, the server MUST reject the request with a 409 response. That response SHOULD contain a detailed conflict report containing the <schema-validation-error> element ๐
Next, uniqueness constraints ๐ The server checks for any uniqueness constraints identified by the application usage. If the application usage required that a particular element or attribute had a unique value within a specific scope, the server checks that this uniqueness property still exists. If the application usage required that a URI within the document was unique within the domain, the server checks whether that's the case. If any of these uniqueness constraints aren't met, the server MUST NOT perform the insertion. It MUST reject the request with a 409 response. That response SHOULD contain a detailed conflict report containing the <uniqueness-failure> element. That element can contain suggested values the client can use to retry. These SHOULD be values that, at the time the server generates the 409, would meet the uniqueness constraints ๐ซถ
Then there are the URI constraints and other non-schema data constraints ๐ The server also checks for these. If the document fails one of them, the server MUST NOT perform the insertion. It MUST reject the request with a 409 response. That response SHOULD contain a detailed conflict report containing the <constraint-failure> element. That element indicates that the document failed non-schema data constraints explicitly called out by the application usage โจ
Removals follow the same vibe ๐ง Element or attribute removals have similar constraints. The server checks the document for schema validity and compliance with the constraints defined by the application usage, and rejects the request as described above if either check fails.
8.2.6. Conditional Processing ๐
A PUT request for an XCAP resource, like any other HTTP resource, can be made conditional by using the If-Match and If-None-Match header fields ๐ธ For a replacement, these are processed as defined in [6]. For an insertion of an element or attribute, conditional operations are permitted. The entity tag used for the procedures in [6] is the one for all of the resources within the same document as the parent of the element or attribute being inserted. One way to think about it: logically speaking, when the PUT request is received, the XCAP server instantiates the etag for the resource referenced by the request, and then applies the processing of the request ๐ฅ Because of this behavior, it is not possible to perform a conditional insert on an attribute or element that is conditioned on the operation being an insertion and not a replacement. In other words, a conditional PUT of an element or attribute with an If-None-Match: * will always fail ๐
8.2.7. Resource Interdependencies ๐ธ๏ธ
Because XCAP resources include elements, attributes, and documents, and each of them has its own HTTP URI, creating or modifying one resource affects the state of many others ๐ For example, inserting a document creates resources on the server for all of the elements and attributes within that document. After the server has performed the insertion associated with the PUT, the server MUST create and/or modify those resources affected by that PUT. The structure of the document completely defines the inter-relationship between those resources ๐
The application usage can also specify other resource interdependencies. The server MUST create or modify the resources specified by the application usage.
If the creation or replacement was successful, and the resource interdependencies are resolved, the server returns a 201 Created or 200 OK, respectively. Note that a 201 Created is generated for creation of new documents, elements, or attributes. A 200 OK response to PUT MUST not contain any content. Per the recommendations of RFC 2616, the 201 can contain a Location header field and entity that identify the resource that was created. An entity tag MUST be included in all successful responses to a PUT ๐ง
8.3. GET Handling ๐ท
The semantics of GET are as specified in RFC 2616. This section clarifies the specific content to be returned for a particular URI that represents an XCAP resource ๐ฆ
If the request URI contains only a document selector, the server returns the document specified by the URI if it exists, else it returns a 404 response. The MIME type of the body of the 200 OK response MUST be the MIME type defined by that application usage (i.e., "application/resource-lists+xml") ๐
If the request URI contains a node selector, the server obtains the document specified by the document selector and, if it's found, evaluates the node-selector within that document. If no document is found, or if the node-selector is a no-match or invalid, the server returns a 404 response. Otherwise, the server returns a 200 OK response. If the node selector identifies an XML element, that element is returned in the 200 OK response as an XML fragment body containing the selected element. The server MUST NOT add namespace bindings representing namespaces used by the element or its children but declared in ancestor elements. The client will either know these bindings already (since it has a cached copy of the whole document), or it can learn them by explicitly querying for the bindings ๐ง The MIME type of the response MUST be "application/xcap-el+xml". If the node selector identifies an XML attribute, the value of that attribute is returned in the body of the response. The MIME type of the response MUST be "application/xcap-att+xml". If the node selector identifies a set of namespace bindings, the server computes the set of namespace bindings in scope for the element (including the default) and encodes it using the "application/xcap-ns+xml" format defined in Section 10. That document is then returned in the body of the response ๐ญ
GET operations can be conditional, and follow the procedures defined in [6] โญ
Note that a GET of a resource that was just PUT might not be octet-for-octet equivalent to what was PUT, due to XML normalization and equivalency rules ๐
A successful response to a GET MUST include an entity tag ๐ซถ
8.4. DELETE Handling ๐๏ธ
The semantics of DELETE are as specified in RFC 2616. This section clarifies the specific content to be deleted for a particular URI that represents an XCAP resource ๐
If the request URI contained a namespace-selector, the server MUST reject the request with a 405 (Method Not Allowed) and MUST include an Allow header field including the GET method ๐
โโ๏ธ
If the request URI contains only a document selector, the server deletes the document specified by the URI if it exists and returns a 200 OK. Otherwise, it returns a 404 response ๐
If the request URI contains a node selector, the server obtains the document specified by the document selector and, if it's found, evaluates the node-selector within that document. If no document is found, or if the node-selector is a no-match or invalid (note that it will be invalid if multiple elements or attributes are selected), the server returns a 404 response. Otherwise, the server removes the specified element or attribute from the document and performs the validation checks defined in Section 8.2.5. Note that this deletion does not include any white space around the element that was deleted. The XCAP server MUST preserve surrounding whitespace ๐ค It's possible that, after deletion, the request URI selects another element in the document. If this happens, the server MUST NOT perform the deletion, and MUST reject the request with a 409 response. The body of the response SHOULD contain a detailed conflict report containing the <cannot-delete> element. If the deletion will cause a failure of one of the constraints, the deletion MUST NOT take place. The server follows the procedures in Section 8.2.5 for computing the 409 response. If the deletion results in a document that is still valid, the server MUST perform the deletion, process the resource interdependencies defined by the application usage, and return a 200 OK response ๐ซ
DELETE operations can be conditional, and follow the procedures defined in [6] ๐
Before the server returns the 200 OK response to a DELETE, it MUST process the resource interdependencies as defined in Section 8.2.7. As long as the document still exists after the delete operation, any successful response to DELETE MUST include the entity tag of the document ๐ท๏ธ
8.5. Managing Etags ๐ท๏ธ
An XCAP server MUST maintain entity tags for all resources that it maintains. This specification adds the extra rule that when one resource within a document (including the document itself) changes, that resource is assigned a new etag, and all other resources within that document MUST be assigned the same etag value. Effectively, there is a single etag for the entire document ๐งฉ An XCAP server MUST include the Etag header field in all 200 or 201 responses to PUT, GET, and DELETE, assuming the document itself still exists after the operation. In the case of a DELETE, the entity tag refers to the value of the entity tag for the document after the deletion of the element or attribute.
XCAP resources don't introduce new requirements on the strength of the entity tags ๐ช
Because of this constraint, when a client changes an element or attribute within a document, the response to that operation conveys the entity tag of the resource that was just affected. Since the client knows this entity tag value is shared by all of the other resources in the document, the client can make conditional requests against other resources using that entity tag ๐ฅฐ
9. Cache Control ๐พ
An XCAP resource is a valid HTTP resource, and therefore it can be cached by clients and network caches. Network caches, however, won't be aware of the interdependencies between XCAP resources. So a change to an element in a document by a client will invalidate other XCAP resources affected by the change ๐ For application usages containing data that is likely to be dynamic or written by clients, servers SHOULD indicate a no-cache directive ๐ง
10. Namespace Binding Format โจ
okay so a node-selector can point at a whole set of namespace bindings that are in scope for one particular element ๐ the catch is that if the server is gonna send those bindings back in a GET response, we need a way to encode them ๐ง
ngl, the encoding is trivially easy ๐
you just put a single XML element inside an XML fragment body. that element has the same local-name as the element whose bindings you want, and the same namespace-prefix too. it gets an xmlns attribute for the default namespace in scope, plus an xmlns:prefix declaration for every prefix that's in scope ๐ฆ
So, the example! Take the XML document from Section 6.4. The node-selector df:foo/df2:bar/df2:baz/namespace::* selects the namespaces in scope for the <baz> element, assuming the request comes with a query component that contains xmlns(df=urn:test:default-namespace) and xmlns(df2=urn:test:namespace1-uri). A GET with that node-selector and those bindings produces this result:
<baz xmlns="urn:test:namespace1-uri"
xmlns:ns1="urn:tes:namespace1-uri"/>
the client does not need to know the actual namespace bindings to build the URI ๐ซถ it only needs the namespace URI for each element in the node-selector. the bindings in the query component are defined by the client, mapping those URIs to a set of prefixes. the bindings the server sends back are the actual bindings used in the document. iconic separation of concerns, no cap ๐
11. Detailed Conflict Reports ๐ฅ
okay this part is so important bestie ๐ญ when the server returns a 409 error response, that response will usually include a document in the body that gives you more details on what went wrong. it's an XML document, formatted according to the schema in Section 11.2, and its MIME type (registered by this spec) is application/xcap-error+xml ๐
11.1. Document Structure ๐งฉ
the structure is simple, no drama ๐ธ it has the root element <xcap-error>, and its content is one specific error condition. each error condition gets its own element, so different errors can carry different data about what actually happened. every error element supports a phrase attribute, which can hold text meant to be rendered for a human user ๐
these are the error elements this spec defines:
<not-well-formed>: the body of the request was not a well-formed XML document. ๐<not-xml-frag>: the request was supposed to contain a valid XML fragment body, but didn't. most likely the XML in the body was malformed or not balanced ๐<no-parent>: an attempt to insert a document, element, or attribute failed because the directory, document, or element it was supposed to go into doesn't exist. this one can contain an optional<ancestor>element, which gives an HTTP URI for the closest parent that would be a valid point of insertion. this HTTP URI MAY be a relative URI, relative to the document itself. since it's a valid HTTP URI, its node selector component MUST be percent-encoded โจ<schema-validation-error>: the document wasn't compliant with the schema after the requested operation was performed ๐<not-xml-att-value>: the request was supposed to contain a valid XML attribute value, but didn't ๐<cannot-insert>: the requested PUT couldn't be performed because a GET of that resource after the PUT wouldn't yield the content of the PUT request ๐ซ<cannot-delete>: the requested DELETE couldn't be performed because it would not be idempotent ๐ โโ๏ธ<uniqueness-failure>: the requested operation would result in a document that broke a uniqueness constraint defined by the application usage. for each URI, element, or attribute the client specified that isn't unique, there's an<exists>element as the content of the error element. each<exists>element has afieldattribute containing a relative URI that identifies the XML element or attribute whose value needed to be unique but wasn't. that relative URI is relative to the document itself, so it starts with the root element. the query component of the URI MUST be present if the node selector portion of the URI contains namespace prefixes. since thefieldnode selector is a valid HTTP URI, it MUST be percent-encoded. the<exists>element can optionally contain a list of<alt-value>elements, each one a suggested alternate value that doesn't currently exist on the server ๐<constraint-failure>: the requested operation would result in a document that failed a data constraint defined by the application usage, but that isn't enforced by the schema or a uniqueness constraint ๐<extension>: an error condition defined by an extension to XCAP. clients that don't understand the content of the extension element MUST discard the xcap-error document and treat the error as an unqualified 409 ๐ง<not-utf-8>: the request couldn't be completed because it would have produced a document that isn't encoded in UTF-8 ๐ธ
main character example time ๐ฌ the following document says the user tried to create an RLS service using the URI sip:friends@example.com, but that URI already exists ๐
<?xml version="1.0" encoding="UTF-8"?>
<xcap-error xmlns="urn:ietf:params:xml:ns:xcap-error">
<uniqueness-failure>
<exists field="rls-services/service/@uri">
<alt-value>sip:mybuddies@example.com</alt-value>
</exists>
</uniqueness-failure>
</xcap-error>
11.2. XML Schema
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="urn:ietf:params:xml:ns:xcap-error"
xmlns="urn:ietf:params:xml:ns:xcap-error"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="error-element" abstract="true"/>
<xs:element name="xcap-error">
<xs:annotation>
<xs:documentation>Indicates the reason for the error.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element ref="error-element"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="extension" substitutionGroup="error-element">
<xs:complexType>
<xs:sequence>
<xs:any namespace="##any" processContents="lax"
minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="schema-validation-error"
substitutionGroup="error-element">
<xs:annotation>
<xs:documentation>This element indicates
that the document was not compliant to the schema after the requested
operation was performed.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="phrase" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="not-xml-frag" substitutionGroup="error-element">
<xs:annotation>
<xs:documentation>This indicates that the request was supposed to
contain a valid XML fragment body, but did not.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="phrase" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="no-parent" substitutionGroup="error-element">
<xs:annotation>
<xs:documentation>This indicates that an attempt to insert
an element, attribute, or document failed because the document or
element into which the insertion was
supposed to occur does not exist.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="ancestor" type="xs:anyURI" minOccurs="0">
<xs:annotation>
<xs:documentation>Contains an HTTP URI that points to the
element that is the closest ancestor that does exist.
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:attribute name="phrase" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cannot-insert" substitutionGroup="error-element">
<xs:annotation>
<xs:documentation>This indicates that the requested
PUT operation could not be performed because a GET of that resource
after the PUT would not yield the content of the PUT request.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="phrase" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="not-xml-att-value"
substitutionGroup="error-element">
<xs:annotation>
<xs:documentation>This indicates that the
request was supposed to contain a valid XML attribute value, but did
not.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="phrase" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="uniqueness-failure"
substitutionGroup="error-element">
<xs:annotation>
<xs:documentation>This indicates that the
requested operation would result in a document that did not meet a
uniqueness constraint defined by the application usage.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="exists" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>For each URI,
element, or attribute specified by the client that is not unique,
one of these is present.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence minOccurs="0">
<xs:element name="alt-value" type="xs:string"
maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>An optional set of alternate values can be
provided.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:attribute name="field" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="phrase" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="not-well-formed"
substitutionGroup="error-element">
<xs:annotation>
<xs:documentation>This indicates that the body of the request was
not a well-formed document.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="phrase" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="constraint-failure"
substitutionGroup="error-element">
<xs:annotation>
<xs:documentation>This indicates that the
requested operation would result in a document that failed a data
constraint defined by the application usage, but not enforced by the
schema or a uniqueness constraint.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="phrase" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cannot-delete" substitutionGroup="error-element">
<xs:annotation>
<xs:documentation>This indicates that the requested DELETE
operation could not be performed because it would not be
idempotent.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="phrase" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="not-utf-8" substitutionGroup="error-element">
<xs:annotation>
<xs:documentation>This indicates that the request could not be
completed because it would have produced a document not
encoded in UTF-8.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="phrase" type="xs:string" use="optional"/>
</xs:complexType>
</xs:element>
</xs:schema>
12. XCAP Server Capabilities โจ
XCAP can be extended by adding new application usages and extensions to the core protocol. ๐งฉ Application usages may define MIME types with XML schemas that allow new extension nodes from new namespaces. It's going to be super common for a client to need to figure out what extensions, application usages, or namespaces a server supports before it makes a request. ๐ค To make that possible, this specification defines an application usage with the AUID "xcap-caps". All XCAP servers MUST support this application usage. This usage defines a single document within the global tree that lists the server's capabilities. Clients can read this well-known document and therefore learn what the server can do. ๐
The structure of the document is simple, bestie. ๐ The root element is <xcap-caps>. Its children are <auids>, <extensions>, and <namespaces>. Each of these contains a list of AUIDs, extensions, and namespaces that the server supports. Extensions are named by tokens defined by the extension, and they typically define new selectors. Namespaces are identified by their namespace URI. To "support" a namespace, the server must have the schemas for all elements within that namespace and be able to validate them if they show up inside documents. ๐ฆ Since all XCAP servers support the "xcap-caps" AUID, it MUST be listed in the <auids> element, and the urn:ietf:params:xml:ns:xcap-caps namespace MUST be listed in the <namespaces> element. ๐
The following sections give you the info you need to define this application usage. ๐ธ
12.1. Application Unique ID (AUID) ๐
This specification defines the "xcap-caps" AUID within the IETF tree, via the IANA registration in Section 15. โจ
12.2. XML Schema ๐
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="urn:ietf:params:xml:ns:xcap-caps"
xmlns="urn:ietf:params:xml:ns:xcap-caps"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="xcap-caps">
<xs:annotation>
<xs:documentation>Root element for xcap-caps</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="auids">
<xs:annotation>
<xs:documentation>List of supported AUID.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="auid" type="auidType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="extensions" minOccurs="0">
<xs:annotation>
<xs:documentation>List of supported extensions.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="extension" type="extensionType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="namespaces">
<xs:annotation>
<xs:documentation>List of supported namespaces.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="namespace" type="namespaceType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:any namespace="##other" processContents="lax"
minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="auidType">
<xs:annotation>
<xs:documentation>AUID Type</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="extensionType">
<xs:annotation>
<xs:documentation>Extension Type</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="namespaceType">
<xs:annotation>
<xs:documentation>Namespace type</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
</xs:schema>
12.3. Default Document Namespace ๐ง
The default document namespace used when evaluating a URI is urn:ietf:params:xml:ns:xcap-caps. ๐
12.4. MIME Type ๐
Documents that conform to this schema are known by the MIME type application/xcap-caps+xml, which is registered in Section 15.2.5. ๐
12.5. Validation Constraints ๐ซถ
There are no additional validation constraints associated with this application usage. โ
12.6. Data Semantics ๐ฅ
Data semantics are defined above. ๐
12.7. Naming Conventions ๐
A server MUST maintain a single instance of the document in the global tree, using the filename "index". There MUST NOT be an instance of this document in the user's tree. ๐ซ
12.8. Resource Interdependencies ๐ธ๏ธ
There are no resource interdependencies in this application usage beyond those defined by the schema. ๐ซ
12.9. Authorization Policies ๐
This application usage does not change the default authorization policy defined by XCAP. ๐โโ๏ธ
13. Examples ๐
Okay bestie, this section walks through a few examples using the resource-lists and rls-services [22] XCAP application usages. ๐
First up, Bill makes a brand-new document (see Section 7.1). It's a fresh resource-list with one list called friends and zero users in it yet ๐ง
PUT
/resource-lists/users/sip:bill@example.com/index HTTP/1.1
Content-Type:application/resource-lists+xml
Host: xcap.example.com
<?xml version="1.0" encoding="UTF-8"?>
<resource-lists xmlns="urn:ietf:params:xml:ns:resource-lists">
<list name="friends">
</list>
</resource-lists>
Figure 24: New Document
Next, Bill makes an RLS services document with one RLS service pointing at that list. The service URI is sip:myfriends@example.com (URIs are line-folded for readability, so don't freak out ๐)
PUT
/rls-services/users/sip:bill@example.com/index HTTP/1.1
Content-Type:application/rls-services+xml
Host: xcap.example.com
<?xml version="1.0" encoding="UTF-8"?>
<rls-services xmlns="urn:ietf:params:xml:ns:rls-services">
<service uri="sip:myfriends@example.com">
<resource-list>http://xcap.example.com/resource-lists/users/
sip:bill@example.com/index/~~/resource-lists/
list%5b@name=%22friends%22%5d
</resource-list>
<packages>
<package>presence</package>
</packages>
</service>
</rls-services>
Figure 25: RLS Services Example
Next, Bill creates an element in the resource-lists document (Section 7.4). Specifically, he adds an entry to the list ๐
PUT
/resource-lists/users/sip:bill@example.com/index
/~~/resource-lists/list%5b@name=%22friends%22%5d/entry HTTP/1.1
Content-Type:application/xcap-el+xml
Host: xcap.example.com
<entry uri="sip:bob@example.com">
<display-name>Bob Jones</display-name>
</entry>
Figure 26: Resource Lists Document
Next, Bill fetches the document (Section 7.3) ๐
GET
/resource-lists/users/sip:bill@example.com/index HTTP/1.1
Figure 27: Fetch Operation
And the result is (note how the white space text nodes show up in the document ๐ค)
HTTP/1.1 200 OK
Etag: "wwhha"
Content-Type: application/resource-lists+xml
<?xml version="1.0" encoding="UTF-8"?>
<resource-lists xmlns="urn:ietf:params:xml:ns:resource-lists">
<list name="friends">
<entry uri="sip:bob@example.com">
<display-name>Bob Jones</display-name>
</entry></list>
</resource-lists>
Figure 28: Results of Fetch
Next, Bill adds another entry to the list. This one is an entire list with three entries inside it. It's still an element creation (Section 7.4) ๐ซถ
PUT
/resource-lists/users/sip:bill@example.com/index/~~/
resource-lists/list%5b@name=%22friends%22%5d/
list%5b@name=%22close-friends%22%5d HTTP/1.1
Content-Type: application/xcap-el+xml
Host: xcap.example.com
<list name="close-friends">
<entry uri="sip:joe@example.com">
<display-name>Joe Smith</display-name>
</entry>
<entry uri="sip:nancy@example.com">
<display-name>Nancy Gross</display-name>
</entry>
<entry uri="sip:petri@example.com">
<display-name>Petri Aukia</display-name>
</entry>
</list>
Figure 29: Adding an Entry
Then Bill changes his mind. He doesn't want Petri on the list anymore, so he deletes that entry (Section 7.5) ๐
DELETE
/resource-lists/users/sip:bill@example.com/index/
~~/resource-lists/list/list/
entry%5b@uri=%22sip:petri@example.com%22%5d HTTP/1.1
Host: xcap.example.com
Figure 30: Deleting an Entry
Bill wants to check Nancy's URI, so he fetches one specific attribute (Section 7.6) ๐ฆ
GET
/resource-lists/users/sip:bill@example.com/index/
~~/resource-lists/list/list/entry%5b2%5d/@uri HTTP/1.1
Host: xcap.example.com
Figure 31: Fetching an Attribute
and the server replies:
HTTP/1.1 200 OK
Etag: "ad88"
Content-Type:application/xcap-att+xml
"sip:nancy@example.com"
Figure 32: Results of Fetch
14. Security Considerations ๐
Okay, this part is serious, so listen up ๐ฅบ XCAP data is often sensitive. To stop eavesdroppers from peeking at it, it is RECOMMENDED that an administrator hand out an HTTPS URI as the XCAP root URI. That gives you TLS-encrypted traffic between client and server, so nobody snoops. Clients MUST implement TLS, so these URIs actually work for the client ๐
Authentication matters too. A client needs to be sure it's really talking to the server it thinks it is. Otherwise it could get false information, and that can lead to denial-of-service attacks against the client ๐ญ To prevent this, a client SHOULD attempt to upgrade [15] any connections to TLS. Authorizing reads and writes is also important, and that requires client authentication. So a server SHOULD challenge a client using HTTP Digest [11] to establish its identity, and this SHOULD be done over a TLS connection. Clients MUST implement digest authentication so they can work with servers that challenge them. Servers MUST NOT perform basic authentication without a TLS connection to the client ๐ซ
Here's the tea ๐ต XCAP is a usage of HTTP and not its own protocol, so it runs on the same port numbers as regular HTTP traffic. That makes it hard to write port-based firewall rules that treat XCAP traffic differently from other HTTP traffic.
Warning: this problem already exists in general, because HTTP is used to reach a huge range of content, all on the same port. XCAP just sees its application configuration documents as another type of HTTP content. So separating XCAP traffic from other HTTP traffic means firewalls have to examine the URL itself. There is no foolproof way to identify a URL as pointing to an XCAP resource. The presence of the double tilde (~~) is a strong hint that the URL points to an XML element or attribute. Always be careful when looking for the double tilde, since a URI can be encoded on the wire in so many ways [29] [13] ๐
15. IANA Considerations ๐
There are several IANA considerations tied to this specification โจ
15.1. XCAP Application Unique IDs
IANA made a brand-new registry for XCAP application unique IDs (AUIDs), as this specification instructed. The registry is a table with three columns:
- AUID: a string supplied in the IANA registrations.
- Description: text supplied by the IANA registration.
- Reference: a reference to the RFC containing the registration.
IANA set up the table with one initial entry. The resulting table looks like this:
Application Unique
ID (AUID) Description Reference
-------------------- ------------------------------- ---------
xcap-caps Capabilities of an XCAP server RFC 4825
XCAP AUIDs get registered with IANA when they're published in standards track RFCs. The IANA Considerations section of the RFC must include the following information, which then shows up in the IANA registry next to the RFC number of the publication ๐ฆ
- Name of the AUID. The name MAY be of any length, but SHOULD be no more than 20 characters long. The name MUST consist of alphanum and mark [16] characters only.
- Descriptive text that describes the application usage.
15.2. MIME Types
This specification asks for several new MIME types to be registered, following the procedures of RFC 4288 [8] and the guidelines in RFC 3023 [9] ๐
15.2.1. application/xcap-el+xml MIME Type
- MIME media type name: application
- MIME subtype name: xcap-el+xml
- Mandatory parameters: none
- Optional parameters: Same as charset parameter application/xml as specified in RFC 3023 [9].
- Encoding considerations: Same as encoding considerations of application/xml as specified in RFC 3023 [9].
- Security considerations: See Section 10 of RFC 3023 [9].
- Interoperability considerations: none
- Published specification: RFC 4825
- Applications that use this media type: This document type has been used to support transport of XML fragment bodies in RFC 4825, the XML Configuration Access Protocol (XCAP).
- Additional Information:
- Magic Number: none
- File Extension:
.xel - Macintosh file type code:
"TEXT"
- Personal and email address for further information: Jonathan Rosenberg, jdrosen@jdrosen.net
- Intended usage: COMMON
- Author/Change controller: The IETF.
15.2.2. application/xcap-att+xml MIME Type
- MIME media type name: application
- MIME subtype name: xcap-att+xml
- Mandatory parameters: none
- Optional parameters: Same as charset parameter application/xml as specified in RFC 3023 [9].
- Encoding considerations: Same as encoding considerations of application/xml as specified in RFC 3023 [9].
- Security considerations: See Section 10 of RFC 3023 [9].
- Interoperability considerations: none
- Published specification: RFC 4825
- Applications that use this media type: This document type has been used to support transport of XML attribute values in RFC 4825, the XML Configuration Access Protocol (XCAP).
- Additional Information:
- Magic Number: none
- File Extension:
.xav - Macintosh file type code:
"TEXT"
- Personal and email address for further information: Jonathan Rosenberg, jdrosen@jdrosen.net
- Intended usage: COMMON
- Author/Change controller: The IETF.
15.2.3. application/xcap-ns+xml MIME Type
- MIME media type name: application
- MIME subtype name: xcap-ns+xml
- Mandatory parameters: none
- Optional parameters: Same as charset parameter application/xml as specified in RFC 3023 [9].
- Encoding considerations: Same as encoding considerations of application/xml as specified in RFC 3023 [9].
- Security considerations: See Section 10 of RFC 3023 [9].
- Interoperability considerations: none
- Published specification: RFC 4825
- Applications that use this media type: This document type has been used to support transport of XML fragment bodies in RFC 4825, the XML Configuration Access Protocol (XCAP).
- Additional Information:
- Magic Number: none
- File Extension:
.xns - Macintosh file type code:
"TEXT"
- Personal and email address for further information: Jonathan Rosenberg, jdrosen@jdrosen.net
- Intended usage: COMMON
- Author/Change controller: The IETF.
15.2.4. application/xcap-error+xml MIME Type โจ
okay so this is the MIME type for XCAP error documents ๐ it's how a server tells you what went wrong, and it's giving very organized energy ๐
MIME media type name: application
MIME subtype name: xcap-error+xml
Mandatory parameters: none
Optional parameters: Same as charset parameter application/xml as
specified in RFC 3023 [9].
Encoding considerations: Same as encoding considerations of
application/xml as specified in RFC 3023 [9].
Security considerations: See Section 10 of RFC 3023 [9].
Interoperability considerations: none
Published specification: RFC 4825
Applications that use this media type: This document type conveys
error conditions defined in RFC 4825
Additional Information:
Magic Number: none
File Extension: .xer
Macintosh file type code: "TEXT"
Personal and email address for further information:
Jonathan Rosenberg, jdrosen@jdrosen.net
Intended usage: COMMON
Author/Change controller: The IETF.
15.2.5. application/xcap-caps+xml MIME Type ๐ฆ
and here's the sibling one for capabilities ๐ซถ same vibe, different job
MIME media type name: application
MIME subtype name: xcap-caps+xml
Mandatory parameters: none
Optional parameters: Same as charset parameter application/xml as
specified in RFC 3023 [9].
Encoding considerations: Same as encoding considerations of
application/xml as specified in RFC 3023 [9].
Security considerations: See Section 10 of RFC 3023 [9].
Interoperability considerations: none
Published specification: RFC 4825
Applications that use this media type: This document type conveys
capabilities of an XML Configuration Access Protocol (XCAP)
server, as defined in RFC 4825.
Additional Information:
Magic Number: none
File Extension: .xca
Macintosh file type code: "TEXT"
Personal and email address for further information:
Jonathan Rosenberg, jdrosen@jdrosen.net
Intended usage: COMMON
Author/Change controller: The IETF.
15.3. URN Sub-Namespace Registrations ๐
this part registers a few new XML namespaces, following the rules in RFC 3688 [17]. the registrations are very serious business, but they're also kind of iconic ๐
15.3.1. urn:ietf:params:xml:ns:xcap-error ๐
the URI for this namespace is urn:ietf:params:xml:ns:xcap-error, and the contacts are the IETF, the SIMPLE working group (simple@ietf.org), and Jonathan Rosenberg (jdrosen@jdrosen.net) ๐
URI: The URI for this namespace is urn:ietf:params:xml:ns:xcap-error
Registrant Contact: IETF, SIMPLE working group, (simple@ietf.org),
Jonathan Rosenberg (jdrosen@jdrosen.net).
the registration also comes with a little HTML page that describes the namespace ๐ธ
XML:
BEGIN
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
"http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type"
content="text/html;charset=iso-8859-1"/>
<title>XCAP Error Namespace</title>
</head>
<body>
<h1>Namespace for XCAP Error Documents</h1>
<h2>urn:ietf:params:xml:ns:xcap-error</h2>
<p>See <a href="http://www.rfc-editor.org/rfc/rfc4825.txt">
RFC4825</a></p>
</body>
</html>
END
15.3.2. urn:ietf:params:xml:ns:xcap-caps ๐ง
same deal for the capabilities namespace, urn:ietf:params:xml:ns:xcap-caps ๐ซง
URI: The URI for this namespace is urn:ietf:params:xml:ns:xcap-caps
Registrant Contact: IETF, SIMPLE working group, (simple@ietf.org),
Jonathan Rosenberg (jdrosen@jdrosen.net).
and its HTML page:
XML:
BEGIN
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
"http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type"
content="text/html;charset=iso-8859-1"/>
<title>XCAP Capabilities Namespace</title>
</head>
<body>
<h1>Namespace for XCAP Capability Documents</h1>
<h2>urn:ietf:params:xml:ns:xcap-caps</h2>
<p>See <a href="http://www.rfc-editor.org/rfc/rfc4825.txt">
RFC4825</a></p>
</body>
</html>
END
15.4. XML Schema Registrations ๐
this section registers two XML schemas, following the procedures in [17]. so two schemas, two vibes ๐ฅ
15.4.1. XCAP Error Schema Registration ๐
the URI is urn:ietf:params:xml:schema:xcap-error, and the contacts are the same as before: IETF, SIMPLE working group, (simple@ietf.org), and Jonathan Rosenberg (jdrosen@jdrosen.net) ๐
the XML for this schema is the sole content of Section 11.2 โจ
15.4.2. XCAP Capabilities Schema Registration ๐
the URI is urn:ietf:params:xml:schema:xcap-caps, with the same registrant contacts as the error schema ๐ and the XML for it is the sole content of Section 12.2 ๐ซถ
16. Acknowledgements ๐
the author wants to thank Jari Urpalainen, who left a ton of important comments and helped with the edit passes ๐ also a big thank you to Ben Campbell, Eva-Maria Leppanen, Hisham Khartabil, Chris Newman, Joel Halpern, Lisa Dusseault, Tim Bray, Pete Cordell, Jeroen van Bemmel, Christian Schmidt, and Spencer Dawkins for their input and comments. and a special shoutout to Ted Hardie for the input and support ๐ซถโจ
17. References ๐
17.1. Normative References ๐ฅ
[1] Maler, E., Yergeau, F., Paoli, J., Bray, T., and C. Sperberg-McQueen, "Extensible Markup Language (XML) 1.0 (Third Edition)", World Wide Web Consortium FirstEdition REC-xml-20040204, February 2004, <http://www.w3.org/TR/2004/REC-xml-20040204>.
[2] Thompson, H., Maloney, M., Mendelsohn, N., and D. Beech, "XML Schema Part 1: Structures Second Edition", World Wide Web Consortium Recommendation REC-xmlschema-1-20041028, October 2004, <http://www.w3.org/TR/2004/REC-xmlschema-1-20041028>.
[3] Layman, A., Hollander, D., and T. Bray, "Namespaces in XML", World Wide Web Consortium FirstEdition REC-xml-names-19990114, January 1999, <http://www.w3.org/TR/1999/REC-xml-names-19990114>.
[4] Daniel, R., DeRose, S., Maler, E., and J. Marsh, "XPointer xmlns() Scheme", World Wide Web Consortium Recommendation REC-xptr-xmlns-20030325, March 2003, <http://www.w3.org/TR/2003/REC-xptr-xmlns-20030325>.
[5] Grosso, P., Marsh, J., Maler, E., and N. Walsh, "XPointer Framework", World Wide Web Consortium Recommendation REC-xptr-framework-20030325, March 2003, <http://www.w3.org/TR/2003/REC-xptr-framework-20030325>.
[6] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
[7] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
[8] Freed, N. and J. Klensin, "Media Type Specifications and Registration Procedures", BCP 13, RFC 4288, December 2005.
[9] Murata, M., St. Laurent, S., and D. Kohn, "XML Media Types", RFC 3023, January 2001.
[10] Clark, J. and S. DeRose, "XML Path Language (XPath) Version 1.0", World Wide Web Consortium Recommendation REC-xpath-19991116, November 1999, <http://www.w3.org/TR/1999/REC-xpath-19991116>.
[11] Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., Leach, P., Luotonen, A., and L. Stewart, "HTTP Authentication: Basic and Digest Access Authentication", RFC 2617, June 1999.
[12] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", RFC 4234, October 2005.
[13] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, January 2005.
[14] Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.
[15] Khare, R. and S. Lawrence, "Upgrading to TLS Within HTTP/1.1", RFC 2817, May 2000.
[16] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., Peterson, J., Sparks, R., Handley, M., and E. Schooler, "SIP: Session Initiation Protocol", RFC 3261, June 2002.
[17] Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688, January 2004.
[18] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, November 2003.
[19] Boyer, J., "Canonical XML Version 1.0", World Wide Web Consortium Recommendation REC-xml-c14n-20010315, March 2001, <http://www.w3.org/TR/2001/REC-xml-c14n-20010315>.
17.2. Informative References ๐ง
[20] Rosenberg, J., "A Presence Event Package for the Session Initiation Protocol (SIP)", RFC 3856, August 2004.
[21] Roach, A., Campbell, B., and J. Rosenberg, "A Session Initiation Protocol (SIP) Event Notification Extension for Resource Lists", RFC 4662, August 2006.
[22] Rosenberg, J., "Extensible Markup Language (XML) Formats for Representing Resource Lists", RFC 4826, May 2007.
[23] Grosso, P. and D. Veillard, "XML Fragment Interchange", World Wide Web Consortium CR CR-xml-fragment-20010212, February 2001, <http://www.w3.org/TR/2001/CR-xml-fragment-20010212>.
[24] Berglund, A., Boag, S., Chamberlin, D., Fernandez, M., Kay, M., Robie, J., and J. Simeon, "XML Path Language (XPath) 2.0", World Wide Web Consortium CR http://www.w3.org/TR/2005/CR-xpath20-20051103, November 2005.
[25] Newman, C. and J. Myers, "ACAP -- Application Configuration Access Protocol", RFC 2244, November 1997.
[26] Day, M., Rosenberg, J., and H. Sugano, "A Model for Presence and Instant Messaging", RFC 2778, February 2000.
[27] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 2434, October 1998.
[28] Roach, A., "Session Initiation Protocol (SIP)-Specific Event Notification", RFC 3265, June 2002.
[29] Duerst, M. and M. Suignard, "Internationalized Resource Identifiers (IRIs)", RFC 3987, January 2005.
Author's Address ๐ฆ
Jonathan Rosenberg
Cisco
Edison, NJ
US
EMail: jdrosen@cisco.com
URI: http://www.jdrosen.net
Full Copyright Statement ๐
Copyright (C) The IETF Trust (2007).
This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.
This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM 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.
Intellectual Property
Okay, so the IETF is being super careful here ๐ง It takes no position on whether any Intellectual Property Rights (or other rights) that someone might claim over the tech in this doc are valid or in scope, and it doesn't say whether any license for them is available or not ๐ It also hasn't done any independent digging to find such rights, so it's not promising anything. If you want the procedures for rights in RFC docs, check out BCP 78 and BCP 79 ๐
Copies of IPR disclosures sent to the IETF Secretariat are there to look at ๐ So are any assurances of licenses that might be made available, plus whatever comes out of an attempt to get a general license or permission for implementers or users to use those proprietary rights. You can find all of that in the IETF on-line IPR repository at http://www.ietf.org/ipr ๐๏ธโจ
The IETF also invites anyone who's interested to flag any copyrights, patents, patent applications, or other proprietary rights that might cover technology needed to implement this standard ๐ซถ Just send the info to the IETF at ietf-ipr@ietf.org ๐
Acknowledgement
And the big thank-you ๐ธ Funding for the RFC Editor function is currently provided by the Internet Society ๐ Honestly, the people keeping these docs running deserve all the flowers ๐
๐ฆ where this page comes from
- ietf: rfc4825 2007-05
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms