mirror of
https://github.com/moparisthebest/xeps
synced 2024-08-13 16:53:48 -04:00
![Peter Waher](/assets/img/avatar_default.png)
New contact information has been provided, and example JIDs are updated to point to example.org.
2001 lines
103 KiB
XML
2001 lines
103 KiB
XML
<?xml version='1.0' encoding='UTF-8'?>
|
|
<!DOCTYPE xep SYSTEM 'xep.dtd' [
|
|
<!ENTITY % ents SYSTEM 'xep.ent'>
|
|
%ents;
|
|
]>
|
|
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
|
|
<xep>
|
|
<header>
|
|
<title>HTTP over XMPP transport</title>
|
|
<abstract>This specification defines how XMPP can be used to transport HTTP communication over peer-to-peer networks.</abstract>
|
|
&LEGALNOTICE;
|
|
<number>0332</number>
|
|
<status>Proposed</status>
|
|
<lastcall>2014-10-21</lastcall>
|
|
<type>Standards Track</type>
|
|
<sig>Standards</sig>
|
|
<approver>Council</approver>
|
|
<dependencies>
|
|
<spec>XMPP Core</spec>
|
|
<spec>XEP-0001</spec>
|
|
<spec>XEP-0030</spec>
|
|
<spec>XEP-0047</spec>
|
|
<spec>XEP-0131</spec>
|
|
<spec>XEP-0137</spec>
|
|
<spec>XEP-0166</spec>
|
|
</dependencies>
|
|
<supersedes/>
|
|
<supersededby/>
|
|
<shortname>NOT_YET_ASSIGNED</shortname>
|
|
&peterwaher;
|
|
<revision>
|
|
<version>0.4</version>
|
|
<date>2015-11-09</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>Updated contact information.</p>
|
|
<p>Updated example JIDs to example.org</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.3</version>
|
|
<date>2014-08-12</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>A sequence number have been added to chunks, to allow chunked service to work over servers that do not maintain message order.</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.2</version>
|
|
<date>2014-07-07</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>Updated invalid links.</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.1</version>
|
|
<date>2013-07-11</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Initial published version approved by the XMPP Council.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.7</version>
|
|
<date>2013-07-09</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>Added remarks for the xml encoding to clarify the need to avoid creating invalid XMPP.</p>
|
|
<p>Clarification added regarding to base64 content size when using schema-aware EXI compression.</p>
|
|
<p>The name of the new proposed URI scheme has been changed from xmpp to httpx.</p>
|
|
<p>An URI Scheme Registration Template has been added, as per BCP 35.</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.6</version>
|
|
<date>2013-06-17</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>Removed the streamBase64 transfer mechanism and replaced it with In-band bytestreams (IBB).</p>
|
|
<p>Created new examples, avoiding re-use of known public examples.</p>
|
|
<p>Extended the descriptions of the different transfer mechanisms.</p>
|
|
<p>Ability to state capabilities of the client in the request.</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.5</version>
|
|
<date>2013-05-22</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>Changed IQ stanza type from 'get' to 'set' for all HTTP methods.</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.4</version>
|
|
<date>2013-05-14</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>Updated format of encoding table, and made it into a definition list.</p>
|
|
<p>Language corrections.</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.3</version>
|
|
<date>2013-05-10</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>Added more information about chunking.</p>
|
|
<p>Added implementation notes regarding bandwidth and stanza size limitations in XMPP Servers.</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.2</version>
|
|
<date>2013-05-08</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>Added support for XEP-0131, Stanza Headers and Internet Metadata.</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.1</version>
|
|
<date>2013-05-05</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>First draft.</p>
|
|
</remark>
|
|
</revision>
|
|
</header>
|
|
<section1 topic='Introduction' anchor='intro'>
|
|
<p>
|
|
Many documents have been written on how to transport XMPP datagrams using HTTP. The motivation behind such solutions has often been to be able to use XMPP in
|
|
scripting languages such as Java Script running in web browsers.
|
|
</p>
|
|
<p>
|
|
But up to this point very little has been written about the reverse: How to transport HTTP methods and HTTP responses over an XMPP-based peer-to-peer network.
|
|
Here, the motivation is as follows: There are multitudes of applications and APIs written that are based on HTTP over TCP as the basic communication transport protocol.
|
|
As these are moving closer and closer to the users, problems arise when the users want to protect their data and services using firewalls. Even though there are methods
|
|
today to open up firewalls manually or automatically permit communication with such devices and applications, you still open up the application for everybody. This
|
|
rises the need for more advanced security measures which is sometimes difficult to implement using HTTP.
|
|
</p>
|
|
<p>
|
|
The XMPP protocol however does not have the same problems as HTTP in these regards. It's a peer-to-peer protocol naturally allowing communication with applications
|
|
and devices behind firewalls. It also includes advanced user authentication and authorization which makes it easier to make sure unauthorized access to private
|
|
content is prevented.
|
|
</p>
|
|
<p>
|
|
Furthermore, with the advent of semantic web technologies and its use in web 3.0 and Internet of Things applications, such applications move even more rapidly into
|
|
the private spheres of the users, where security and privacy is of paramount importance, it is necessary to use more secure transport protocols than HTTP over TCP.
|
|
</p>
|
|
<p>
|
|
There are many different types of HTTP-based communication that one would like to be able to transport over XMPP. A non-exhaustive list can include:
|
|
</p>
|
|
<ul>
|
|
<li>Web Content like pages, images, files, etc.</li>
|
|
<li>Web Forms.</li>
|
|
<li>Web Services (SOAP, REST, etc.)</li>
|
|
<li>Semantic Web Resources (RDF, Turtle, etc.)</li>
|
|
<li>Federated SPARQL queries (SQL-type query language for the semantic web, or web 3.0)</li>
|
|
<li>Streamed multi-media content in UPnP and DLNA networks.</li>
|
|
</ul>
|
|
<p>
|
|
Instead of trying to figure out all possible things transportable over HTTP and make them transportable over XMPP, this document ignores the type of content transported,
|
|
and instead focuses on encoding and decoding the original HTTP requests and responses, building an HTTP tunnel over an existing XMPP connection. It would enable
|
|
existing applications to work seamlessly over XMPP if browsers and web services supported this extension (like displaying your home control application on your phone
|
|
when you are at work), without the need to update the myriad of existing applications. It would also permit federated SPARQL queries in personal networks with the added
|
|
benefit of being able to control who can talk to who (or what can talk to what) through established friendship relationships.
|
|
</p>
|
|
<p>
|
|
Previous extensions handling different aspects of XMPP working together with HTTP:
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
&xep0070;: This specification handles client authentication of resources, where there are three parties: HTTP Client <-> HTTP Server/XMPP Client <-> XMPP Server.
|
|
Here HTTP Client authentication to resources on the HTTP Server is made by a third party, an XMPP Server.
|
|
</li>
|
|
<li>
|
|
&xep0072;: This specification handles execution of SOAP-based web services specifically. This specification has some benefits regarding to Web Service calls over XMPP,
|
|
but is only one example of all types of HTTP-based communication one would desire to transport over XMPP.
|
|
</li>
|
|
<li>
|
|
&xep0124;: This specification handles XMPP-based communication over HTTP sessions (BOSH), allowing for instance, XMPP communication in java script using the
|
|
XML HTTP Request object. This is in some way the reverse of what this document proposes to do.
|
|
</li>
|
|
<li>
|
|
&xep0131;: While not directly related to HTTP, it is used to transport headers in the form of collections of key-value pairs, exactly as is done in HTTP. The format
|
|
for encoding headers into XMP defined by this XEP will be re-used in this XEP.
|
|
</li>
|
|
<li>
|
|
&xep0147;: This informational specification proposes ways to define XMPP-actions using URL's. The xmpp URI scheme is formally defined in &rfc5122;.
|
|
This document will propose a different URI scheme for HTTP-based resources over an XMPP transport: httpx.
|
|
</li>
|
|
</ul>
|
|
</section1>
|
|
<section1 topic='Requirements' anchor='reqs'>
|
|
<p>
|
|
This document presupposes the server already has a web server (HTTP Server) implementation, and that it hosts content through it, content which can be both
|
|
dynamic (i.e. generated) or static (e.g. files) in nature. Content, which it wants to
|
|
publish to XMPP clients as well as HTTP clients. It also presupposes that the client is aware of HTTP semantics and MIME encoding.
|
|
</p>
|
|
</section1>
|
|
<section1 topic='Glossary' anchor='glossary'>
|
|
<p>The following table lists common terms and corresponding descriptions.</p>
|
|
<dl>
|
|
<di>
|
|
<dt>HTTP</dt>
|
|
<dd>
|
|
Hyper Text Transfer Protocol. Version 1.1 of HTTP is described in RFC 2616 <note>
|
|
RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1 <<link url='http://tools.ietf.org/html/rfc2616'>http://tools.ietf.org/html/rfc2616</link>>
|
|
</note>. The PATCH method is described in RFC 5789 <note>
|
|
RFC 5789: PATCH Method for HTTP <<link url='http://tools.ietf.org/html/rfc5789'>http://tools.ietf.org/html/rfc5789</link>>
|
|
</note>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>HTTP Client</dt>
|
|
<dd>An HTTP Client is the initiator of an HTTP Request.</dd>
|
|
</di>
|
|
<di>
|
|
<dt>HTTP Method</dt>
|
|
<dd>
|
|
HTTP Methods are: <strong>OPTIONS</strong>, <strong>GET</strong>, <strong>HEAD</strong>, <strong>POST</strong>,
|
|
<strong>PUT</strong>, <strong>DELETE</strong>, <strong>TRACE</strong> and <strong>PATCH</strong>. The HTTP
|
|
Method CONNECT is not supported by this specification.
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>HTTP Request</dt>
|
|
<dd>An HTTP Request consists of a HTTP Method, version information, headers and optional body.</dd>
|
|
</di>
|
|
<di>
|
|
<dt>HTTP Resource</dt>
|
|
<dd>A resource on an HTTP Server identified by a path. Each path begins with a separator character (/).</dd>
|
|
</di>
|
|
<di>
|
|
<dt>HTTP Response</dt>
|
|
<dd>An HTTP Response consists of a status code, optional status message, headers and optional body.</dd>
|
|
</di>
|
|
<di>
|
|
<dt>HTTP Server</dt>
|
|
<dd>An HTTP Server responds to HTTP Client requests.</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Web Server</dt>
|
|
<dd>Used synonymously with HTTP Server.</dd>
|
|
</di>
|
|
</dl>
|
|
</section1>
|
|
<section1 topic='Use Cases' anchor='usecases'>
|
|
<p>
|
|
All HTTP communication is done using the <strong>Request</strong>/<strong>Response</strong> paradigm. Each HTTP Request is made sending an <strong>iq</strong>-stanza
|
|
containing a <strong>req</strong> element to the server. Each <strong>iq</strong>-stanza sent is of type <strong>set</strong>.
|
|
</p>
|
|
<p>
|
|
When the server responds, it does so by sending an <strong>iq</strong>-stanza response (type <strong>result</strong>) back to the client containing a <strong>resp</strong>
|
|
element. Since responses are asynchronous, and since multiple requests may be active at the same time, responses may be returned in a different order than the in which the
|
|
original requests were made.
|
|
</p>
|
|
<p>
|
|
Requests or responses containing data must also consider how this data should be encoded within the XML telegram. Normally in HTTP, content and headers are separated
|
|
by a blank line, and the transfer of the content is made in the same stream. Specific HTTP headers are used to define how the content is transferred and encoded within
|
|
the stream (Content-Type, Content-Length, Content-Encoding, Content-Transfer-Encoding). This approach is not possible if the response is to be embedded in an XML telegram,
|
|
since it can interfere with the encoding of the encompassing XML.
|
|
</p>
|
|
<p>
|
|
To solve this, this document specifies additional data transfer mechanisms that are compatible with the XMPP protocol. The normal HTTP-based content transfer headers will
|
|
still be transported, but do not affect the content encoding used in the XMPP transport. The following content encoding methods are available:
|
|
</p>
|
|
<dl>
|
|
<di>
|
|
<dt>text</dt>
|
|
<dd>
|
|
<p>
|
|
Normal text content. The text is encoded as text within XML, using the same encoding used by the XML stream. XML escape characters (<, > and &)
|
|
are escaped using the normal &lt;, &gt; and &amp; character escape sequences.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>xml</dt>
|
|
<dd>
|
|
<p>
|
|
Xml content embedded in the XML telegram. Note however, that any processing instructions or XML version statements must be avoided, since it may cause
|
|
the XML stream to become invalid XML. If this is a problem, normal <strong>text</strong> encoding can be used as an alternative. The advantage of <strong>xml</strong>
|
|
instead of <strong>text</strong> or <strong>base64</strong> encodings is when used in conjunction with EXI compression &xep0322;. EXI compression has the ability to
|
|
compress XML efficiently. Text will not be compressed, unless response exists in internal string tables. Base-64 encoded data will be compressed so that the 33%
|
|
size gain induced by the encoding is recaptured.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>base64</dt>
|
|
<dd>
|
|
<p>
|
|
Base-64 encoded binary content. Can be used to easily embed binary content in the telegram.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>chunkedBase64</dt>
|
|
<dd>
|
|
<p>
|
|
Chunked Base-64 encoded binary content. The content is not embedded in the telegram. Instead it is sent in chunks, using separate
|
|
<strong>chunk</strong> messages to the client. Chunked transport can be used by the server when it doesn't know the size of the final result.
|
|
Streaming content, i.e. content of infinite length, must use <strong>ibb</strong> or <strong>jingle</strong> transport types to transfer content.
|
|
If the content consists of a file, <strong>sipub</strong> should be used.
|
|
</p>
|
|
<p>
|
|
Chunked encoding is perfect for dynamic responses of moderate sizes, for instance for API method responses. The server does not know when the response
|
|
is begun to be generated what the final size will be, but it will be most probably "manageable". Using the chunked transfer mechanism enables the
|
|
server to start sending the content, minimizing the need for buffers, and at the same time minimizing the number of messages that needs to be sent,
|
|
increasing throughput.
|
|
</p>
|
|
<p>
|
|
The client can limit the maximum chunk size to be used by the server, using the <strong>maxChunkSize</strong> attribute in the request. The chunk
|
|
size can be set to a value between 256 and 65536. If not provided in the request, the server chooses an appropriate value. Note that chunks can
|
|
be sent containing a smaller amount of bytes than the maximum chunk size provided in the request.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>sipub</dt>
|
|
<dd>
|
|
<p>
|
|
The sender might deem the content to be too large for sending embedded in the XMPP telegram. To circumnavigate this, the sender publishes
|
|
the content as a file using &xep0137; (Publishing Stream Initiation Requests), instead of embedding the content directly. This might be the case for instance, when
|
|
a client requests a video resource, without using a ranged request.
|
|
</p>
|
|
<p>
|
|
This transfer mechanism is of course the logical choice, if the content is already stored in a file on the server, and the size of the file
|
|
is sufficiently large to merit the overhead of sipub. Smaller files can simply be returned using the <strong>text</strong>, <strong>xml</strong>
|
|
or <strong>base64</strong> mechanisms.
|
|
</p>
|
|
<p>
|
|
The client can disable the use of <strong>sipub</strong> by the server, by including a <strong>sipub='false'</strong> attribute in the request.
|
|
<strong>sipub</strong> is enabled by default. On constrained devices with limited support for different XEP's, this can be a way to avoid the
|
|
use of technologies not supported by the client.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>ibb</dt>
|
|
<dd>
|
|
<p>
|
|
This option may be used to encode indefinite streams, like live audio or video streams (HLS, SHOUTcast, Motion JPeg web cams, etc).
|
|
It uses &xep0047; to send the content over an in-band bytestream to the client. This option is not available in requests, only in responses.
|
|
</p>
|
|
<p>
|
|
Streams must not use any of the above mechanisms. Only <strong>ibb</strong> and <strong>jingle</strong> mechanisms can be used. If the content
|
|
represents multimedia <strong>jingle</strong> is preferrable, especially if different encodings are available.
|
|
</p>
|
|
<p>
|
|
The client can disable the use of <strong>ibb</strong> by the server, by including a <strong>ibb='false'</strong> attribute in the request.
|
|
<strong>ibb</strong> is enabled by default. On constrained devices with limited support for different XEP's, this can be a way to avoid the
|
|
use of technologies not supported by the client.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>jingle</dt>
|
|
<dd>
|
|
<p>
|
|
For demanding multi-media streams alternative methods to transport streaming rather than embedded into the XMPP stream may be
|
|
required. Even though the <strong>ibb</strong> method may be sufficient to stream a low-resolution web cam in the home, or listen to a microphone
|
|
or a radio station, it is probably badly suited for high-resolution video streams with multiple video angles and audio channels. If such content is accessed
|
|
and streamed, the server can negotiate a different way to stream the content using &xep0166;.
|
|
</p>
|
|
<p>
|
|
The client can disable the use of <strong>ingle</strong> by the server, by including a <strong>jingle='false'</strong> attribute in the request.
|
|
<strong>jingle</strong> is enabled by default. On constrained devices with limited support for different XEP's, this can be a way to avoid the
|
|
use of technologies not supported by the client.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
</dl>
|
|
<p>
|
|
<strong>Note:</strong> Content encoded using <strong>chunkedBase64</strong> encoding method can be terminated, either by the receptor going off-line, or by
|
|
sending a <strong>close</strong> command to the sender. The transfer methods <strong>sipub</strong>, <strong>ibb</strong> and <strong>jingle</strong> have
|
|
their own mechanisms for aborting content transfer.
|
|
</p>
|
|
<section2 topic='HTTP Methods'>
|
|
<p>
|
|
The following use cases show how different HTTP methods may work when transported over XMPP. To facilitate the readability in these examples,
|
|
simple text or xml results are shown.
|
|
</p>
|
|
<section3 topic='OPTIONS' anchor='OPTIONS'>
|
|
<p>
|
|
This section shows an example of an OPTIONS method call. OPTIONS is described in <link url='http://tools.ietf.org/html/rfc2616#section-9.2'>§9.2 in RFC 2616</link>.
|
|
</p>
|
|
<example caption='OPTIONS'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='1'>
|
|
<req xmlns='urn:xmpp:http' method='OPTIONS' resource='*' version='1.1'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>example.org</header>
|
|
</headers>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='1'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 13:52:10 GMT-4</header>
|
|
<header name='Allow'>OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE</header>
|
|
<header name='Content-Length'>0</header>
|
|
</headers>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section3>
|
|
<section3 topic='GET' anchor='GET'>
|
|
<p>
|
|
This section shows an example of a GET method call. GET is described in <link url='http://tools.ietf.org/html/rfc2616#section-9.3'>§9.3 in RFC 2616</link>.
|
|
</p>
|
|
<example caption='GET'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='2'>
|
|
<req xmlns='urn:xmpp:http' method='GET' resource='/rdf/xep' version='1.1'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>example.org</header>
|
|
</headers>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='2'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 16:39:54GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>text/turtle</header>
|
|
<header name='Content-Length'>...</header>
|
|
<header name='Connection'>Close</header>
|
|
</headers>
|
|
<data>
|
|
<text>@prefix dc: <http://purl.org/dc/elements/1.1/>.
|
|
@base <http://example.org/>.
|
|
|
|
<xep> dc:title "HTTP over XMPP";
|
|
dc:creator <PeterWaher>;
|
|
dc:publisher <XSF>.</text>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
<p>
|
|
<strong>Note:</strong> The XMPP/HTTP bridge at the server only transmits headers literally as they are reported, as if it was normal HTTP over TCP
|
|
that was used. In the HTTP over XMPP case, connections are not handled in the same way, and so the "Connection: Close" header has no meaning in this
|
|
case. For more information about connection handling in the HTTP over XMPP case, see the section on <link url='#httpconnections'>Connection Handling</link>.
|
|
</p>
|
|
</section3>
|
|
<section3 topic='HEAD' anchor='HEAD'>
|
|
<p>
|
|
This section shows an example of a HEAD method call. HEAD is described in <link url='http://tools.ietf.org/html/rfc2616#section-9.4'>§9.4 in RFC 2616</link>.
|
|
</p>
|
|
<example caption='HEAD'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='3'>
|
|
<req xmlns='urn:xmpp:http' method='HEAD' resource='/video/video1.m4' version='1.1'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>example.org</header>
|
|
</headers>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='3'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 16:57:12GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>video/mp4</header>
|
|
<header name='Content-Length'>12345678</header>
|
|
</headers>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section3>
|
|
<section3 topic='POST' anchor='POST'>
|
|
<p>
|
|
This section shows an example of a POST method call. POST is described in <link url='http://tools.ietf.org/html/rfc2616#section-9.5'>§9.5 in RFC 2616</link>.
|
|
</p>
|
|
<example caption='POST'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='4'>
|
|
<req xmlns='urn:xmpp:http' method='POST' resource='/sparql/?default-graph-uri=http%3A%2F%2Fexample.org%2Frdf/xep' version='1.1'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>example.org</header>
|
|
<header name='User-agent'>Clayster HTTP/XMPP Client</header>
|
|
<header name='Content-Type'>application/sparql-query</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<text>PREFIX dc: <http://purl.org/dc/elements/1.1/>
|
|
BASE <http://example.org/>
|
|
|
|
SELECT ?title ?creator ?publisher
|
|
WHERE { ?x dc:title ?title .
|
|
OPTIONAL { ?x dc:creator ?creator } .
|
|
}</text>
|
|
</data>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='4'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 17:09:34-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>application/sparql-results+xml</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<xml>
|
|
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
|
|
<head>
|
|
<variable name="title"/>
|
|
<variable name="creator"/>
|
|
</head>
|
|
<results>
|
|
<result>
|
|
<binding name="title">
|
|
<literal>HTTP over XMPP</literal>
|
|
</binding>
|
|
<binding name="creator">
|
|
<uri>http://example.org/PeterWaher</uri>
|
|
</binding>
|
|
</result>
|
|
</results>
|
|
</sparql>
|
|
</xml>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
<p>
|
|
<strong>Note:</strong> If using <strong>xml</strong> encoding of data, care has to be taken to avoid including the version and encoding information
|
|
(<?xml version="1.0"?>) at the top of the document, otherwise the resulting XML will be invalid. Care has also to be taken to make sure that the
|
|
generated XML is not invalid XMPP, even though it might be valid XML. This could happen for instance, if the XML contains illegal elements from the
|
|
jabber:client namespace. If in doubt, use another encoding mechanism.
|
|
</p>
|
|
</section3>
|
|
<section3 topic='PUT' anchor='PUT'>
|
|
<p>
|
|
This section shows an example of a PUT method call. PUT is described in <link url='http://tools.ietf.org/html/rfc2616#section-9.6'>§9.6 in RFC 2616</link>.
|
|
</p>
|
|
<example caption='PUT'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='5'>
|
|
<req xmlns='urn:xmpp:http' method='PUT' resource='/index.html' version='1.1'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>example.org</header>
|
|
<header name='Content-Type'>text/html</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<text><html><header/><body><p>Beautiful home page.</p></body></html></text>
|
|
</data>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='5'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='204' statusMessage='No Content'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 17:40:41GMT-4</header>
|
|
<header name='Content-Length'>0</header>
|
|
</headers>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section3>
|
|
<section3 topic='DELETE' anchor='DELETE'>
|
|
<p>
|
|
This section shows an example of a DELETE method call. DELETE is described in <link url='http://tools.ietf.org/html/rfc2616#section-9.7'>§9.7 in RFC 2616</link>.
|
|
</p>
|
|
<example caption='DELETE'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='6'>
|
|
<req xmlns='urn:xmpp:http' method='DELETE' resource='/index.html' version='1.1'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>example.org</header>
|
|
</headers>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='6'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='403' statusMessage='Forbidden'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 17:46:07GMT-4</header>
|
|
<header name='Content-Type'>text/plain</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<text>You're not allowed to change the home page!</text>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section3>
|
|
<section3 topic='TRACE' anchor='TRACE'>
|
|
<p>
|
|
This section shows an example of a TRACE method call. TRACE is described in <link url='http://tools.ietf.org/html/rfc2616#section-9.8'>§9.8 in RFC 2616</link>.
|
|
</p>
|
|
<example caption='TRACE'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='7'>
|
|
<req xmlns='urn:xmpp:http' method='TRACE' resource='/rdf/ex1.turtle' version='1.1'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>example.org</header>
|
|
</headers>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='7'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 17:55:10GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>message/http</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<text>GET /rdf/ex1.turtle HTTP/1.1
|
|
Host: example.org</text>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
<p>
|
|
<strong>Note:</strong> The Trace command returns the request it received from the client by the server. Here, however, it is assumed that the request
|
|
is made over HTTP/TCP, not HTTP/XMPP. Therefore, in this example, the XMPP layer has transformed the HTTP/XMPP request into an HTTP/TCP-looking
|
|
request, which is returned as the response to the TRACE Method call. RFC 2616 is silent to the actual format of the TRACE response
|
|
(MIME TYPE message/http), and TRACE is only used (if not disabled for security reasons) for debugging connections and routing via proxies.
|
|
Therefore, a response returning the original XMPP request should also be accepted by the caller.
|
|
</p>
|
|
</section3>
|
|
<section3 topic='PATCH' anchor='PATCH'>
|
|
<p>
|
|
This section shows an example of a PATCH method call. PATCH is described in <link url='http://tools.ietf.org/html/rfc5789'>RFC 5789</link>.
|
|
</p>
|
|
<example caption='PATCH'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='8'>
|
|
<req xmlns='urn:xmpp:http' method='PATCH' resource='/file.txt' version='1.1'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>www.example.com</header>
|
|
<header name='Content-Type'>application/example</header>
|
|
<header name='If-Match'>e0023aa4e</header>
|
|
<header name='Content-Length'>100</header>
|
|
</headers>
|
|
<data>
|
|
[description of changes]
|
|
</data>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='8'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='204' statusMessage='No Content'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Content-Location'>/file.txt</header>
|
|
<header name='ETag'>e0023aa4e</header>
|
|
</headers>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section3>
|
|
</section2>
|
|
<section2 topic='Encoding formats' anchor='encoding'>
|
|
<p>
|
|
In the following sub-sections, the different data encoding formats are discussed, each with corresponding examples to illustrate how they work.
|
|
The interesting part of these examples is the <strong>data</strong> element and its contents.
|
|
</p>
|
|
<section3 topic='text'>
|
|
<p>
|
|
Text responses is a simple way to return text responses (i.e. any MIME Type starting with text/). Since the text is embedded into XML, the
|
|
characters <, > and & need to be escaped to &lt;, &gt; and &amp; respectively.
|
|
</p>
|
|
<p>
|
|
The following example shows how a TURTLE response, which is text-based, is returned using the <strong>text</strong> encoding:
|
|
</p>
|
|
<example caption='text'>
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='2'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 16:39:54GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>text/turtle</header>
|
|
<header name='Content-Length'>...</header>
|
|
<header name='Connection'>Close</header>
|
|
</headers>
|
|
<data>
|
|
<text>@prefix dc: <http://purl.org/dc/elements/1.1/>.
|
|
@base <http://example.org/>.
|
|
|
|
<xep> dc:title "HTTP over XMPP";
|
|
dc:creator <PeterWaher>;
|
|
dc:publisher <XSF>.</text>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section3>
|
|
<section3 topic='xml'>
|
|
<p>
|
|
XML is a convenient way to return XML embedded in the XMPP response. This can be suitable for MIME Types of the form <strong>.*/(.*[+])?xml</strong>
|
|
(using regular expression to match them), like text/xml, application/soap+xml or application/sparql-results+xml. Care has to be taken however, since
|
|
not all XML constructs can be embedded as content to an XML element without invalidating it, like the xml version and encoding declaration
|
|
(<?xml version="1.0"?> as an example). Care has also to be taken to make sure that the generated XML is not invalid XMPP, even though it might
|
|
be valid XML. This could happen for instance, if the XML contains illegal elements from the jabber:client namespace.
|
|
</p>
|
|
<p>
|
|
If unsure how to handle XML responses using the <strong>xml</strong> encoding type, you can equally well use the <strong>text</strong> type, but
|
|
encode the XML escape characters <, > and &, or use another encoding, like <strong>base64</strong>.
|
|
</p>
|
|
<p>
|
|
The advantage of <strong>xml</strong> instead of <strong>text</strong> or <strong>base64</strong> encodings is when used in conjunction with
|
|
<link url='http://xmpp.org/extensions/xep-0322.html'>EXI compression</link>. EXI compression has the ability to compress XML efficiently.
|
|
Text will not be compressed, unless response exists in internal string tables. Base-64 encoded data will be compressed so that the 33% size
|
|
gain induced by the encoding is recaptured.
|
|
</p>
|
|
<example caption='xml'>
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='4'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 17:09:34-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>application/sparql-results+xml</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<xml>
|
|
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
|
|
<head>
|
|
<variable name="title"/>
|
|
<variable name="creator"/>
|
|
</head>
|
|
<results>
|
|
<result>
|
|
<binding name="title">
|
|
<literal>HTTP over XMPP</literal>
|
|
</binding>
|
|
<binding name="creator">
|
|
<uri>http://example.org/PeterWaher</uri>
|
|
</binding>
|
|
</result>
|
|
</results>
|
|
</sparql>
|
|
</xml>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section3>
|
|
<section3 topic='base64'>
|
|
<p>
|
|
Base-64 encoding is a simple way to encode content that is easily embedded into XML. Apart from the advantage of being easy to encode,
|
|
it has the disadvantage to increase the size of the content by 33%, since it requires 4 bytes to encode 3 bytes of data.
|
|
Care has to be taken not to send too large items using this encoding.
|
|
</p>
|
|
<p>
|
|
<strong>Note:</strong> The actual size of the content being sent does not necessarily need to increase if this encoding method is used.
|
|
If EXI compression is used at the same time, and it uses schema-aware compression, it will actually understand that the character set used
|
|
to encode the data only uses 6 bits of information per character, and thus compresses the data back to its original size.
|
|
</p>
|
|
<p>
|
|
The following example shows an image is returned using the <strong>base64</strong> encoding:
|
|
</p>
|
|
<example caption='base64'>
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='9'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 16:39:54GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>image/png</header>
|
|
<header name='Content-Length'>221203</header>
|
|
</headers>
|
|
<data>
|
|
<base64>iVBORw0KGgoAAAANSUhEUgAAASwAAAGQCAYAAAAUdV17AAAAAXNSR0 ... tVWJd+e+y1AAAAABJRU5ErkJggg==</base64>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section3>
|
|
<section3 topic='chunkedBase64'>
|
|
<p>
|
|
In HTTP, Chunked Transfer Encoding is used when the sender does not know the size of the content being sent, and to avoid having its buffers
|
|
overflow, sends the content in chunks with a definite size.
|
|
</p>
|
|
<p>
|
|
A similar method exists in the HTTP over XMPP transport: The <strong>chunkedBase64</strong> allows the sender to transmit the content in chunks.
|
|
Every chunk is base-64 encoded. The stream of chunks are identified by a <strong>streamId</strong> parameter, since chunks from different responses
|
|
may be transmitted at the same time.
|
|
</p>
|
|
<p>
|
|
Another difference between normal chunked transport, and the <strong>chunkedBase64</strong> encoding, is that the size of chunks does not have to be
|
|
predetermined. Chunks are naturally delimited and embedded in the XML stanza. The last chunk in a response must have the <strong>last</strong>
|
|
attribute set to true.
|
|
</p>
|
|
<example caption='chunkedBase64'>
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='10'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 04 May 2013 13:43:12GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>image/png</header>
|
|
<header name='Content-Length'>221203</header>
|
|
</headers>
|
|
<data>
|
|
<chunkedBase64 streamId='Stream0001'/>
|
|
</data>
|
|
</resp>
|
|
</iq>
|
|
|
|
<message from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'>
|
|
<chunk xmlns='urn:xmpp:http' streamId='Stream0001' nr='0'>iVBORw0KGgoAAAANSUhEUgAAASwAAAGQCAYAA ...</chunk>
|
|
</message>
|
|
|
|
...
|
|
|
|
<message from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'>
|
|
<chunk xmlns='urn:xmpp:http' streamId='Stream0001' nr='5' last='true'>... 2uPzi9u+tVWJd+e+y1AAAAABJRU5ErkJggg==</chunk>
|
|
</message>]]>
|
|
</example>
|
|
<p>
|
|
<strong>Note:</strong> Chunked encoding assumes the content to be finite. If content is infinite (i.e. for instance live streaming),
|
|
the <strong>ibb</strong> or <strong>jingle</strong> transfer encodings must be used instead. If the sender is unsure if the content is
|
|
finite or infinite, <strong>ibb</strong> or <strong>jingle</strong> must be used.
|
|
</p>
|
|
<p>
|
|
<strong>Note 2:</strong> If the web server sends chunked data to the client it uses the HTTP header <strong>Transfer-Encoding: chunked</strong>,
|
|
and then sends the data in chunks but with chunk sizes inserted so the receiving end can decode the incoming data. Note that this data will
|
|
be included in the data sent in the XMPP chunks defined by this document. In this case, data will be chunked twice: First by the web server,
|
|
and then by the HTTP over XMPP transport layer. When received by the client, it is first reassembled by the HTTP over XMPP layer on the client,
|
|
and then by the HTTP client who will read the original chunk size elements inserted into the content. More information about HTTP chunking,
|
|
can be found in <link url='http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1'>RDF2616 §3.6.1</link>.
|
|
</p>
|
|
<p>
|
|
<strong>Note 3:</strong> In order to work over XMPP servers that do not maintain message order, a <strong>nr</strong> attribute is available on the
|
|
<strong>chunk</strong> element. The first chunk reports a <strong>nr</strong> of zero. Each succcessive chunk reports a <strong>nr</strong> that is
|
|
incremented by one. In this way, the receiver can make sure to order incoming chunks in the correct order.
|
|
</p>
|
|
</section3>
|
|
<section3 topic='sipub'>
|
|
<p>
|
|
Often content being sent can be represented by a file, virtual or real, especially if the content actually represents a file and is not
|
|
dynamically generated. In these instances, instead of embedding the contents in the response,
|
|
since content can be potentially huge, a File Stream Initiation is returned instead, as defined in
|
|
<link url='http://xmpp.org/extensions/xep-0137.html'>XEP 0137: Publishing Stream Initiation Requests</link>. This is done using the
|
|
<strong>sipub</strong> element.
|
|
</p>
|
|
<example caption='sipub'>
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='11'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 16:39:54GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>image/png</header>
|
|
<header name='Content-Length'>221203</header>
|
|
</headers>
|
|
<data>
|
|
<sipub xmlns='http://jabber.org/protocol/sipub'
|
|
from='httpserver@example.org'
|
|
id='file-0001'
|
|
mime-type='image/png'
|
|
profile='http://jabber.org/protocol/si/profile/file-transfer'>
|
|
<file xmlns='http://jabber.org/protocol/si/profile/file-transfer'
|
|
name='Kermit.png'
|
|
size='221203'
|
|
date='2013-03-06T16:47Z'/>
|
|
</sipub>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section3>
|
|
<section3 topic='ibb' anchor='#streams'>
|
|
<p>
|
|
Some web servers provide streaming content, i.e. content where packets are sent according to a timely fashion. Examples are video
|
|
and audio streams like HLS (HTTP Live Streams), SHOUTcast, ICEcast, Motion JPeg, etc. In all these examples, content is infinite,
|
|
and cannot be sent "all as quickly as possible". Instead, content is sent according to some kind of bitrate or frame rate for
|
|
example.
|
|
</p>
|
|
<p>
|
|
Such content must use the <strong>ibb</strong> transfer mechanism, if used (or the <strong>jingle</strong> transfer machanism).
|
|
The <strong>ibb</strong> transfer mechanism uses <link url='http://xmpp.org/extensions/xep-0047.html'>In-Band Bytestreams</link>
|
|
to transfer data from the server to the client. It starts by sending an a <strong>ibb</strong> element containing a <strong>sid</strong>
|
|
attribute identifying the stream. Then the server sends an <strong>ibb:open</strong> IQ-stanza to the client according to
|
|
<link url='http://xmpp.org/extensions/xep-0047.html'>XEP-0047</link>. The client can choose to reject, negotiate or acceopt the request
|
|
whereby the transfer is begun. When the client is satisified and wants to close the stream, it does so, also according to
|
|
<link url='http://xmpp.org/extensions/xep-0047.html'>XEP-0047</link>. The <strong>sid</strong> value returned in the HTTP response
|
|
is the same <strong>sid</strong> value that is later used by the IBB messages that follow. In this way, the client can relate
|
|
the HTTP request and response, with the corresponding data transferred separately.
|
|
</p>
|
|
<example caption='ibb'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='12'>
|
|
<req xmlns='urn:xmpp:http' method='GET' resource='/webcam1.jpg' version='1.1'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>example.org</header>
|
|
</headers>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='12'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 04 May 2013 15:05:32GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>multipart/x-mixed-replace;boundary=__2347927492837489237492837</header>
|
|
</headers>
|
|
<data>
|
|
<ibb sid='Stream0002'/>
|
|
</data>
|
|
</resp>
|
|
</iq>
|
|
|
|
<iq type='set'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='13'>
|
|
<open xmlns='http://jabber.org/protocol/ibb'
|
|
block-size='32768'
|
|
sid='Stream0002'
|
|
stanza='message'/>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='13'/>
|
|
|
|
<message from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'>
|
|
<data xmlns='http://jabber.org/protocol/ibb' sid='Stream0002' seq='0'>...</chunk>
|
|
</message>
|
|
|
|
...
|
|
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='14'>
|
|
<close xmlns='http://jabber.org/protocol/ibb' sid='Stream0002'/>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='14'/>]]>
|
|
</example>
|
|
</section3>
|
|
<section3 topic='jingle' anchor='jingle'>
|
|
<p>
|
|
For demanding multi-media streams alternative methods to transport streaming rather than embedded into the XMPP stream may be
|
|
required. Even though the <strong>ibb</strong> method may be sufficient to stream a low-resolution web cam in the home, or listen to a microphone
|
|
or a radio station, it is probably badly suited for high-resolution video streams with multiple video angles and audio channels. If such content is accessed
|
|
and streamed, the server can negotiate a different way to stream the content using <link url='http://xmpp.org/extensions/xep-0166.html'>XEP 0166: Jingle</link>.
|
|
</p>
|
|
<example caption='jingle'>
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='14'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 16:39:54GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>video/mp4</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<jingle xmlns='urn:xmpp:jingle:1'
|
|
action='session-initiate'
|
|
initiator='romeo@montague.lit/orchard'
|
|
sid='a73sjjvkla37jfea'>
|
|
<content creator='initiator' name='voice'>
|
|
<description xmlns='urn:xmpp:jingle:apps:rtp:1' media='audio'>
|
|
<payload-type id='96' name='speex' clockrate='16000'/>
|
|
<payload-type id='97' name='speex' clockrate='8000'/>
|
|
<payload-type id='18' name='G729'/>
|
|
<payload-type id='0' name='PCMU' />
|
|
<payload-type id='103' name='L16' clockrate='16000' channels='2'/>
|
|
<payload-type id='98' name='x-ISAC' clockrate='8000'/>
|
|
</description>
|
|
<transport xmlns='urn:xmpp:jingle:transports:ice-udp:1'
|
|
pwd='asd88fgpdd777uzjYhagZg'
|
|
ufrag='8hhy'>
|
|
<candidate component='1'
|
|
foundation='1'
|
|
generation='0'
|
|
id='el0747fg11'
|
|
ip='10.0.1.1'
|
|
network='1'
|
|
port='8998'
|
|
priority='2130706431'
|
|
protocol='udp'
|
|
type='host'/>
|
|
<candidate component='1'
|
|
foundation='2'
|
|
generation='0'
|
|
id='y3s2b30v3r'
|
|
ip='192.0.2.3'
|
|
network='1'
|
|
port='45664'
|
|
priority='1694498815'
|
|
protocol='udp'
|
|
rel-addr='10.0.1.1'
|
|
rel-port='8998'
|
|
type='srflx'/>
|
|
</transport>
|
|
</content>
|
|
</jingle>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
<p>
|
|
<strong>Note:</strong> Example taken from <link url='http://xmpp.org/extensions/xep-0166.html#howitworks'>XEP 166: Jingle</link>.
|
|
</p>
|
|
<p>
|
|
<strong>Note2:</strong> Using Jingle in this way makes it possible for an intelligent server to return multiple streams the client
|
|
can choose from, something that is not done in normal HTTP over TCP. The first candidate should however correspond to the same stream
|
|
that would have been returned if the request had been made using normal HTTP over TCP.
|
|
</p>
|
|
</section3>
|
|
</section2>
|
|
<section2 topic='Applications'>
|
|
<p>
|
|
The following section lists use cases based on type of application. It is used to illustrate what types of applications would benefit from
|
|
implementing this extension.
|
|
</p>
|
|
<section3 topic='Browsers'>
|
|
<p>
|
|
HTTP began as a protocol for presenting text in browsers. So, browsers is a natural place to start to list use cases for this extensions.
|
|
In general, content is identified using URL's, and in the browser a user enters the URL into Address Field of the browser, and the corresponding
|
|
content is displayed in the display area. The content itself will probably contain links to other content, each such item identified
|
|
by an absolute or relative URL.
|
|
</p>
|
|
<section4 topic='httpx scheme' anchor='httpxscheme'>
|
|
<p>
|
|
The syntax and format of Uniform Resource Locators (URLs) or Uniform Resource Identifiers (URIs) is defined in &rfc3986;. The basic format is
|
|
defined as follows:
|
|
</p>
|
|
<example caption='URL syntax'>
|
|
<![CDATA[
|
|
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
|
|
|
|
hier-part = "//" authority path-abempty
|
|
/ path-absolute
|
|
/ path-rootless
|
|
/ path-empty]]>
|
|
</example>
|
|
<p>
|
|
&rfc2616; furthermore defines the format of URLs using the http URI scheme, as follows:
|
|
</p>
|
|
<example caption='HTTP (over TCP) URL syntax'>
|
|
<![CDATA[
|
|
http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]]]>
|
|
</example>
|
|
<p>
|
|
&rfc2818; continues to define the https scheme for HTTP transport over SSL/TLS over TCP using the same format as for HTTP URLs, except the
|
|
https scheme is used to inform the client that HTTP over SSL/TLS is to be used.
|
|
</p>
|
|
<p>
|
|
In a similar way, this document proposes a new URI scheme: <strong>httpx</strong>, based on the HTTP URL scheme, except
|
|
<strong>httpx</strong> URLs imply the use of HTTP over XMPP instead of HTTP over TCP. URLs using the <strong>httpx</strong>
|
|
URL scheme has the following format:
|
|
</p>
|
|
<example caption='HTTP over XMPP URL syntax'>
|
|
<![CDATA[
|
|
httpx_URL = "httpx:" "//" resourceless_jid [ abs_path [ "?" query ]]]]>
|
|
</example>
|
|
<p>
|
|
Here, the host and port parts of normal HTTP URLs have been replaced by the resource-less JID of the HTTP Server, i.e. only the user name,
|
|
the @ character and the domain. The / separator between the resource-less JID and the following abs_path, is part of abs_path.
|
|
</p>
|
|
<example caption='Examples of URLs with the httpx scheme'>
|
|
<![CDATA[
|
|
httpx://httpServer@example.org/index.html
|
|
httpx://httpServer@example.org/images/image1.png
|
|
httpx://httpServer@example.org/api?p1=a&p2=b]]>
|
|
</example>
|
|
<p>
|
|
By creating a new scheme for HTTP over XMPP transport, and implementing support for it in web browsers, XML HTTP request objects and web servers,
|
|
Web Applications previously requiring web hosting on the Internet will be able to be seamlessly hosted privately and securely behind firewalls instead,
|
|
by simply switching from the http URL scheme to the httpx URL scheme in the calling application. All relative URL's within the application, including
|
|
URL's sent to the XHR object (Ajax) will automatically be directed to use the HTTP over XMPP transport instead.
|
|
</p>
|
|
</section4>
|
|
<section4 topic='Friendship requests'>
|
|
<p>
|
|
It's beyond the scope of this specification to define how browsers handles its own XMPP account(s) and roster. This section only
|
|
makes a suggestion to show how this can be handled. It is assumed in this discussion that the browser has a working XMPP
|
|
connection with a server, and has its own JID. For simplicity, we will assume the browser has only one connection. Extension to
|
|
multiple connection is canonical.
|
|
</p>
|
|
<p>
|
|
When resolving an URL using the httpx scheme, the browser needs to extract the JID of the server hosting the resource. If that JID
|
|
is already in the roster, the request can proceed as usual.
|
|
</p>
|
|
<p>
|
|
If not in the roster, the browser needs to send a friendship request. A non-exhaustive list of states could be made:
|
|
</p>
|
|
<ul>
|
|
<li>No response: This could be presented as a connection to the content server being made.</li>
|
|
<li>Request rejected: This could be handled in the same way as HTTP Error Forbidden.</li>
|
|
<li>Request accepted: Connection made, proceed with fetching content.</li>
|
|
<li>Timeout: If no friendship request response have been returned, the browser can choose to time out.</li>
|
|
</ul>
|
|
<p>
|
|
Since XMPP works both ways, the browser can receive friendship requests from the outside world. Any such requests should be displayed to the
|
|
end user, if any, or rejected.
|
|
</p>
|
|
<p>
|
|
For more information, see <link url='#rosterclient'>Roster Handling in web clients</link> and
|
|
<link url='#rosterserver'>Roster Handling in web servers</link>.
|
|
</p>
|
|
</section4>
|
|
<section4 topic='Seamless use of web applications hosted at home'>
|
|
<p>
|
|
Today, most people who want to host their own web applications (HTML/HTTP based applications) need to host them on a server publicly
|
|
available on the Internet. However, many applications of a private nature like a family blog, home automation system, etc., is not
|
|
suited for public hosting, since it puts all private data at risk of being compromised, or access to home security functions (like
|
|
home web cams) to get in the hands of people you don't want to have access to them.
|
|
</p>
|
|
<p>
|
|
To solve this, one can host the application on a server at home, perhaps a small cheap plug computer consuming as little as 1 or 2 Watts
|
|
of electricity, using a web server supporting this extension. If the following design rules are followed, the application should be visible
|
|
in any browser also supporting this extensions, as long as friendship exists between the browser and the web server:
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
<p>
|
|
Only relative URL's are used within references (images, audio, video, links, objects, etc.). If absolute URL's are used (including scheme),
|
|
the browser might get the first page correctly, but will be unable to get the content with the absolute URL, unless the URL has the same scheme
|
|
as the principal page.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
URL's to web forms must also be relative, for the same reason.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Any URL's sent to the XML HTTP Request (XHR) Object directed to API's or resources hosted by the same application must also be relative,
|
|
for the same reasons as above. The XHR Object supports relative URL's.
|
|
</p>
|
|
</li>
|
|
</ul>
|
|
<p>
|
|
If the above rules are met, which they should under normal conditions, typing in the httpx URL in the browser (for instance when
|
|
you're at the office) should display the application (hosted for example at home behind a firewall) in the same way as when you use http
|
|
(or https) when you have access to the server (for instance when you're home), as long as friendship exists between the browser JID and
|
|
the server JID.
|
|
</p>
|
|
</section4>
|
|
</section3>
|
|
<section3 topic='Web Services'>
|
|
<p>
|
|
Many applications use a Service Oriented Architecture (SOA) and use web services to communicate between clients and servers. These web services
|
|
are mostly HTTP over TCP based, even though there are bindings which are not based on this. The most common APIs today (REST) are however all
|
|
based on HTTP over TCP. Being HTTP over TCP requires the web server hosting the web services either to be public or directly accessible by the
|
|
client. But as the services move closer to end users (for instance a Thermostat publishing a REST API for control in your home), problems arise
|
|
when you try to access the web service outside of private network in which the API is available. As explained previously, the use of HTTP over XMPP
|
|
solves this.
|
|
</p>
|
|
<section4 topic='SOAP'>
|
|
<p>
|
|
The following example shows a simple SOAP method call:
|
|
</p>
|
|
<example caption='SOAP method call'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.com'
|
|
id='15'>
|
|
<req xmlns='urn:xmpp:http' method='POST' resource='/Math' version='1.1'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>www.example.com</header>
|
|
<header name='Content-Type'>application/soap+xml; charset=utf-8</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<xml>
|
|
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
|
|
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
|
|
<soap:Body xmlns:m="http://www.example.org/math">
|
|
<m:AddNumbers>
|
|
<m:N1>10</m:N1>
|
|
<m:N2>20</m:N2>
|
|
</m:GetStockPrice>
|
|
</soap:Body>
|
|
</soap:Envelope>
|
|
</xml>
|
|
</data>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.com'
|
|
to='httpclient@example.org/browser'
|
|
id='15'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Content-Type'>application/soap+xml; charset=utf-8</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<xml>
|
|
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
|
|
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
|
|
<soap:Body xmlns:m="http://www.example.org/math">
|
|
<m:AddNumbersResponse>
|
|
<m:Sum>30</m:Sum>
|
|
</m:AddNumbersResponse>
|
|
</soap:Body>
|
|
</soap:Envelope>
|
|
</xml>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
<p>
|
|
<strong>Note:</strong> Other components of SOAP, such as WSDL and disco-documents are just examples of content
|
|
handled by simple <link url='#GET'>GET</link> requests.
|
|
</p>
|
|
</section4>
|
|
<section4 topic='REST'>
|
|
<p>
|
|
This section shows an example of a REST method call. REST method calls are just simple <link url='#GET'>GET</link>,
|
|
<link url='#POST'>POST</link>, <link url='#PUT'>PUT</link> or <link url='#DELETE'>DELETE</link> HTTP calls with
|
|
dynamically generated content.
|
|
</p>
|
|
<example caption='REST'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='16'>
|
|
<req xmlns='urn:xmpp:http' method='GET' resource='/api/multiplicationtable?m=5' version='1.1'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>example.org</header>
|
|
</headers>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='16'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 05 May 2013 15:01:53GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>text/xml</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<xml>
|
|
<table>
|
|
<value n='1' nTimesM='5'/>
|
|
<value n='2' nTimesM='10'/>
|
|
<value n='3' nTimesM='15'/>
|
|
<value n='4' nTimesM='20'/>
|
|
<value n='5' nTimesM='25'/>
|
|
<value n='6' nTimesM='30'/>
|
|
<value n='7' nTimesM='35'/>
|
|
<value n='8' nTimesM='40'/>
|
|
<value n='9' nTimesM='45'/>
|
|
<value n='10' nTimesM='50'/>
|
|
</table>
|
|
</xml>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section4>
|
|
</section3>
|
|
<section3 topic='Semantic Web & IoT'>
|
|
<p>
|
|
The Semantic Web was originally developed as a way to link data between servers on the Web, and understand it. However, with the advents
|
|
of technologies such as <link url='http://www.w3.org/TR/sparql11-query/'>SPARQL</link>, the Semantic Web has become a way to
|
|
unify API's into a universal form of distributed API to all types of data possible. It also allows for a standardized way to perform
|
|
grid computing, in the sense that queries can be federated and executed in a distributed fashion ("in the grid").
|
|
</p>
|
|
<p>
|
|
For these reasons, and others, semantic web technologies have been moving closer to Internet of Things, and also into the private spheres
|
|
of its end users. Since the semantic web technologies are based on HTTP, they also suffer from the shortcomings of HTTP over TCP, when it
|
|
comes to firewalls and user authentication and authorization. Allowing HTTP transport over XMPP greatly improves the reach of semantic
|
|
technologies beyond "The Internet" while at the same time improving security and controllability of the information.
|
|
</p>
|
|
<p>
|
|
As the semantic web moves closer to Internet of Things and the world of XMPP, it can benefit from work done with relation to the Internet of
|
|
Things, such as &xep0324;, which would give automatic control of who (or what) can communicate with whom (or what).
|
|
</p>
|
|
<section4 topic='Turtle'>
|
|
<p>
|
|
Turtle <note>
|
|
Turtle: Terse RDF Triple Language <<link url='http://www.w3.org/TR/turtle/'>http://www.w3.org/TR/turtle/</link>>
|
|
</note>, is a simple way to represent semantic data. The following example shows Turtle-encoded semantic data being returned
|
|
to the client as a response to a request.
|
|
</p>
|
|
<example caption='Turtle'>
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='2'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 16:39:54GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>text/turtle</header>
|
|
<header name='Content-Length'>...</header>
|
|
<header name='Connection'>Close</header>
|
|
</headers>
|
|
<data>
|
|
<text>@prefix dc: <http://purl.org/dc/elements/1.1/>.
|
|
@base <http://example.org/>.
|
|
|
|
<xep> dc:title "HTTP over XMPP";
|
|
dc:creator <PeterWaher>;
|
|
dc:publisher <XSF>.</text>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section4>
|
|
<section4 topic='RDF'>
|
|
<p>
|
|
RDF <note>
|
|
RDF: Resource Description Framework <<link url='http://www.w3.org/RDF/'>http://www.w3.org/RDF/</link>>
|
|
</note>, is a another way to represent semantic data, better suited than Turtle for M2M communication. Related technologies,
|
|
such as the micro format RDFa <note>
|
|
RDFa: RDF through attributes <<link url='http://www.w3.org/TR/rdfa-syntax/'>http://www.w3.org/TR/rdfa-syntax/</link>>
|
|
</note> allows for embedding RDF into HTML pages or XML documents. The following example shows RDF-encoded semantic data being returned
|
|
to the client as a response to a request.
|
|
</p>
|
|
<example caption='RDF'>
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='17'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 05 May 2013 16:02:23GMT-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>application/rdf+xml</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<xml>
|
|
<rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
|
<rdf:Description rdf:about="http://example.org/xep">
|
|
<dc:title>HTTP over XMPP</dc:title>
|
|
<dc:creator rdf:resource="http://example.org/PeterWaher" />
|
|
<dc:publisher rdf:resource="http://example.org/XSF" />
|
|
</rdf:Description>
|
|
</rdf:RDF>
|
|
</xml>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section4>
|
|
<section4 topic='SPARQL'>
|
|
<p>
|
|
This section shows an example of a SPARQL query executed as a POST call.
|
|
</p>
|
|
<example caption='SPARQL'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='4'>
|
|
<req xmlns='urn:xmpp:http' method='POST' version='1.1'
|
|
resource='/sparql/?default-graph-uri=http%3A%2F%2Fanother.example%2Fcalendar.rdf'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Host'>example.org</header>
|
|
<header name='User-agent'>Clayster HTTP/XMPP Client</header>
|
|
<header name='Content-Type'>application/sparql-query</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<text>@prefix dc: <http://purl.org/dc/elements/1.1/>.
|
|
@base <http://example.org/>.
|
|
|
|
<xep> dc:title "HTTP over XMPP";
|
|
dc:creator <PeterWaher>;
|
|
dc:publisher <XSF>.</text>
|
|
</data>
|
|
</req>
|
|
</iq>
|
|
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='4'>
|
|
<resp xmlns='urn:xmpp:http' version='1.1' statusCode='200' statusMessage='OK'>
|
|
<headers xmlns='http://jabber.org/protocol/shim'>
|
|
<header name='Date'>Fri, 03 May 2013 17:09:34-4</header>
|
|
<header name='Server'>Clayster</header>
|
|
<header name='Content-Type'>application/sparql-results+xml</header>
|
|
<header name='Content-Length'>...</header>
|
|
</headers>
|
|
<data>
|
|
<xml>
|
|
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
|
|
<head>
|
|
<variable name="title"/>
|
|
<variable name="creator"/>
|
|
</head>
|
|
<results>
|
|
<result>
|
|
<binding name="title">
|
|
<literal>HTTP over XMPP</literal>
|
|
</binding>
|
|
<binding name="creator">
|
|
<uri>http://example.org/PeterWaher</uri>
|
|
</binding>
|
|
</result>
|
|
</results>
|
|
</sparql>
|
|
</xml>
|
|
</data>
|
|
</resp>
|
|
</iq>]]>
|
|
</example>
|
|
</section4>
|
|
</section3>
|
|
<section3 topic='Streaming'>
|
|
<p>
|
|
There are many types of streams and streaming protocols. Several of these are based on HTTP or variants simulating HTTP. Examples of such HTTP-based or
|
|
pseudo-HTTP based streaming protocols can include HLS <note>
|
|
HLS: HTTP Live Streaming <<link url='http://en.wikipedia.org/wiki/HTTP_Live_Streaming'>http://en.wikipedia.org/wiki/HTTP_Live_Streaming</link>>
|
|
</note> used for multi-media streaming,
|
|
SHOUTcast <note>
|
|
SHOUTcast <<link url='http://en.wikipedia.org/wiki/SHOUTcast'>http://en.wikipedia.org/wiki/SHOUTcast</link>>
|
|
</note> used for internet radio and
|
|
Motion JPeg <note>
|
|
Motion JPeg <<link url='http://en.wikipedia.org/wiki/Motion_JPEG'>http://en.wikipedia.org/wiki/Motion_JPEG</link>>
|
|
</note> common format for web cameras.
|
|
</p>
|
|
<p>
|
|
Common for all streaming data, is that they are indefinite, but at the same time rate-limited depending on quality, etc. Because of this, the
|
|
web server is required to use the <link url='#streams'>ibb</link> encoding or the <link url='#jingle'>jingle</link> encoding to
|
|
transport the content to the client.
|
|
</p>
|
|
</section3>
|
|
</section2>
|
|
</section1>
|
|
<section1 topic='Determining Support' anchor='support'>
|
|
<p>If an entity supports the protocol specified herein, it MUST advertise that fact by returning a feature of "urn:xmpp:http" in response to &xep0030; information requests.</p>
|
|
<example caption="Service discovery information request">
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='httpclient@example.org/browser'
|
|
to='httpserver@example.org'
|
|
id='disco1'>
|
|
<query xmlns='http://jabber.org/protocol/disco#info'/>
|
|
</iq>]]>
|
|
</example>
|
|
<example caption="Service discovery information response">
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='httpserver@example.org'
|
|
to='httpclient@example.org/browser'
|
|
id='disco1'>
|
|
<query xmlns='http://jabber.org/protocol/disco#info'>
|
|
...
|
|
<feature var='urn:xmpp:http'/>
|
|
...
|
|
</query>
|
|
</iq>]]>
|
|
</example>
|
|
<p>
|
|
In order for an application to determine whether an entity supports this protocol, where possible it SHOULD use the dynamic, presence-based profile of service discovery defined
|
|
in &xep0115;. However, if an application has not received entity capabilities information from an entity, it SHOULD use explicit service discovery instead.
|
|
</p>
|
|
</section1>
|
|
<section1 topic='Implementation Notes' anchor='impl'>
|
|
<section2 topic='Connection handling' anchor='httpconnections'>
|
|
<p>
|
|
HTTP over TCP includes headers for connection handling. The basic sequence for an HTTP request might be:
|
|
</p>
|
|
<ul>
|
|
<li>Client connects to server</li>
|
|
<li>Clients sends request</li>
|
|
<li>Client received response</li>
|
|
<li>Client closes connection</li>
|
|
</ul>
|
|
<p>
|
|
However, in the HTTP over XMPP case, there are no connections between the client and the server. Both clients and servers
|
|
have active connections to the XMPP Server, but these remain unchanged during the sequence of requests. Therefore, both
|
|
clients and servers should ignore any HTTP over TCP connection settings, since they have no meaning in the HTTP over XMPP
|
|
case. However, the corresponding headers should always be transported as is, to maintain the information.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='HTTP Headers' anchor='headers'>
|
|
<p>
|
|
HTTP Headers are serialized to and from XML using the XEP-0131 <link url='http://xmpp.org/extensions/xep-0131.html'>Stanza Headers and Internet Metadata</link>.
|
|
However, this does not mean that the SHIM feature needs to be published by the client, as defined in §3 in
|
|
<link url='http://xmpp.org/extensions/xep-0131.html#disco'>XEP-0131</link>, since the headers will be embedded into the HTTP elements.
|
|
Also, if there is any conflicts in how to store header values, when it comes to data types, etc., the original format as used by the original
|
|
HTTP request must be used, and not the format defined in <link url='http://xmpp.org/extensions/xep-0131.html#headers'>Header Definitions</link> or
|
|
<link url='http://xmpp.org/extensions/xep-0131.html#dates'>A Note About date-Related Headers</link> in XEP-0131.
|
|
</p>
|
|
<p>
|
|
The HTTP over XMPP tunnel is just a tunnel of HTTP over XMPP, it does not know the semantic meaning of headers used in the transport. It does not know
|
|
if additional headers added by the myriad of custom applications using HTTP are actually HTTP-compliant. It just acts as a transport, returning the
|
|
sime kind of response (being deterministric) as if the original request was made through other means, for example over TCP. It does not add, remove or
|
|
change semantic meaning of keys and values, nor change the format of the corresponding values. Such changes will create uncountable problems very difficult
|
|
to detect and solve in a general case.
|
|
</p>
|
|
<p>
|
|
This specification differs from XEP-0131 in that this specification the headers are consumed by web servers and web clients (The XMPP client here only
|
|
being a "dumb" gateway), while in XEP-0131 the headers are consumed by the XMPP clients themselves, knowing XML and XML formats.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='Stanza Sizes'>
|
|
<p>
|
|
Some XMPP Servers may limit stanza sizes for various reasons. While this may work well for certain applications, like
|
|
Instant Messaging and Chat, implementors of HTTP over XMPP need to know that some server have such stanza size
|
|
restrictions. Therefore, an implementation should include configurable size limits, so chunking can be used instead
|
|
of sending large stanzas. Another limit could be when streaming should be used instead of chunking. This later limit
|
|
should be applied in particular on audio and video content.
|
|
</p>
|
|
<p>
|
|
The implementor should also consider to send large content in the form of files using file transfer, and large multi-media
|
|
content using Jingle.
|
|
</p>
|
|
<p>
|
|
<strong>Note:</strong> According to &rfc6120; there is a smallest allowed maximum stanza size that all XMPP servers must support.
|
|
According to §13.12.4 of that document, this limit is set to 10000 bytes including all characters from the opening < character
|
|
to the closing > character.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='Bandwidth Limitations'>
|
|
<p>
|
|
Some XMPP Servers may also have bandwidth resitrctions enforced. This to limit the possibility of Denial of Service attacks
|
|
or similar flooding of messages. Implementors of the HTTP over XMPP extensions must know however, that the bandwidth
|
|
limitations for instant messaging and chat may be completely different from that of normal web applications. In chatting,
|
|
a 1000 bytes/s limit is in most cases sufficient, while the same limit for even a modest web applications will make the
|
|
application completely impossible to use.
|
|
</p>
|
|
</section2>
|
|
</section1>
|
|
<section1 topic='Security Considerations' anchor='security'>
|
|
<p>
|
|
It's beyond the scope of this document to define how HTTP clients or HTTP servers handle rosters internally. The following
|
|
sections list suggestions on how these can be handled by different parties.
|
|
</p>
|
|
<section2 topic='Roster handling in browsers' anchor='rosterclient'>
|
|
<p>
|
|
Since browsers are operated by end users, any friendship request received from the outside should be either shown to the user
|
|
(if the browser also maintains an IM client), or automatically rejected.
|
|
</p>
|
|
<p>
|
|
On the other hand, when the browser wants to access an URL using the httpx scheme, an automatic friendship request to the
|
|
corresponding JID should be done, if not already in the roster. It is assumed that by entering the URL, or using the URL
|
|
of an application already displayed, this implies giving permission to add that JID as a friend to the roster of the
|
|
browser.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='Roster handling in web servers' anchor='rosterserver'>
|
|
<p>
|
|
A web server should have different security settings available. The following subsections list possible settings for different
|
|
scenarios. Note that these settings only reflect roster handling and cannot be set per resource. However, the server can
|
|
maintain a set of JIDs with different settings and restrict access to parts of the content hosted by the server per JID.
|
|
</p>
|
|
<section3 topic='Public Server'>
|
|
<p>
|
|
A public server should accept requests from anybody (reachable from the current JID). All friendship requests should be
|
|
automatically accepted.
|
|
</p>
|
|
<p>
|
|
To avoid bloating the roster, friendship requests could be automatically unsubscribed once the HTTP session has ended.
|
|
</p>
|
|
</section3>
|
|
<section3 topic='Manual Server'>
|
|
<p>
|
|
All new friendship are shown (or queued) to an administrator for manual acceptance or rejection. Once accepted, the client
|
|
can access the corresponding content. During the wait (which can be substantial), the client should display a message
|
|
that the friendship request is sent and response is pending.
|
|
</p>
|
|
<p>
|
|
Automatic unsubscription of friendships should only be done on a much longer inactivity timeframe than the normal session
|
|
timeout interval.
|
|
</p>
|
|
</section3>
|
|
<section3 topic='Private Server'>
|
|
<p>
|
|
All new friendship requests are automatically rejected. Only already accepted friendships are allowed to make HTTP requests
|
|
to the server.
|
|
</p>
|
|
</section3>
|
|
<section3 topic='Provisioned Server'>
|
|
<p>
|
|
All new friendship requests are delegated to a trusted third party, according to
|
|
<link url='http://xmpp.org/extensions/xep-0324.html'>XEP 0324: Internet of Things - Provisioning</link>. Friendship
|
|
acceptance or rejection is then performed according to the response from the provisioning server(s).
|
|
</p>
|
|
<p>
|
|
Automatic friendship unsubscription can be made to avoid bloating the roster. However, the time interval for unsubscribing
|
|
inactive users should be longer than the normal session timeout period, to avoid spamming any provisioning servers each
|
|
time a client requests friendship.
|
|
</p>
|
|
</section3>
|
|
</section2>
|
|
</section1>
|
|
<section1 topic='IANA Considerations' anchor='iana'>
|
|
<p>
|
|
The httpx URL scheme, as described <link url='#httpxscheme'>above</link>, must be registered as a provisional URI scheme according to BCP 35 <note>
|
|
BCP 35: New URI Schemes <<link url='http://tools.ietf.org/html/bcp35'>http://tools.ietf.org/html/bcp35</link>>
|
|
</note>. The registration procedure is specified in <link url='http://tools.ietf.org/html/bcp35#section-5.2'>BCP 35, section 5.2</link>.
|
|
</p>
|
|
<section2 topic='URI Scheme Registration Template'>
|
|
<p>
|
|
Following is an URI Scheme Registration Template, as per <link url='http://tools.ietf.org/html/bcp35#section-5.4'>BCP 35, section 5.4</link>.
|
|
</p>
|
|
<dl>
|
|
<di>
|
|
<dt>URI scheme name</dt>
|
|
<dd>
|
|
<p>
|
|
httpx
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Status</dt>
|
|
<dd>
|
|
<p>
|
|
provisional
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>URI scheme syntax</dt>
|
|
<dd>
|
|
<p>
|
|
The syntax used for the httpx scheme reuses the URI scheme syntax for the http scheme, as defined in RFC 2616:
|
|
</p>
|
|
<code>
|
|
<![CDATA[
|
|
http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]]]>
|
|
</code>
|
|
<p>
|
|
Instead of using host and port to define the where the HTTP server resides, the httpx scheme uses a resource-less
|
|
XMPP JID to define where the HTTP server resides, implying the use of HTTP over XMPP as defined in this document
|
|
instead of HTTP over TCP:
|
|
</p>
|
|
<code>
|
|
<![CDATA[
|
|
httpx_URL = "httpx:" "//" resourceless_jid [ abs_path [ "?" query ]]]]>
|
|
</code>
|
|
<p>
|
|
Here, the host and port parts of normal HTTP URLs have been replaced by the resource-less JID of the HTTP Server, i.e. only the user name,
|
|
the @ character and the domain. The / separator between the resource-less JID and the following abs_path, is part of abs_path.
|
|
</p>
|
|
<code>
|
|
<![CDATA[
|
|
httpx://httpServer@example.org/index.html
|
|
httpx://httpServer@example.org/images/image1.png
|
|
httpx://httpServer@example.org/api?p1=a&p2=b]]>
|
|
</code>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>URI scheme semantics</dt>
|
|
<dd>
|
|
<p>
|
|
By creating a new scheme for HTTP over XMPP transport, and implementing support for it in web browsers, XML HTTP request objects and web servers,
|
|
Web Applications previously requiring web hosting on the Internet will be able to be seamlessly hosted privately and securely behind firewalls instead,
|
|
by simply switching from the http URL scheme to the httpx URL scheme in the calling application. All relative URL's within the application, including
|
|
URL's sent to the XHR object (Ajax) will automatically be directed to use the HTTP over XMPP transport instead.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Encoding considerations</dt>
|
|
<dd>
|
|
<p>
|
|
Encoding is fully described in the
|
|
<link url='http://xmpp.org/extensions/xep-0332.html#encoding'>Encoding section of the HTTP over XMPP XEP</link> document.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Applications/protocols that use this URI scheme name</dt>
|
|
<dd>
|
|
<p>
|
|
This URI scheme is to be used in the same environments and by the same types of applications as the http URI scheme.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Interoperability considerations</dt>
|
|
<dd>
|
|
<p>
|
|
Interoperability considerations is described in the
|
|
<link url='http://xmpp.org/extensions/xep-0332.html#impl'>Implementation Notes section of the HTTP over XMPP XEP</link> document.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Security considerations</dt>
|
|
<dd>
|
|
<p>
|
|
Security considerations is described in the
|
|
<link url='http://xmpp.org/extensions/xep-0332.html#security'>Security considerations section of the HTTP over XMPP XEP</link> document.
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Contact</dt>
|
|
<dd>
|
|
<p>
|
|
For further information, please contact Peter Waher:
|
|
</p>
|
|
<p>
|
|
Email: <link url='mailto:peter.waher@example.org'>peter.waher@example.org</link><br/>
|
|
JabberID: <link url='xmpp:peter.waher@jabber.org'>peter.waher@jabber.org</link><br/>
|
|
URI: <link url='http://www.linkedin.com/in/peterwaher'>http://www.linkedin.com/in/peterwaher</link>
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Author/Change controller</dt>
|
|
<dd>
|
|
<p>
|
|
For concerns regarding changes to the provisional registration, please contact Peter Waher:
|
|
</p>
|
|
<p>
|
|
Email: <link url='mailto:peter.waher@example.org'>peter.waher@example.org</link><br/>
|
|
JabberID: <link url='xmpp:peter.waher@jabber.org'>peter.waher@jabber.org</link><br/>
|
|
URI: <link url='http://www.linkedin.com/in/peterwaher'>http://www.linkedin.com/in/peterwaher</link>
|
|
</p>
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>References</dt>
|
|
<dd>
|
|
<p>
|
|
Following is a short list of referenced documents:
|
|
</p>
|
|
<ol>
|
|
<li>
|
|
RFC 6120: <link url='http://tools.ietf.org/html/rfc6120'>
|
|
Extensible Messaging and Presence Protocol (XMPP): Core
|
|
</link>
|
|
</li>
|
|
<li>
|
|
RFC 2616: <link url='http://tools.ietf.org/html/rfc2616'>
|
|
Hypertext Transfer Protocol -- HTTP/1.1
|
|
</link>
|
|
</li>
|
|
<li>
|
|
HTTP over XMPP XEP: <link url='http://xmpp.org/extensions/xep-0332.html'>
|
|
XMPP Extension Protocol: HTTP over XMPP
|
|
</link>
|
|
</li>
|
|
</ol>
|
|
</dd>
|
|
</di>
|
|
</dl>
|
|
</section2>
|
|
</section1>
|
|
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
|
|
<p>
|
|
The <link url="#schema">protocol schema</link> needs to be added to the list of <link url="http://xmpp.org/resources/schemas/">XMPP protocol schemas</link>.
|
|
</p>
|
|
</section1>
|
|
<section1 topic='XML Schema' anchor='schema'>
|
|
<code>
|
|
<![CDATA[
|
|
<?xml version='1.0' encoding='UTF-8'?>
|
|
<xs:schema
|
|
xmlns:xs='http://www.w3.org/2001/XMLSchema'
|
|
targetNamespace='urn:xmpp:http'
|
|
xmlns='urn:xmpp:http'
|
|
xmlns:shim='http://jabber.org/protocol/shim'
|
|
xmlns:sipub='http://jabber.org/protocol/sipub'
|
|
xmlns:ibb='http://jabber.org/protocol/ibb'
|
|
xmlns:jingle='urn:xmpp:jingle:1'
|
|
elementFormDefault='qualified'>
|
|
|
|
<xs:import namespace='http://jabber.org/protocol/shim'/>
|
|
<xs:import namespace='http://jabber.org/protocol/sipub'/>
|
|
<xs:import namespace='http://jabber.org/protocol/ibb'/>
|
|
<xs:import namespace='urn:xmpp:jingle:1'/>
|
|
|
|
<xs:element name='req'>
|
|
<xs:complexType>
|
|
<xs:sequence>
|
|
<xs:element ref='shim:headers' minOccurs='0' maxOccurs='1'/>
|
|
<xs:element name='data' type='Data' minOccurs='0' maxOccurs='1'/>
|
|
</xs:sequence>
|
|
<xs:attribute name='method' type='Method' use='required'/>
|
|
<xs:attribute name='resource' type='xs:string' use='required'/>
|
|
<xs:attribute name='version' type='Version' use='required'/>
|
|
<xs:attribute name='maxChunkSize' type='MaxChunkSize' use='optional'/>
|
|
<xs:attribute name='sipub' type='xs:boolean' use='optional' default='true'/>
|
|
<xs:attribute name='ibb' type='xs:boolean' use='optional' default='true'/>
|
|
<xs:attribute name='jingle' type='xs:boolean' use='optional' default='true'/>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
|
|
<xs:simpleType name='MaxChunkSize'>
|
|
<xs:restriction base='xs:int'>
|
|
<xs:minInclusive value='256'/>
|
|
<xs:maxInclusive value='65536'/>
|
|
</xs:restriction>
|
|
</xs:simpleType>
|
|
|
|
<xs:element name='resp'>
|
|
<xs:complexType>
|
|
<xs:sequence>
|
|
<xs:element ref='shim:headers' minOccurs='0' maxOccurs='1'/>
|
|
<xs:element name='data' type='Data' minOccurs='0' maxOccurs='1'/>
|
|
</xs:sequence>
|
|
<xs:attribute name='version' type='Version' use='required'/>
|
|
<xs:attribute name='statusCode' type='xs:positiveInteger' use='required'/>
|
|
<xs:attribute name='statusMessage' type='xs:string' use='optional'/>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
|
|
<xs:complexType name='Data'>
|
|
<xs:choice minOccurs='1' maxOccurs='1'>
|
|
<xs:element name='text' type='xs:string'>
|
|
<xs:annotation>
|
|
<xs:documentation>Used for text responses that are not XML.</xs:documentation>
|
|
</xs:annotation>
|
|
</xs:element>
|
|
<xs:element name='xml'>
|
|
<xs:annotation>
|
|
<xs:documentation>Specifically used for XML-formatted responses.</xs:documentation>
|
|
</xs:annotation>
|
|
<xs:complexType>
|
|
<xs:sequence minOccurs='0' maxOccurs='1'>
|
|
<xs:any processContents="lax" namespace="##any"/>
|
|
</xs:sequence>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
<xs:element name="base64" type="xs:base64Binary">
|
|
<xs:annotation>
|
|
<xs:documentation>Short binary responses, base-64 encoded.</xs:documentation>
|
|
</xs:annotation>
|
|
</xs:element>
|
|
<xs:element name="chunkedBase64">
|
|
<xs:annotation>
|
|
<xs:documentation>Content is divided into chunks of binary base-64 encoded data.</xs:documentation>
|
|
<xs:documentation>Used if content is generated dynamically and/or content size is not known.</xs:documentation>
|
|
<xs:documentation>For streaming data the ibb:open or jingle:jingle transports must be used.</xs:documentation>
|
|
<xs:documentation>For static data, such as files, sipub:sipub should be used.</xs:documentation>
|
|
</xs:annotation>
|
|
<xs:complexType>
|
|
<xs:attribute name="streamId" type="xs:string" use="required"/>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
<xs:element ref='sipub:sipub'>
|
|
<xs:annotation>
|
|
<xs:documentation>Content available through file transfer.</xs:documentation>
|
|
</xs:annotation>
|
|
</xs:element>
|
|
<xs:element name="ibb">
|
|
<xs:annotation>
|
|
<xs:documentation>Content returned through an in-band bytestream.</xs:documentation>
|
|
</xs:annotation>
|
|
<xs:complexType>
|
|
<xs:attribute name="sid" type="xs:string" use="required"/>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
<xs:element ref="jingle:jingle">
|
|
<xs:annotation>
|
|
<xs:documentation>Multi-media content returned through jingle.</xs:documentation>
|
|
</xs:annotation>
|
|
</xs:element>
|
|
</xs:choice>
|
|
</xs:complexType>
|
|
|
|
<xs:element name="chunk">
|
|
<xs:complexType>
|
|
<xs:simpleContent>
|
|
<xs:extension base="xs:base64Binary">
|
|
<xs:attribute name="streamId" type="xs:string" use="required"/>
|
|
<xs:attribute name="nr" type="xs:nonNegativeInteger" use="required"/>
|
|
<xs:attribute name="last" type="xs:boolean" use="optional" default="false"/>
|
|
</xs:extension>
|
|
</xs:simpleContent>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
|
|
<xs:element name='close'>
|
|
<xs:complexType>
|
|
<xs:attribute name='streamId' type='xs:string' use='required'/>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
|
|
<xs:simpleType name='Method'>
|
|
<xs:restriction base='xs:string'>
|
|
<xs:enumeration value='OPTIONS'/>
|
|
<xs:enumeration value='GET'/>
|
|
<xs:enumeration value='HEAD'/>
|
|
<xs:enumeration value='POST'/>
|
|
<xs:enumeration value='PUT'/>
|
|
<xs:enumeration value='DELETE'/>
|
|
<xs:enumeration value='TRACE'/>
|
|
<xs:enumeration value='PATCH'/>
|
|
</xs:restriction>
|
|
</xs:simpleType>
|
|
|
|
<xs:simpleType name='Version'>
|
|
<xs:restriction base='xs:string'>
|
|
<xs:pattern value='\d[.]\d'/>
|
|
</xs:restriction>
|
|
</xs:simpleType>
|
|
|
|
</xs:schema>]]>
|
|
</code>
|
|
</section1>
|
|
<section1 topic='Acknowledgements' anchor='ack'>
|
|
<p>Thanks to Peter Saint-Andre, Karin Forsell, Matthew A. Miller, Kevin Smith and Ralph Meijer for all valuable feedback.</p>
|
|
</section1>
|
|
</xep>
|