1. Request "Content-Type" Header with %rest:consumes

RESTXQ Function selection can be constrained by the Content-Type header of a HTTP Request. This is managed by the %rest:consumes Annotation.

In the following example, the function xml-submitted can only ever be invoked if the client sent a Request with the Content-Type header set to text/xml, while the json-submitted function could only be invoked if the Request Content-Type header was set to application/json

declare
  %rest:path("/post-resource")
  %rest:consumes('text/xml')
function xml-submitted() {
  "Request Content-Type Header was set to text/xml"
};

declare
  %rest:path("/post-resource")
  %rest:consumes('application/json')
function json-submitted() {
  "Request Content-Type Header was set to application/json"
};

2. Request "Accept" Header with %rest:produces

RESTXQ Function selection can be constrained by the Accept header in a HTTP Request. This is managed by the %rest:produces Annotation.

declare
  %rest:path("/my-service")
  %rest:produces("application/json")
function json-response() {
  array-node { 1, 2, 3, 4 }
};

declare
  %rest:path("/my-service")
  %rest:produces("text/xml", "application/xml")
function xml-response() {
  <data>
    <item>1</item>
    <item>2</item>
    <item>3</item>
    <item>4</item>
  </data>
};

In the above example, the json-response function would be invoked if the Request Accept header contained application/json, while the xml-response function would be invoked if the Request Accept header contained either text/xml or application/xml.

NOTE

The %rest:produces annotation will not set the Content Type of the HTTP Response, to do this look at Controlling the HTTP Response or using the %output:media-type annotation in Controlling Output Serialization

2. Wildcards and Multiple Arguments

The %rest:consumes and %rest:produces annotations accept wildcards '*' as well as multiple arguments.

In the following example, the conventional-xml function could only be invoked if the Request Content-Type header was set to either text/xml OR application/xml.

declare
  %rest:path("/post-resource")
  %rest:consumes('text/xml', 'application/xml')
function conventional-xml() {
  "Retrieved an XML document"
};

The following 3 functions make use of wildcards.

declare
  %rest:path("/post-resource")
  %rest:consumes('text/*')
function text-resource() {
  "Any type of Text document."
};

declare
  %rest:path("/post-resource")
  %rest:consumes('*/xml')
function xml-resource() {
  "application/xml or text/xml."
};

declare
  %rest:path("/post-resource")
  %rest:consumes('*/*') (: not required :)
function anything-else() {
  "anything else"
};

The function text-resource could only ever be invoked if the Request Content-Type header started with text/ so text/plain text/html, text/css would all be acceptable.

The function xml-resource could only ever be invoked if the Request Content-Type header ended with /xml so application/xml and text/xml would both be acceptable.

Finally the function anything-else could only ever be invoked if neither the text-resource or xml-resource functions matched. In-fact, in this particular case the annotation statement %rest:consumes('*/*') is not required as this is the default behaviour for RESTXQ functions, this is just included here for demonstration purposes.

3. Media Type Preference

Sometimes function selection based on %rest:consumes or %rest:produces annotations alone can be ambiguous, in this case more specific media types have higher preference than less specific media types.

The following list shows media type expressions ordered by preference

application/xml
application/*
*/xml
*/*

4. Quality Factors in the "Accept" Header

HTTP Clients can send a Request with a set of media types in an Accept Header, where the client gives preference to certain types over others through Quality Factors.

Consider the following Accept Header sent by a client

Accept: */*;q=0.5,application/json;q=0.8,text/xml;q=1.0

In this case, the client would first and foremost prefer to receive the response in XML format (q=1.0), followed by JSON format (q=0.8) and if neither of those are available then it'll have anything else that's on offer.

XQRS takes these quality factors into consideration when choosing a suitable function to invoke.

Let's look at a previous example

declare
  %rest:path("/my-service")
  %rest:produces("application/json")
function json-response() {
  array-node { 1, 2, 3, 4 }
};

declare
  %rest:path("/my-service")
  %rest:produces("text/xml", "application/xml")
function xml-response() {
  <data>
    <item>1</item>
    <item>2</item>
    <item>3</item>
    <item>4</item>
  </data>
};

In this case, XQRS would choose the xml-response function as the client has stated they prefer this. However, if you were to remove the xml-response function from the XQuery code, XQRS would then choose the json-response function.

TOP