A Path Annotation maps the URI of a RESTful web service to a Resource Function and provides for path templates.
Create Annotation Templates in the format {$my-var}
in a URI, these are mapped through to Function Parameters
with the same name. See the following example functions
declare
%rest:path("/say/hello/{$name}")
function say-hello($name as xs:string) {
<hello>{$name}</hello>
};
declare
%rest:path("/product/{$prod-id}/part/{$part-id}")
function part($prod-id as xs:integer, $part-id as xs:integer) {
fn:collection('product-' || $prod-id)/part[@id = $part-id]
};
A function will only be invoked if it's Path Annotation matches the actual Request Path.
Values extracted from Annotation Templates are automatically
converted
into the correct type for the function parameter.
All parameters which come from Annotation Templates must must be
single atomic types that inherit from
xs:anyAtomicType
, this includes xs:date
,
xs:dateTime
etc. If type conversion isn't possible
at runtime an exception will be thrown explaining this.
Normal Annotation Templates work on the principle that
a URI is neatly made into segments separated by the /
character.
You may wish to take a little more control, you may wish to only invoke a function if a URI segment matches a particular regular expression or you may wish to simply take total control over matching URIs with regular expressions
Consider the following Function which will only get
invoked if URI segments $a
and $b
both match
the regex [0-9]+
declare
%rest:path("/multiply/{$a=[0-9]+}/{$b=[0-9]+}")
function multiply($a as xs:integer, $b as xs:integer) as xs:integer {
$a * $b
};
The following example allows you take control of the very
end of the URI Path. of which it could include any amount of
/
characters.
declare
%rest:path("/control-suffix/{$a}/{$b=.+}")
function control-suffix($a as xs:string, $b as xs:string) as xs:string {
string-join(($a, $b), ',')
};
A request of /control-suffix/hello/aaa/bbb/ccc/ddd
against the above function, would return the result
hello,aaa/bbb/ccc/ddd
One needs to be careful with the Regular Expressions they write. Regular Expressions can be greedy in nature, gobbling up as many characters as they can. Consider the following example
declare
%rest:path("/greedy-regex/{$a=.+}/{$b=.+}")
function greedy($a as xs:string, $b as xs:string) as xs:string {
string-join(($a, $b), ',')
};
A request of /greedy-regex/aaa/bbb/ccc/ddd/eee
would return the result
aaa/bbb/ccc/ddd,eee
Sometimes, XQRS trying to select the function to invoke purely based on the Path Annotations alone can be ambiguous in which case there are rules defined by the RESTXQ Spec on how to deal with that.
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.
Path X is more specific than path Y if it has more segments.
/a/b is more specific than /a
If more than one Path has the same number of segments, the segments of the paths are compared from left to right.
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.
/a/b is more specific than /a/{$x}. /a/{$x} is more specific than /{$x}/y.
The following example contains six paths sorted by their specificity
/person/elisabeth /person/{$name} /{$type}/elisabeth /{$type}/{$name} /person /{$type}