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"
};
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.
%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 SerializationThe %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.
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 */*
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.