A Path Annotation maps the URI of a RESTful web service to a Resource Function and provides for path templates.

1. Annotation 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.

2. Annotation Templates with Regular Expressions

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

3. Path Preference and Specificity

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 specifity

/person/elisabeth
/person/{$name}
/{$type}/elisabeth
/{$type}/{$name}
/person
/{$type}
TOP