Skip to content

Instantly share code, notes, and snippets.

@ChristianGruen
Created February 25, 2015 11:45
Show Gist options
  • Save ChristianGruen/1d7e52cd7865c5b99968 to your computer and use it in GitHub Desktop.
Save ChristianGruen/1d7e52cd7865c5b99968 to your computer and use it in GitHub Desktop.
RESTXQ 1.0, Next version
<!DOCTYPE html>
<html>
<head>
<title>RESTXQ 1.0: RESTful Annotations for XQuery</title>
<meta charset='utf-8'/>
<script src='http://www.w3.org/Tools/respec/respec-w3c-common' class='remove'></script>
<script class='remove'>
var respecConfig = {
// specification status (e.g. WD, LCWD, NOTE, etc.). If in doubt use ED.
specStatus: "unofficial",
// the specification's short name, as in http://www.w3.org/TR/short-name/
shortName: "restxq",
// if your specification has a subtitle that goes below the main
// formal title, define it here
subtitle : "An EXQuery Project",
// if you wish the publication date to be other than today, set this
// publishDate: "2009-08-06",
// if the specification's copyright date is a range of years, specify
// the start date here:
// copyrightStart: "2005"
// if there is a previously published draft, uncomment this and set its YYYY-MM-DD date
// and its maturity status
// previousPublishDate: "1977-03-15",
// previousMaturity: "WD",
// if there a publicly available Editor's Draft, this is the link
// edDraftURI: "http://dev.w3.org/2009/dap/ReSpec.js/documentation.html",
edDraftURI: "http://exquery.github.com/exquery/exquery-restxq-specification/restxq-1.0-specification.html",
// if this is a LCWD, uncomment and set the end of its review period
// lcEnd: "2009-08-05",
// editors, add as many as you like
// only "name" is required
editors: [
{ name: "Adam Retter", url: "http://adamretter.org.uk/",
company: "Evolved Binary", companyURL: "http://adamretter.org.uk/" }
],
// authors, add as many as you like.
// This is optional, uncomment if you have authors as well as editors.
// only "name" is required. Same format as editors.
authors: [
{ name: "Adam Retter", url: "http://adamretter.org.uk/",
company: "Evolved Binary", companyURL: "http://adamretter.org.uk/" },
{ name: "Christian Grün", url: "http://christian-gruen.de/",
company: "BaseX GmbH", companyURL: "http://basex.org/" }
],
// name of the WG
wg: "EXQuery RESTXQ WG",
// URI of the public WG page
wgURI: "http://exquery.org/restxq-wg",
// name (without the @w3c.org) of the public mailing to which comments are due
wgPublicList: "exquery-restxq",
// URI of the patent status for this WG, for Rec-track documents
// !!!! IMPORTANT !!!!
// This is important for Rec-track documents, do not copy a patent URI from a random
// document unless you know what you're doing. If in doubt ask your friendly neighbourhood
// Team Contact.
wgPatentURI: "",
// If specified, defines an array of alternate formats in which document is available (e.g., XML, Postscript). The format of the array is:
// alternateFormats:
doRDFa: "1.1",
};
</script>
<style>
<!--
div.exampleInner {
background-color: #D5DEE3;
border-top-width: 4px;
border-top-style: double;
border-top-color: lightGrey;
border-bottom-width: 4px;
border-bottom-style: double;
border-bottom-color: lightGrey;
padding: 4px;
margin: 0em;
}
code.function {
font-weight: bold;
}
code.return-type {
font-style: italic;
}
code.type {
font-style: italic;
}
span.explain {
font-family: sans-serif;
font-style: italic;
}
-->
</style>
</head>
<body>
<section id="sotd">
It is unclear yet whether this document will be submitted to the W3C, either
to the XQuery WG or as Community Group. For the time being it lives under the
<a href="http://exquery.org/" title="EXQuery: Extensions for EXQuery">EXQuery project</a>.
</section>
<section id='abstract'>
Whilst XQuery [[!XQUERY]] was originally envisaged and designed as a query language for XML,
it has been adopted by many as a language for application development. This specification
describes a set of XQuery Annotations [[!XQUERY-30]] and a small set of functions to enable XQuery
to provide RESTful services, thus enabling Web Application development in XQuery.
</section>
<section id="introduction">
<h2>Introduction</h2>
<p>
XQuery processors are now frequently provided as part of complete data application
processing platforms, which typically incorporate amongst others, XML Data storage
and Web serving capabilities.
</p>
<p>
XQuery has long been recognised as a good language for producing XHTML and HTML from
complex data queries, however XQuery is almost completely ignorant of the Web.
XQuery provides no native capabilities for either making Web requests or operating
as a server-side scripting language and processing Web requests.
</p>
<p>
As of XQuery 3.0, there is still no standard way to create Web Applications in XQuery.
Many vendors provide extensions to their XQuery implementations which allow users
to serve web requests using XQuery processing.
Whilst vendors have borrowed ideas from each other, there is no standard for Web capabilities
in XQuery, as such developers have to use proprietary extensions, which limits the portability
of their XQuery code, ultimately fragmenting the XQuery community, limiting re-use and reducing
peer-learning.
</p>
<p>
RESTXQ attempts to resolve these problem of interoperablility. RESTXQ defines a standard set of
vendor agnostic XQuery Annotations and functions for XQuery. When implemented by vendors,
these annotations provide a standard W3C XQuery compliant approach to delivering RESTful
Web Services from XQuery, whilst the functions provide user convenience for interacting with
implementations of RESTXQ.
</p>
<section id="goals">
<h3>Goals</h3>
<p>
The guiding goals for the RESTXQ specification are:
<dl>
<dt>Interoperability</dt>
<dd>
Only features that are already present in XQuery MUST be applied to create RESTXQ.
Any XQuery code that makes use of RESTXQ instead of vendor extensions, is valid XQuery
code, and therefore portable. Note that RESTXQ support is required in the XQuery
processor to execute resource functions in a Web context.
</dd>
<dt>Simplicity for XQuery developers</dt>
<dd>XQuery developers MUST NOT have to maintain external or complex code for wiring RESTful
services to XQuery functions. Developers should just write standard XQuery.
</dd>
<dt>Vendor Agnostic</dt>
<dd>RESTXQ MUST NOT assume anything about an implementation above what is defined in
XQuery. RESTXQ MUST be equally implementable by any vendor.
</dd>
<dt>Technical improvement</dt>
<dd>RESTXQ MUST improve on the current approaches, a comprehensive review was undertaken
<a href="http://www.adamretter.org.uk/papers/restful-xquery_january-2012.pdf" title="RESTful XQuery, Standardised XQuery Annotations for REST">here</a>.
</dd>
</dl>
</p>
</section>
<section id="audience">
<h3>Audience</h3>
<p>
This specification is intended for both vendors and developers looking to implement RESTXQ in
their products, XQuery developers looking to use the RESTXQ features defined in this specification,
and individuals wishing to establish the correctness of implementations with respect to the requirements
of this specification.
</p>
<p>
This document assumes that readers already have at least a basic understanding of XQuery, and
an understanding of Web technologies and server side scripting.
</p>
</section>
<section>
<h3>Namespaces and Prefixes</h3>
<p>
The annotations and functions discussed in this document are contained in
namespaces (see [[!XML-NAMES]]) and referenced using an xs:QName:
</p>
<ul>
<li><code>http://exquery.org/ns/restxq</code>, associated with <code>rest</code>.</li>
<li><code>http://www.w3.org/2010/xslt-xquery-serialization</code>, associated with <code>output</code>.</li>
<li><code>http://expath.org/ns/http-client</code>, associated with <code>http</code>.</li>
</ul>
<p>
The namespace prefix used for the functions, datatypes and errors can vary, as
long as the prefix is bound to the correct URI.
</p>
</section>
</section>
<section id="annotations">
<h2>Annotations</h2>
<section id="annotations-background">
<h3>Background</h3>
<p>
RESTXQ is heavily influenced by [[!JAX-RS]]. However, we simplify and deviate from JAX-RS
predominantly due to the language structure differences between Java and XQuery. Where JAX-RS describes Resource Classes
and Resources Methods for Java, in XQuery we simply use the term Resource Function; for mapping HTTP calls
to XQuery invocation, our unit of granularity is the XQuery function.
</p>
<p>
Through the use of annotations on functions in XQuery, we declaratively mark-up the HTTP capabilities
of a function. To minimise refactoring by developers when adding annotations to existing code, two measures
must be respected by implementations:
</p>
<ol>
<li>Implementations of RESTXQ MUST support annotated functions which have additional
function parameters which are not annotation mapped, providing the cardinality type
of those un-mapped parameters accepts an empty sequence.
</li>
<li>Implementors MUST not enforce the order of function parameters. Whether mapped
by annotations or not is unimportant, as annotations explicitly name the parameters
to which they are mapped.
</li>
</ol>
</section>
</section>
<section id="resource-functions">
<h3>Resource Functions</h3>
<p>
A Resource Function is an XQuery function which has been marked up with RESTXQ annotations.
These annotations indicate to a processor that when presented with a RESTful web service
request, that matches the constraints indicated by the annotations, that the function
SHOULD be invoked and the result SHOULD be returned as the result of the service request.
</p>
<p>There are two types of Resource Function Annotations described in RESTXQ:</p>
<ul>
<li>Constraints (<a href="#resource-function-constraints" class="sectionRef"></a>)</li>
<li>Parameters (<a href="#resource-function-parameters" class="sectionRef"></a>)</li>
</ul>
<section id="templates">
<h4>Templates</h4>
<p>
Some of the RESTXQ Annotations make use of Templates, which allow for the substitution of parameters
from the request into the query. The syntax of these templates is very simple and is designed to be
familiar to existing XQuery developers, it is expressed in <a href="#template-grammar" class="sectionRef"></a>.
</p>
<p>The Template appears inside a string literal within the annotation, but the meaning is that the
value of the templated substitution MUST be used as the parameter to the named argument of the
annotated function.</p>
<pre class="example highlight" title="Template">
{$number-of-cats}
</pre>
<p>
In the example above, a parameter given from the template substitution MUST be
set for the function argument called 'number-of-cats' on the annotated function.
</p>
</section>
<section id="resource-function-constraints">
<h4>Resource Function Constraints</h4>
<p>Constraints restrict the service requests that a Resource Function MAY process.</p>
<section id="path-annotation">
<h5>Path Annotation</h5>
<p>
A Path Annotation maps the URI of a RESTful web service to a Resource Function
and provides for path templates.
</p>
<p> <!-- TODO also consider allowing zero or more path annotations -->
A Resource Function MUST contain a single path annotation. Additional annotations
MAY be used to constrain or parameterize the Resource Function.
</p>
<p>
The path annotation is named <code>%rest:path</code> and takes a single
mandatory literal string, which describes the URI path for this service.
The URI path is considered relative to an implementation-defined base URI
(<a href="#base-uri" class="sectionRef"></a>).
</p>
<p>
The path string MAY start and end with an optional slash.
It MAY also contain zero or more URI templates which denote path
segments that MUST map to named function parameters. Parameters addressed by
templates in the URI path must meet the following constraints:
</p>
<ol>
<li>
<!-- TODO describe error codes -->
The cardinality MUST allow for an atomic value, otherwise an error should be raised by the
implementation, i.e., it must not be of type empty-sequence().</li>
<li>
<!-- TODO describe error codes -->
The type MUST inherit from xs:anyAtomicType, otherwise, an error should be raised by the implementation.
</li>
</ol>
<p>
<!-- TODO describe type conversion -->
Conversion from the URI segment string to the required type is performed
at run-time, and an error is raised if conversion is impossible.
</p>
<pre class="example highlight" title="Path Annotation">
declare
%rest:path("/stock/widget/{$id}")
function local:widget($id as xs:int) {
fn:collection("/db/widgets")//widget[@id = $id]
};
</pre>
<p>
In the above example, an HTTP GET on the following URI would cause the widget
with the <code>id</code> of '1981' to be retrieved:
<code>http://www.widget-factory.com/stock/widget/{$id}</code>.
</p>
<div class="note">
When many Resource Functions are defined, there can be many Path Annotations.
As such, conflicts may occur, the resolution of such conflicts MUST be processed
as described in <a href="#path-preference"></a>.
</div>
</section>
<section id="method-annotation">
<h5>Method Annotation</h5>
<p>
Resource Functions MAY be constrained to zero or more HTTP methods by means of
a method annotation. Unless otherwise constrained by a method annotation,
the path annotation of a Resource Function applies to all HTTP methods.
</p>
<p>
Annotations are defined for all HTTP 1.1 methods except TRACE and CONNECT.
All methods MAY return resources except for HEAD, which must only return a
<code>rest:response</code> element.
</p>
<pre class="example highlight" title="Method Annotation">
declare
%rest:DELETE
%rest:path("/widget/{$id}")
function local:widget($id as xs:int) {
delete node fn:collection("/db/widgets")//widget[@id = $id]
};
</pre>
<p>
The method annotations <code>POST</code> and <code>PUT</code> may take an
optional string literal which maps the HTTP request body to a named function
parameter. The same syntax as that used for URI templates is applied.
For example
<code>%rest:POST("{$request-body")</code> would inject the request body into
the function through the function parameter named 'request-body'. The
function parameter for the request body must meet the following constraints:
<ol>
<li>
The cardinality MUST allow for one or more of the typed item(s).
</li>
<li>
The type MUST be compatible with the request body. The type of the request
body is determined by the HTTP <code>Content-Type</code> header and may be
constrained by means of the <code>%rest:consumes</code> annotation. The
interpretation of the request body is similar to that of the
<a href="http://expath.org/spec/http-client">EXPath HTTP Client</a>:
<ol>
<li>
If the content type is textual, the function parameter type will be
<code>xs:string</code>.
</li>
<li>
If the content type is XML, the request body is parsed as XML and
the function parameter type will be <code>document-node()</code>.
</li>
<li>
Otherwise, a binary content type is assumed, and the function
parameter type will be <code>xs:base64Binary</code>.
</li>
<li>
An implementation MAY provide support for other input types
such as HTML or JSON.
</li>
</ol>
</li>
</ol>
</p>
</section>
<section id="consumes-annotation">
<h5>Consumes Annotation</h5>
<p>
Resource Functions MAY be constrained to certain content type by means of
a <code>%rest:consumes</code> annotation. A function will only be invoked
if the HTTP <code>Content-Type</code> header of the request matches one
of the given types.
</p>
</section>
<section id="produces-annotation">
<h5>Produces Annotation</h5>
<p>
If the <code>%rest:produces</code> annotation is specified, a function will
only be invoked if the HTTP <code>Accept</code> header of the request
matches one of the given types.
</p>
<pre class="example highlight" title="Consumes and Produces Annotation">
(: Will only be invoked if a user supplies the specified content types :)
declare
%rest:path("/widgets")
%rest:consumes("application/xml", "application/atom+xml")
%rest:produces("application/xml")
function local:widgets() {
fn:collection("/db/widgets")/widgets
};
</pre>
</section>
</section>
<section id="resource-function-parameters">
<h4>Resource Function Parameters</h4>
<p>
Parameters to Resource Functions are extracted from the RESTful Web Service
request and passed in as additional function parameters. Unlike constraints,
parameters are always optional. Resource Function Parameters use the same
URI template syntax as described in §4.3.1 to map the parameter onto a function
parameter. They must meet the following constraints:
<ol>
<li>
The cardinality MUST allow for zero or many atomic values in the case of
Query, Form or Header parameters, or zero or one atomic value in the
case of Cookie parameters, otherwise an error should be raised by the
implementation.
</li>
<li>
The type MUST inherit from xs:anyAtomicType, otherwise, an error should
be raised by the implementation.
</li>
</ol>
<p>
<!-- TODO describe type conversion -->
Conversion from the URI segment string to the required type is performed
at run-time, and an error is raised if conversion is impossible.
</p>
<p>
The annotations in this section MUST have two or more arguments:
<ol>
<li>The first argument represents the name of a parameter of the request.</li>
<li>The second argument contains the Resource Function Parameter.</li>
<li>The remaining arguments form the default value, which is assigned
if a parameter is not present in the request.</li>
</ol>
</p>
</p>
<section id="query-param-annotation">
<h5>Query Parameters</h5>
<p>
The annotation <code>%rest:query-param</code> is provided for accessing
parameters in the Query String of the URL used for the RESTful Web Service
request.
</p>
<pre class="example highlight" title="Query Parameter Annotation with a default value">
declare
%rest:GET
%rest:path("/widget/{$id}")
%rest:query-param("client", "{$client}", "unknown")
function local:widget($id as xs:int, $client as xs:string*) {
fn:collection("/db/widgets")//widget[@id = $id][@client = $client]
};
</pre>
</section>
<section id="form-param-annotation">
<h5>Form Parameters</h5>
<p>
The annotation <code>%rest:form-param</code> is provided for accessing
parameters from an HTML form submitted with the content type
<code>application/x-www-form-urlencoded</code>.
</p>
<pre class="example highlight" title="Form Parameter Annotation with a default value">
declare
%rest:GET
%rest:path("/widget/{$id}")
%rest:form-param("client", "{$client}", "unknown")
function local:widget($id as xs:int, $client as xs:string*) {
fn:collection("/db/widgets")//widget[@id = $id][@client = $client]
};
</pre>
</section>
<section id="form-header-annotation">
<h5>HTTP Header Parameters</h5>
<p>
The annotation <code>%rest:header-param</code> is provided for accessing
HTTP Request headers. If a single header field value contains comma separated
values, an implementation MUST extract each value from the comma separated
list into an item in the sequence provided to the function parameter.
</p>
<pre class="example highlight" title="Header Parameter Annotation">
declare
%rest:GET
%rest:path("/widget/{$id}")
%rest:header-param("X-Client-Type", "{$client-type}")
function local:widget($id as xs:int, $client-type as xs:string*) {
fn:collection("/db/widgets")//widget[@id = $id][@client-type = $client-type]
};
</pre>
</section>
<section id="form-cookie-annotation">
<h5>Cookie Parameters</h5>
<p>
The annotation <code>%rest:cookie-param</code> is provided for accessing
HTTP Cookies from the RESTful Web Service request.
</p>
<pre class="example highlight" title="Cookie Parameter Annotation">
declare
%rest:GET
%rest:path("/widget/{$id}")
%rest:header-param("X-Client-Type", "{$client-type}")
function local:widget($id as xs:int, $client-type as xs:string*) {
fn:collection("/db/widgets")//widget[@id = $id][@client-type = $client-type]
};
</pre>
</section>
</section>
<section id="resource-function-parameters">
<h4>Resource Function Parameters</h4>
<p>
Parameters to Resource Functions are extracted from the RESTful Web Service
request and passed in as additional function parameters. Unlike constraints,
parameters are always optional. Resource Function Parameters use the same
also make use of the <a href="#templates">template</a> syntax to map the parameter onto a function
parameter. They may also provide a default value should the parameter not be
present in the request. Resource Function Parameters always place the
following constraints on the function parameters that they map to:
<ol>
<li>
Cardinality that allows for zero or many atomic values in the case of
<a href="#query-param-annotation">Query</a>, <a href="#form-param-annotation">Form</a> or <a href="#header-param-annotation">Header</a> parameters, or zero or one atomic value in the
case of <a href="#cookie-param-annotation">Cookie</a> parameters, otherwise an error should be raised by the
implementation.
</li>
<li>
Type that inherits from <code>xs:anyAtomicType</code>, otherwise, an error should
be raised by the implementation. In addition, conversion from the
parameter string to the required type should be performed at run-time,
and an error raised if conversion is impossible.
</li>
</ol>
</p>
<section id="query-param-annotation">
<h5>Query Parameters</h5>
<p>
The annotation <code>%rest:query-param</code> is provided for accessing
parameters in the Query String of the URL.
</p>
<pre class="example highlight" title="Query Parameter Annotation with a default value">
declare
%rest:GET
%rest:path("/widget/{$id}")
%rest:query-param("client", "{$client}", "unknown")
function local:widget($id as xs:int, $client as xs:string*) {
fn:collection("/db/widgets")//widget[@id = $id][@client = $client]
};
</pre>
</section>
<section id="form-param-annotation">
<h5>Form Parameters</h5>
<p>
The annotation <code>%rest:form-param</code> is provided for accessing
parameters from an HTML form with content type
<code>application/x-www-form-urlencoded</code>.
</p>
<pre class="example highlight" title="Form Parameter Annotation with a default value">
declare
%rest:GET
%rest:path("/widget/{$id}")
%rest:form-param("client", "{$client}", "unknown")
function local:widget($id as xs:int, $client as xs:string*) {
fn:collection("/db/widgets")//widget[@id = $id][@client = $client]
};
</pre>
</section>
<section id="form-header-annotation">
<h5>HTTP Header Parameters</h5>
<p>
The annotation <code>%rest:header-param</code> is provided for accessing
HTTP Request headers. If a single Header field value contains comma separated
values, an implementation must extract each value from the comma separated
list into an item in the sequence provided to the function parameter.
</p>
<pre class="example highlight" title="Header Parameter Annotation">
declare
%rest:GET
%rest:path("/widget/{$id}")
%rest:header-param("X-Client-Type", "{$client-type}")
function local:widget($id as xs:int, $client-type as xs:string*) {
fn:collection("/db/widgets")//widget[@id = $id][@client-type = $client-type]
};
</pre>
</section>
<section id="form-cookie-annotation">
<h5>Cookie Parameters</h5>
<p>
The annotation <code>%rest:cookie-param</code> is provided for accessing
HTTP Cookies.
</p>
<pre class="example highlight" title="Cookie Parameter Annotation">
declare
%rest:GET
%rest:path("/widget/{$id}")
%rest:header-param("X-Client-Type", "{$client-type}")
function local:widget($id as xs:int, $client-type as xs:string*) {
fn:collection("/db/widgets")//widget[@id = $id][@client-type = $client-type]
};
</pre>
</section>
</section>
</section>
<section id="response">
<h2>Response</h2>
<section id="serialization">
<h3>Serialization</h3>
<p>
The results of a Resource Function may be serialized back to an HTTP
response for the RESTful web service response.
A Resource Function may return one of three response types:
<ol>
<li> A Resource, i.e. just content.</li>
<li> HTTP headers, for example acknowledging the request or providing a status
code or additional information.</li>
<li> Both HTTP Headers and a Resource</li>
</ol>
The XQuery Specification states in
<a href="http://www.w3.org/TR/xquery-30/#id-serialization">Section 2.2.4</a>
how the result of a query is serialized. Serialization may be controlled by
the use of Output Declarations. In RESTXQ, the following rules are applied:
<ol>
<li>
If the function is from within a Main Module, and if an output declaration
exists, then we use this as the default serialization settings for each
Resource Function in that module.
</li>
<li>
Output Declarations may be re-written as annotations on any Resource
Function, e.g. <code>%output:method("xml")</code>. These annotation output
declarations override any defaults from 1.
</li>
<li>
If no Output Declaration, annotated or otherwise, is provided, then the
default is to serialize as XML, UTF-8 encoding, with indenting.
</li>
</ol>
Each of the three possible result types of a Resource Function needs to be
handled in a different manner by an implementation, and as such we provide
appropriate function signature restrictions, and detail how annotations
interact with these:
<ol>
<li>
For a function that returns just a resource, either:
<ol>
<li>
If the result type is omitted from the function, it is assumed to be
<code>document-node(element())</code> or just <code>element()</code>,
and XML Serialization should be applied to the result of the function.
The annotation <code>%output:method</code>, if present,
MUST be set to <code>xml</code>.
</li>
<li>
If the result type is present, it MUST be a type which is compatible with
the chosen serialization method, defined by either the XQuery output
declaration or overridden by the <code>%output:method</code> annotation on
the Resource Function. The default serialization method is XML.
If the result type is not compatible with the serialization,
an implementation MUST throw an error.
</li>
</ol>
</li>
<li>
For a function that returns just HTTP headers, the result type of the function
MUST be defined as <code>document-node(element(rest:response))</code>.
Any other annotations that effect the serialization of the result are ignored.
</li>
<li>
For a function that returns both HTTP headers and a resource, the result type
of the function MUST be defined as <code>item()+</code>. The first item in the
result sequence is the HTTP headers i.e.
<code>document-node(element(rest:response)</code>, the second item in the
result sequence is the resource itself. The rules of both (1) and (2) MUST be
applied to the result sequence.
</li>
</ol>
</p>
</section>
<section id="response-format">
<h3>Response Format</h3>
<p>
A REST Response document may be returned from a function either with or without
a Resource. The purpose of this document is to control the REST (in this case HTTP)
response sent back to the client of the RESTful web service.
</p>
<pre class="highlight note" title="Syntax of Response Format">
&lt;rest:response&gt;
(http:response?)
&lt;/rest:response&gt;
&lt;http:response status?="integer" message?="string"&gt;
(http:header*)
&lt;/http:response&gt;
&lt;http:header name="string" value="string"/&gt;</pre>
<p>
Should the status be omitted for the response, or should a REST Response
document not be returned from a Resource Function, then the status defaults to
200 OK. It is expected that implementations will make use of sane defaults for
HTTP headers as part of their HTTP responses, however any default headers MUST
be overridable by the values set in the REST Response document.
</p>
<p>
As an example, the following response can be returned to trigger a
client-side redirection:
</p>
<pre class="example highlight" title="Client-Side Redirection">
&lt;rest:response&gt;
&lt;http:response status="302" message="Temporary Redirect"&gt;
&lt;http:header name="location" value="/new/location"/&gt;
&lt;/http:response&gt;
&lt;/rest:response&gt;</pre>
</section>
</section>
<section id="http-mechanics">
<h2>HTTP Mechanics</h2>
<p><!--TODO --></p>
<section id="base-uri">
<h3>Base URI</h3>
<p>
The base URI of a Resource Function is implementation-defined. That is to say
that an implementation is free to define either statically or dynamically the
URI part that appears before the relative URI of any Path Annotation
(<a href="#path-annotation" class="sectionRef"></a>).
<!-- TODO if a path annotation is not specified then the remaining URIs apply to the base uri -->
</p>
</section>
<section>
<h3>HTTP Request Matching</h3>
<p>
In many cases, there is more than one Resource Function that could service an
incoming HTTP Request. This chapter defines how the best matching Resource
Function is selected.
The specificity of a Resource Function is governed by the following rules,
which MUST be applied in order.
</p>
<section id="constraint-preference">
<h4>Constraint Preference</h4>
<p>
Resource Functions that impose the most specific constraints MUST first be
selected as candidates to process the HTTP Request.
</p>
<p>Most specific constraints first:</p>
<ol>
<!-- TODO break Content Type into Consumes and Produces? -->
<li>Path, Method, Content Type</li>
<li>Path, Method</li>
<li>Path, Content Type</li>
<li>Path</li>
<li>Method, Content Type</li>
<li>Method</li>
<li>Content Type</li>
</ol>
<pre class="example highlight" title="Constraint Specificity">
<span class="explain">The following Resource Function:</span>
declare function
%rest:GET
%rest:path("/a/b/c")
%rest:consumes("application/xml")
local:function-1() {
&lt;fn&gt;1&lt;/fn&gt;
};
<span class="explain">is more specific than:</span>
declare function
%rest:GET
%rest:path("/a/b/c")
local:function-2() {
&lt;fn&gt;2&lt;/fn&gt;
};
</pre>
</section>
<section id="path-preference">
<h4>Path Preference</h4>
<p>
More than one Path from a Resource Function Path Annotations MAY appear to
satisfy a request. Often, these can be disambiguated by specificity of
application to the HTTP Request URI. The most specific paths are selected
as candidates to process the HTTP Request.
</p>
<p>The rules determining Path specifity to a request are:</p>
<ol>
<li>Path Segment Length</li>
<p>
Path X is more specific than path Y if it has more segments.
</p>
<pre class="example" title="Path Length Specificity">
<code>/a/b</code> <span class="explain">is more specific than</span> <code>/a</code>.</pre>
<li>Path Selection</li>
<p>
If more than one Path has the same number of segments, the segments of the paths are
compared from left to right.
</p>
<p>
Path X is more specific than Path Y if the current segment of Y
is a template, while the respective segment of X is not.
</p>
<pre class="example" title="Path Selection Specificity">
<code>/a/b</code> <span class="explain">is more specific than</span> <code>/a/{$x}</code>.
<code>/a/{$x}</code> <span class="explain">is more specific than</span> <code>/{$x}/y</code>.</pre>
</ol>
<p>
The following example contains six paths sorted by their specifity:
</p>
<pre class="example" title="Path Specificity">
/person/elisabeth
/person/{$name}
/{$type}/elisabeth
/{$type}/{$name}
/person
/{$type}</pre>
</section>
<section id="media-type-preference">
<h4>Content Type Preference</h4>
<p>
More than one Content Type from Resource Function Consumes or Produces
Annotations MAY appear to satisfy a request. Often, these can be
disambiguated by specificity. The most specific content types MUST be
selected as candidates to process the HTTP Request.
</p>
<p>The rules determining content type specifity are:</p>
<ol>
<li>Absolute before Wildcard</li>
<p>Absolute Content Types are considered more specific than Content Types
with wildcard subtypes</p>
<pre class="example highlight" title="Content Type Specificity">
<code>application/xml</code> <span class="explain">is more specific than</span> <code>application/*</code>.
</pre>
</ol>
</section>
</section>
</section>
<section id="functions">
<h2>RESTXQ Function Module</h2>
<p>RESTXQ offers a few simple functions to assist with the construction of RESTful Web Services.</p>
<section>
<h3>Registry Functions</h3>
<p>Functions to assist in managing the RESTXQ Registry.</p>
<section>
<h4>rest:resource-functions()</h4>
<div class="exampleInner">
<pre><code class="function">rest:resource-functions</code>() as <code class="type">document-node(element(rest:resource-functions))</code></pre>
</div>
<p>
Summary: This function returns an XML document describing the Resource Functions registered
with the RESTXQ Registry.
</p>
<p>The XML document root element <code>rest:resource-functions</code> structure:</p>
<div class="exampleInner">
<pre>&lt;rest:resource-functions&gt;
rest:resource-function*
&lt;/rest:resource-functions&gt;</pre>
</div>
<p>The <code>rest:resource</code> XML element has the following structure:</p>
<div class="exampleInner">
<pre>&lt;rest:resource-function
xquery-uri = xs:anyURI&gt;
&lt;rest:identity
namespace = xs:anyURI
local-name = xs:NCName
arity = xs:int/&gt;
&lt;/rest:resource-function&gt;</pre>
</div>
</section>
</section>
<section>
<h3>URI Functions</h3>
<p>URI functions assist in the construction and selection of URIs.</p>
<section>
<h4>rest:base-uri()</h4>
<div class="exampleInner">
<pre><code class="function">rest:base-uri</code>() as <code class="type">xs:anyURI</code></pre>
</div>
<p>
Summary: This function returns the implementation-defined base URI
(<a href="#base-uri" class="sectionRef"></a>) of the Resource Function.
</p>
</section>
<section>
<h4>rest:uri()</h4>
<div class="exampleInner">
<pre><code class="function">rest:uri</code>() as <code class="type">xs:anyURI</code></pre>
</div>
<p>
Summary: This function is returns the complete URI that addresses the Resource Function. Typically
this is the <code>rest:base-uri()</code> appended with the path from the Path Annotation (if present) of the Resource Function.
</p>
</section>
</section>
</section>
<section class="appendix">
<h2>Resources for Implementers</h2>
<p>
If you plan to implement RESTXQ, there is already a set of common abstraction libraries written in Java
which should significantly reduce the ammount of effort involved and avoid re-inventing more wheels. You need
just implement a few interfaces and adapters. For more information see the
<a href="http://www.github.com/exquery/exquery" title="EXQuery GitHub">EXQuery GitHub page</a>.
</p>
</section>
<section class="appendix" id="template-grammar">
<h2>Annotation Template Grammar</h2>
<p>The grammar used for RESTXQ Templates is expressed in EBNF and re-uses the <a href="http://www.w3.org/TR/xquery-30/#prod-xquery30-EQName" title="EQName">EQName</a> from the XQuery grammar</p>
<table>
<tr>
<td>[1]</td>
<td>Template</td>
<td>::=</td>
<td>&quot;{&quot; &quot;$&quot; <a href="http://www.w3.org/TR/xquery-30/#prod-xquery30-EQName" title="EQName">EQName</a> &quot;}&quot;</td>
</tr>
</table>
</section>
<section class='appendix'>
<h2>Acknowledgements</h2>
<p>
Many thanks to:
<ul>
<li>Christian Grün for early adoption and enthusiasm.</li>
<li>Robin Berjon for making the production of this speficiation much simpler with his cool ReSpec tool.</li>
</ul>
</p>
</section>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment