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.