Skip to content

Commit

Permalink
Formally define XML elements with RELAX NG; validate XML samples (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfc2822 authored Nov 11, 2024
1 parent 66a72a3 commit 4e791ee
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 88 deletions.
51 changes: 11 additions & 40 deletions content.mkd
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,7 @@ PROPFIND https://example.com/webdav/collection/
HTTP/1.1 207 Multi-Status
<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:" xmlns:P="DAV:Push">
<response>
<href>/webdav/collection/</href>
<prop>
<P:transports>
<P:web-push />
<P:some-other-transport>
<P:some-parameter>...</P:some-parameter>
</P:some-other-transport>
</P:transports>
<P:topic>O7M1nQ7cKkKTKsoS_j6Z3w</P:topic>
</prop>
</response>
</multistatus>
{::include xml/sample-propfind-multistatus.xml}
~~~

In this case, the requested collection supports WebDAV-Push in general (because it has a push topic). Two push transports can be used:
Expand All @@ -170,13 +157,11 @@ In this case, the requested collection supports WebDAV-Push in general (because
Name: `transports`
Namespace: `DAV:Push`
Purpose: Indicates which push transports are supported by the server.
Definition: `<!ELEMENT transports (web-push | %other-transport)+`
Example: see below

Name: `topic`
Namespace: `DAV:Push`
Purpose: Globally unique identifier for the collection.
Definition: `<!ELEMENT topic (#PCDATA)`
Description:

Character sequence that identifies a WebDAV collection for push purposes (globally unique). A specific collection could be reachable at different URLs, but it can only have one push topic.
Expand Down Expand Up @@ -223,6 +208,7 @@ Sample request for Web Push:
POST https://example.com/webdav/collection/
Content-Type: application/xml; charset="utf-8"
<?xml version="1.0" encoding="utf-8" ?>
{::include xml/sample-registration.xml}
HTTP/1.1 201 Created
Expand Down Expand Up @@ -294,18 +280,14 @@ Description:
This element specifies details about a subscription that shall be notified when the collection is updated. Besides the optional expiration, there must be exactly one `subscription` element that
defines the subscription details.

Definition: `<!ELEMENT push-register (expires?, subscription)`

Name: `subscription`
Namespace: `DAV:Push`
Purpose: Specifies a subscription that shall be notified on updates. Contains exactly one element with details about a specific subscription type. In this document, only the `web-push-subscription` child element is defined.
Definition: `<!ELEMENT subscription (web-push-subscription | %other-subscription)`

Name: `expires`
Namespace: `DAV:Push`
Purpose: Specifies an expiration date of the registered subscription. Depending on the context, it's either a requested expiration date or an actual expiration date.
Description: Specifies an expiration date-time in the `IMF-fixdate` format {{RFC9110}}.
Definition: `<!ELEMENT expires (#PCDATA)`
Example: `<expires>Sun, 06 Nov 1994 08:49:37 GMT</expires>`


Expand Down Expand Up @@ -357,7 +339,6 @@ A server MAY use some logic like remembering the last successful delivery plus s
Name: `push-message`
Namespace: `DAV:Push`
Purpose: Contains information of a push message / notification.
Definition: `<!ELEMENT push-message (propstat)`

Example 1:

Expand Down Expand Up @@ -437,25 +418,20 @@ Element definitions:
Name: `web-push`
Purpose: Specifies the Web Push transport.
Description: Used to specify the Web Push Transport in the context of a `<transports>` element, for instance in a list of supported transports.
Definition: `<!ELEMENT web-push (EMPTY)`
Example: `<web-push/>`

Name: `web-push-subscription`
Purpose: Public information of a Web Push subscription that is shared with the WebDAV-Push server (Web Push application server).
Description: Used to specify a Web Push subscription in the context of a `<subscription>` element,
for instance to register a subscription.
Definition: `<!ELEMENT web-push-subscription (push-resource)`
Example: see below

Name: `push-resource`
Purpose: Identifies the endpoint where Web Push notifications are sent to. The push resource is used as the unique identifier for the subscription.
Definition: `<!ELEMENT push-resource (#PCDATA)`
Example:

~~~
<web-push-subscription xmlns="DAV:Push">
<push-resource>https://push.example.net/push/JzLQ3raZJfFBR0aqvOMsLrt54w4rJUsV</push-resource>
</web-push-subscription>
{::include xml/sample-web-push-subscription.xml}
~~~


Expand Down Expand Up @@ -500,19 +476,7 @@ Example service detection of a WebDAV server that supports VAPID:

~~~
<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:" xmlns:P="DAV:Push">
<response>
<href>/webdav/collection/</href>
<prop>
<P:transports>
<P:web-push>
<server-public-key type="p256dh">BA1Hxzyi1RUM1b5wjxsn7nGxAszw2u61m164i3MrAIxHF6YK5h4SDYic-dRuU_RCPCfA5aq9ojSwk5Y2EmClBPs</server-public-key>
</P:web-push>
</P:transports>
<P:topic>O7M1nQ7cKkKTKsoS_j6Z3w</P:topic>
</prop>
</response>
</multistatus>
{::include xml/sample-propfind-multistatus-with-vapid.xml}
~~~

If available, the client SHOULD use this key to create a restricted subscription at the push service.
Expand All @@ -538,3 +502,10 @@ Example for a subscription registration requesting message encryption:
~~~

The server uses these data to encrypt the payload and send it to the push service. The client then decrypts the payload again.


# XML Schema

~~~
{::include xml/webdav-push.rng}
~~~
13 changes: 13 additions & 0 deletions xml/sample-propfind-multistatus-with-vapid.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<multistatus xmlns="DAV:" xmlns:P="DAV:Push">
<response>
<href>/webdav/collection/</href>
<prop>
<P:transports>
<P:web-push>
<P:server-public-key type="p256dh">BA1Hxzyi1RUM1b5wjxsn7nGxAszw2u61m164i3MrAIxHF6YK5h4SDYic-dRuU_RCPCfA5aq9ojSwk5Y2EmClBPs</P:server-public-key>
</P:web-push>
</P:transports>
<P:topic>O7M1nQ7cKkKTKsoS_j6Z3w</P:topic>
</prop>
</response>
</multistatus>
17 changes: 17 additions & 0 deletions xml/sample-propfind-multistatus.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<multistatus xmlns="DAV:" xmlns:P="DAV:Push">
<response>
<href>/webdav/collection/</href>
<prop>
<P:transports>
<P:web-push />

<!-- Not covered by this document:
<P:some-other-transport>
<P:some-parameter>...</P:some-parameter>
</P:some-other-transport>
-->
</P:transports>
<P:topic xmlns="DAV:Push">O7M1nQ7cKkKTKsoS_j6Z3w</P:topic>
</prop>
</response>
</multistatus>
1 change: 0 additions & 1 deletion xml/sample-registration.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8" ?>
<push-register xmlns="DAV:Push">
<subscription>
<web-push-subscription>
Expand Down
3 changes: 3 additions & 0 deletions xml/sample-web-push-subscription.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<web-push-subscription xmlns="DAV:Push">
<push-resource>https://push.example.net/push/JzLQ3raZJfFBR0aqvOMsLrt54w4rJUsV</push-resource>
</web-push-subscription>
31 changes: 31 additions & 0 deletions xml/validate-samples.rng
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<grammar xmlns="http://relaxng.org/ns/structure/1.0">

<!-- root elements of examples in document -->
<start>
<choice>
<ref name="multistatus"/>
<ref name="subscription-registration"/>
<ref name="push-message"/>
<ref name="web-push-subscription"/>
</choice>
</start>

<define name="multistatus" ns="DAV:">
<element name="multistatus">
<element name="response">
<element name="href">
<text/>
</element>
<element name="prop">
<zeroOrMore>
<ref name="prop-transports"/>
<ref name="prop-topic"/>
</zeroOrMore>
</element>
</element>
</element>
</define>

<include href="webdav-push.rng"/>

</grammar>
3 changes: 2 additions & 1 deletion xml/validate.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#!/bin/sh
xmllint --schema webdav-push.xsd --noout *.xml

xmlstarlet val -e -r validate-samples.rng *.xml
114 changes: 114 additions & 0 deletions xml/webdav-push.rng
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<grammar xmlns="http://relaxng.org/ns/structure/1.0" ns="DAV:Push">

<!-- New WebDAV collection properties -->

<define name="prop-transports">
<!-- available push transports -->
<element name="transports">
<choice>
<ref name="web-push-transport"/>
<!-- or other transport, not covered by this schema -->
</choice>
</element>
</define>

<define name="prop-topic">
<!-- push topic -->
<element name="topic">
<text/>
</element>
</define>


<!-- Subscription registration -->

<define name="subscription-registration">
<element name="push-register">
<!-- subscription to register -->
<element name="subscription">
<choice>
<ref name="web-push-subscription"/>
<!-- or other subscription, not covered by this schema -->
</choice>
</element>

<!-- expiration -->
<optional>
<element name="expires">
<text/> <!-- date-time in IMF-fixdate format -->
</element>
</optional>
</element>
</define>


<!-- Push Message -->

<define name="push-message">
<element name="push-message">
<element ns="DAV:" name="propstat"> <!-- defined in WebDAV (RFC 4918) -->
<optional>
<element ns="DAV:" name="status"> <!-- defined in WebDAV (RFC 4918) -->
<text/>
</element>
</optional>

<element ns="DAV:" name="prop"> <!-- defined in WebDAV (RFC 4918) -->
<ref name="prop-topic"/>

<optional>
<element ns="DAV:" name="sync-token"> <!-- defined in Collection Synchronization for WebDAV (RFC 6578) -->
<text/>
</element>
</optional>
</element>
</element>
</element>
</define>


<!-- Web Push -->

<define name="web-push-transport">
<element name="web-push">
<!-- VAPID key -->
<optional>
<element name="server-public-key">
<attribute name="type">
<choice>
<value>p256dh</value>
<!-- or other type / not covered by this schema -->
</choice>
</attribute>
<text/>
</element>
</optional>
</element>
</define>

<define name="web-push-subscription">
<element name="web-push-subscription">
<element name="push-resource">
<text/> <!-- push resource (URL) -->
</element>

<!-- message encryption -->
<optional>
<element name="client-public-key">
<attribute name="type">
<choice>
<value>p256dh</value>
<!-- or other type / not covered by this schema -->
</choice>
</attribute>
<text/>
</element>

<element name="auth-secret">
<text/>
</element>
</optional>
</element>
</define>

</grammar>
46 changes: 0 additions & 46 deletions xml/webdav-push.xsd

This file was deleted.

0 comments on commit 4e791ee

Please sign in to comment.