Changes

Jump to navigation Jump to search
3,398 bytes added ,  19:42, 24 January 2017
HTTP responses.
Please note that BaseX provides various extensions to the official original draft of the specification:
* Multipart types are supported, including {{Code|multipart/form-data}}
* Quality factors in the [[#Content Negotiation|Accept header]] will be evaluated
* <code>%input</code> annotations, support for input-specific content-type parameters
* <code>%rest:single</code> annotation to cancel running RESTXQ functions
<br />
=Introduction=
 
==Preliminaries==
The RESTXQ service is accessible via {{Code|http://localhost:8984/}}.
All RESTXQ [[XQuery 3.0#Annotations|annotations]] are assigned to the {{Code|<code><nowiki>http://exquery.org/ns/restxq</nowiki>}} </code> namespace, which is statically bound to the {{Code|rest}} prefix. A ''Resource Function'' is an XQuery function that has been marked up with RESTXQ annotations. When an HTTP request comes in, a resource function will be invoked that matches the constraints indicated by its annotations. If a RESTXQ URL is requested, the [[Options#RESTXQPATH|RESTXQPATH]] module directory and its sub-directories will be traversed, and all [[XQuery Extensions#Suffixes|XQuery files]] will be parsed for functions with RESTXQ annotations. Sub-directories that include an {{Code|.ignore}} file will be skipped. To speed up processing, the functions of the existing XQuery modules are automatically cached in main memory. Functions will be invalidated and parsed again if the timestamp of their module changes. {{Mark|Updated with Version 8.6:}}
Whenever a * RESTXQ URL is requested, file monitoring has been improved and can be adjusted via the new [[Options#RESTXQPATHPARSERESTXQ|RESTXQPATHPARSERESTXQ]] option. In productive environments with a high load, it may be recommendable to change the timeout, or completely disable monitoring. If files are replaced while the web server is running, the RESTXQ module directory and its sub-directories will cache should be parsed for functions with RESTXQ annotations in library modules (detected explicitly invalidated by calling the extension static root path {{Code|/.xqminit}}) and main modules (detected or by {{Codecalling the [[RESTXQ Module#rest:init|rest:init]] function.xq}}* Authentication was readded to RESTXQ (see [[Web Application]] for more details). In main expressions, the main module will never be evaluated. All modules will be cached and parsed again when their timestamp changes. ==Examples==
A first RESTXQ function is shown below:
%rest:form-param("message","{$message}", "(no message)")
%rest:header-param("User-Agent", "{$agent}")
function page:hello-postman( $message as xs:string, $agent as xs:string*) as element(response){
&lt;response type='form'&gt;
&lt;message&gt;{ $message }&lt;/message&gt;
</pre>
=RequestsRequest=
This section shows how annotations are used to handle and process HTTP requests.
The body of a POST or PUT request will be converted to an XQuery item. Conversion can be
controlled by specifying a content type. Since {{Version|8.1}}, it It can be further influenced
by specifying additional content-type parameters:
| {{Code|application/json}}
| [[JSON Module#Options|JSON Options]]
| {{Code|document-node()}} or {{Code|map(*)}}
|-
| {{Code|text/html}}
| {{Code|text/comma-separated-values}}
| [[CSV Module#Options|CSV Options]]
| {{Code|document-node()}} or {{Code|map(*)}}
|-
| ''others''
===Input options===
Since {{Version|8.1}}, conversion Conversion options for [[Options#JSONPARSER|JSON]], [[Options#CSVPARSER|CSV ]] and [[Options#HTMLPARSER|HTML ]] can also be specified via annotations using with the <code>input</code> prefix. The following function interprets the input as text with the CP1252 encoding and treats the first line of the textual input as CSV header:
<pre class="brush:xquery">
%rest:path("/store.csv")
%rest:POST("{$csv}")
%input:csv("header=true,encoding=CP1252") function page:store-csv($csv as document-node()){
"Number of rows: " || count($csv/csv/record)
};
%rest:POST("{$data}")
%rest:consumes("multipart/mixed") (: optional :)
function page:multipart($data as item()*){
"Number of items: " || count($data)
};
%rest:query-param("id", "{$id}")
%rest:query-param("add", "{$add}", 42, 43, 44)
function page:params($id as xs:string?, $add as xs:integer+){
<result id="{ $id }" sum="{ sum($add) }"/>
};
%rest:path("/upload")
%rest:form-param("files", "{$files}")
function page:upload($files){
for $name in map:keys($files)
let $content := $files($name)
%rest:cookie-param("authentication", "{$auth}", "no_auth")
</pre>
 
==Query Execution==
 
In many RESTXQ search scenarios, input from browser forms is processed and search results are returned. User experience can generally be made more interactive if an updated search request is triggered with each key click. However, this may lead to many expensive parallel requests, from which only the result of the last request will be relevant for the client.
 
With the <code>%rest:single</code> annotation, it can be enforced that only one instance of a function will be executed for the same client. If the same function will be called for the second time, the already running query will be stopped, and the HTTP error code {{Code|410}} (Gone) will be returned instead:
 
<pre class="brush:xquery">
(: If fast enough, returns the result. Otherwise, if called again, raises 410 :)
declare
%rest:path("/search")
%rest:query-param("term", "{$term}")
%rest:single
function page:search($term as xs:string) {
<ul>{
for $result in db:open('large-db')//*[text() = $term]
return <li>{ $result }</li>
}</ul>
};
</pre>
 
By specifying a string along with the annotation, functions can be bundled together, and one request can be canceled by calling another one.
 
This is shown by another example, in which the first function can be interrupted by the second one. If you call both functions in separate browser tabs, you will note that the first tab will return <code>410</code>, and the second one will return <xml>stopped</xml>.
 
<pre class="brush:xquery">
declare
%rest:path("/compute")
%rest:single("EXPENSIVE")
function local:compute() {
(1 to 100000000000000)[. = 0]
};
 
declare
%rest:path("/stop")
%rest:single("EXPENSIVE")
function local:stop() {
<xml>stopped</xml>
};
</pre>
 
The following things should be noted:
 
* If a query will be canceled, there will be no undesirable side-effects. For example, it won’t be possible to kill a query if it is currenly updating the database or perfoming any other I/O operations. As a result, the termination of a running query can take some more time as expected.
* The currently executed function is bound to the current session. This way, a client will not be able to cancel requests from other clients. As a result, functions can only be stopped if there was at least one previous successful response, in which initial session data was returned to the client.
=Response=
===rest:redirect===
 
The function <code>[[Web Module#web:redirect|web:redirect]]</code> can be used to create a redirect response element. Alternatively, the following element can be sent:
<pre class="brush:xml"><rest:redirect>{ $location }</rest:redirect></pre>
…is basically It is an abbreviation for…for:
<pre class="brush:xml">
<rest:response>
<http:response status="302" message="Temporary Redirect">
<http:header name="location" value="{ $location }"/>
</http:response>
==Output==
Similar to The content-type of a response can be influenced by the user via [[REST#Content TypeSerialization|RESTSerialization Parameters]] interface, result serialization can be modified via . The steps are described in the [[XQuery 3.0REST#SerializationContent Type|XQuery 3.0 serialization parametersREST]]chapter. In RESTXQ, serialization parameters may can be specified in the query prolog, via annotations, or within the REST response element. Global parameters are overwritten by more local parameters.:
===Query Prolog===
===Annotations===
The Global serialization parameters can also be parameterized overwritten via <code>%output</code> annotations. The following example serializes XML nodes as JSON, using the [[JSON Module|JsonML]] format:
<pre class="brush:xquery">
%output:method("json")
%output:json("format=jsonml")
function page:cities(){
element cities {
db:open('factbook')//city/name
<pre class="brush:xquery">
declare
%rest:path("done")
%output:method("xhtml")
%output:omit-xml-declaration("no")
%output:doctype-public("-//W3C//DTD XHTML 1.0 Transitional//EN")
%output:doctype-system("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd")
function page:html(){
<html xmlns="http://www.w3.org/1999/xhtml">
<body>done</body>
===Response Element===
The following example demonstrates how serialization Serialization parameters can also be dynamically set within specified in a REST reponse element in a query. Serialization parameters will be overwritten:
<pre class="brush:xquery">
};
</pre>
 
The content type can also be overwritten by specifying an output {{Code|method}}. The following method mappings are available:
 
* <code>xml</code> → <code>application/xml</code>
* <code>xhtml</code> → <code>text/html</code>
* <code>html</code> → <code>text/html</code>
* <code>text</code> → <code>text/plain</code>
* <code>json</code> → <code>application/json</code>
* <code>raw</code> → <code>application/octet-stream</code>
 
When using <code>raw</code>, binary data will be sent in its original byte representation, i. e., without further conversion.
=Error Handling=
{| class="wikitable"
|- valign="top"
! PriorityPrecedence
! Syntax
! Example
|}
All error codes that are specified for a function must be of have the same priorityprecedence.
The following rules apply when catching errors:
* Codes with a higher priority precedence (smaller number) will be preferredgiven preference.
* A global RESTXQ error will be raised if two functions with conflicting codes are found.
declare
%rest:path("/check/{$user}")
function page:check($user){
if($user = ('jack', 'lisa'))
then 'User exists'
%rest:error("err:user")
%rest:error-param("description", "{$user}")
function page:user-error($user){
'User "' || $user || '" is unknown'
};
</pre>
 
An XQuery error in a RESTXQ context delivers by default a HTTP status code 400 error back to the client. However, you can also define a custom error code by using the third argument of the error function:
 
<pre class="brush:xquery">
declare
%rest:path("/teapot")
function page:teapot() {
fn:error(xs:QName('error'), "I'm a teapot", 418)
};
</pre>
=References=
RESTXQ has been proposed by [http://www.adamretter.org.uk/ Adam Retter].More information on all specifics can be found in the following two documentsDocumentation:
* [http://exquery.org/spec/restxq RESTXQ Specification], First Draft
* [http://www.adamretter.org.uk/papers/restful-xquery_january-2012.pdf RESTful XQuery, Standardised XQuery 3.0 Annotations for REST]. Paper, XMLPrague, 2012
* [http://www.adamretter.org.uk/presentations/restxq_mugl_20120308.pdf RESTXQ]. Slides, MarkLogic User Group London, 2012
* [http://files.basex.org/xmlprague2013publications/slidesxmlprague/2013/Develop-RESTXQ-WebApps-with-BaseX.pdf Web Application, RESTXQ Development]. Web Application Development with RESTXQ Slides from XMLPrague 2013 Examples: * Sample code combining XQuery and JavaScript: [http://balisage.net/Proceedings/vol17/author-pkg/Galtman01/BalisageVol17-Galtman01.html Materials] and [http://balisage.net/Proceedings/vol17/html/Galtman01/BalisageVol17-Galtman01.html paper] from Amanda Galtman, Balisage 2016.* [[DBA]]: The Database Administration interface, bundled with the full distributions of BaseX.
=Changelog=
 
;Version 8.4
 
* Added: <code>%rest:single</code> annotation
;Version 8.1
* Added: new XML elements {{Code|<rest:redirect/>}} and {{Code|<rest:forward/>}}
 
[[Category:HTTP]]
[[Category:Developer]]
Bureaucrats, editor, reviewer, Administrators
13,550

edits

Navigation menu