Difference between revisions of "RESTXQ"

From BaseX Documentation
Jump to navigation Jump to search
Line 86: Line 86:
 
<pre class="brush:xquery">
 
<pre class="brush:xquery">
 
declare %rest:path("/a/path/{$with}/some/{$variable}")
 
declare %rest:path("/a/path/{$with}/some/{$variable}")
   function local:test($with, $variable as xs:integer) { ... };
+
   function page:test($with, $variable as xs:integer) { ... };
 
</pre>
 
</pre>
 
<!-- TODO how matching works -->
 
<!-- TODO how matching works -->
Line 98: Line 98:
 
<pre class="brush:xquery">
 
<pre class="brush:xquery">
 
declare %rest:GET %rest:POST %rest:path("")
 
declare %rest:GET %rest:POST %rest:path("")
   function local:root() { <html/> };
+
   function page:root() { <html/> };
 
</pre>
 
</pre>
  
Line 105: Line 105:
 
<pre class="brush:xquery">
 
<pre class="brush:xquery">
 
declare %rest:PUT("{$data}") %rest:path("")
 
declare %rest:PUT("{$data}") %rest:path("")
   function local:put($data) { "Data: " || $data };
+
   function page:put($data) { "Data: " || $data };
 
</pre>
 
</pre>
  
===Content Types===
+
===Content Negotiation===
  
* '''HTTP Content Types''': One or more media-types may be specified as strings, e.g.:<br/>
+
Two additional annotations can be used to restrict functions to specific content types:
 +
 
 +
* '''HTTP Content Types''': a function will only be invoked if the HTTP {{Mono|Content-Type}} header of the request matches one of the given mime types. Example:
 
<pre class="brush:xquery">%rest:consumes("application/xml", "text/xml")</pre>
 
<pre class="brush:xquery">%rest:consumes("application/xml", "text/xml")</pre>
* '''HTTP Accept''': One or more media-types may be specified as strings, e.g.:<br/>
+
* '''HTTP Accept''': a function will only be invoked if the HTTP {{Mono|Accept}} header of the request matches one of the defined mime types. Example:
 
<pre class="brush:xquery">%rest:produces("application/atom+xml")</pre>
 
<pre class="brush:xquery">%rest:produces("application/atom+xml")</pre>
  
These default to <code>*/*</code> if no media-type annotations are given.
+
By default, both mime types are {{Mono|*/*}}.
  
 
==Parameters==
 
==Parameters==
Line 155: Line 157:
 
%rest:cookie-param("username","{$user}")
 
%rest:cookie-param("username","{$user}")
 
%rest:cookie-param("authentication","{$auth}", "no_auth")
 
%rest:cookie-param("authentication","{$auth}", "no_auth")
 +
</pre>
 +
 +
==Output==
 +
 +
By default, all results will be returned with content type {{Mono|application/xml}}.
 +
Similar to our [[REST#Content Type|REST]] interface, result serialization can be modified via [[XQuery 3.0#Serialization|XQuery 3.0 serialization parameters]]. In RESTXQ, all parameters are specified within annotations.
 +
 +
The content type can be overwritten with the {{Mono|media-type}} annotation:
 +
 +
<pre class="brush:xquery">
 +
declare %output:media-type("text/plain") %rest:path("")
 +
  function page:kiss() { 'keep it simple, stupid' };
 +
</pre>
 +
 +
Next, the content type can also be overwritten by specifying an output {{Mono|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>raw</code> → <code>application/octet-stream</code>
 +
#* <code>json</code> or <code>jsonml</code> → <code>application/json</code>
 +
 +
The following example will use {{Mono|text/html}} as content type:
 +
 +
<pre class="brush:xquery">
 +
declare
 +
  %rest:path("")
 +
  %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:start() {
 +
 +
<html xmlns="http://www.w3.org/1999/xhtml">
 +
  <body>done</body>
 +
</html>
 +
};
 
</pre>
 
</pre>
  

Revision as of 01:26, 14 May 2012

This page is part of the Developer Section. It describes how to use the RESTXQ API of BaseX.

RESTXQ, introduced by Adam Retter, is a new API that facilitates the use of XQuery as a Server Side processing language for the Web. RESTXQ has been inspired by Java’s JAX-RS API: it defines a pre-defined set of XQuery 3.0 annotations for mapping HTTP requests to XQuery functions, which in turn generate and return HTTP responses.

As of Version 7.2, RESTXQ is supported by BaseX. Note that various details of the specification may be subject to change due to the early state of the API.

Getting started

First of all, launch the BaseX as Web Application. By default, Jetty is used as web server. All HTTP services will be available on port 8984, and the RESTXQ service is accessible at http://localhost:8984/restxq/. If the server is started as servlet, all Main Options (such as the path to the database) can be configured in the web.xml file. If run as a standalone application, the settings are stored in the file .basex.

Module Declarations

A RESTXQ module needs to contain a declaration to the namespace http://exquery.org/ns/restxq. A Resource Function is an XQuery function that has been marked up with RESTXQ annotations (annotations will be introduced with the upcoming XQuery 3.0 standard). When an HTTP request comes in, a resource function will be invoked that matches the constraints indicated by its annotations.

All files with extension *.xqm, placed inside the directory specified by HTTPPATH (refer to HTTP Server Configuration) will be treated as RESTXQ modules. These will be parsed for RESTXQ annotations and cached. If a module is modified, it will be parsed again at runtime.

A simple RESTXQ module is shown below, it is part of a clean installation and available at http://localhost:8984/restxq/ .

(:~ simplified module as in http/restxq.xqm :)
module namespace page = 'http://basex.org/modules/web-page';
declare namespace rest = 'http://exquery.org/ns/restxq';

declare %rest:path("hello/{$world}")
        %rest:GET
        %rest:header-param("User-Agent", "{$agent}")
        function page:hello($world as xs:string, $agent as xs:string*) {
  <response>
    <title>Hello { $world }!</title>
    <info>You requested this page with { $agent }.</info>
  </response>
};

If the URI http://localhost:8984/restxq/hello/world is accessed, the result will be kind of

<response>
	<title>Hello world!</title>
	<info>You requested this page with Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13.</info>
</response>

We added another method within that module:

declare %rest:path("form/")
        %rest:POST
        %rest:form-param("content","{$message}", "'no message delivered'")
        function page:hello-postman($message as xs:string) {
  <response>
    <title>Hello!</title>
    <info>It seems you posted a message: { $message }</info>
  </response>
};

If you posted something (e.g. using curl or the embedded form at http://localhost:8984/restxq/ )

curl -i -X POST --data "content='Here comes the post'" http://admin:admin@localhost:8984/restxq/form

You would recieve

<response>
  <title>Hello!</title>
  <info>It seems you posted a message: 'Here comes the post'</info>
</response>

Annotations

This section lists all annotations provided by RESTXQ. rest is used as namespace prefix.

Constraints

Constraints restrict the HTTP requests that a resource function may process.

Paths

A resource function must have a single Path Annotation. It will be called if a URL matches the path segments and templates specified as argument. Path templates contain variables in curly brackets, and map the values of the actual request path to the function arguments.

The following example contains a path annotation with three segments and two templates. One of the function arguments is further specified with a data type, which means that the value for $variable will be cast to an xs:integer before being bound:

declare %rest:path("/a/path/{$with}/some/{$variable}")
  function page:test($with, $variable as xs:integer) { ... };

HTTP Methods

The HTTP method annotations are equivalent to all HTTP request methods except for TRACE and CONNECT. Zero or more methods may be used on a function; if none is specified, the function will be invoked for each method.

The following function will be called if GET or POST is used as request method:

declare %rest:GET %rest:POST %rest:path("")
  function page:root() { <html/> };

The POST and PUT annotations may optionally take a string literal, which will be mapped to a named function parameter. Once again, the target variable must be embraced by curly brackets:

declare %rest:PUT("{$data}") %rest:path("")
  function page:put($data) { "Data: " || $data };

Content Negotiation

Two additional annotations can be used to restrict functions to specific content types:

  • HTTP Content Types: a function will only be invoked if the HTTP Content-Type header of the request matches one of the given mime types. Example:
%rest:consumes("application/xml", "text/xml")
  • HTTP Accept: a function will only be invoked if the HTTP Accept header of the request matches one of the defined mime types. Example:
%rest:produces("application/atom+xml")

By default, both mime types are */*.

Parameters

Parameters are optional annotations that can be used to bind additional values to function arguments:

Query Strings

The value of the first parameter, if found in the Query String, will be assigned to the variable specified as second parameter. Optionally, a third parameter may be specified as default:

%rest:query-param("parameter", "{$value}", "default")
%rest:query-param("answer", "{$answer}", 42, 43, 44)
%rest:query-param("search", "{$search-param}")

HTML Form Fields

Form parameters are specified the same way as query strings. Their values are extracted from GET or POST requests.

%rest:form-param("parameter", "{$value}", "default")

HTTP Headers

Header parameters are specified the same way as query strings:

%rest:header-param("User-Agent","{$user-agent}")
%rest:header-param("Referer","{$referer}", "none")

Cookies

Cookie parameters are specified the same way as query strings:

%rest:cookie-param("username","{$user}")
%rest:cookie-param("authentication","{$auth}", "no_auth")

Output

By default, all results will be returned with content type application/xml. Similar to our REST interface, result serialization can be modified via XQuery 3.0 serialization parameters. In RESTXQ, all parameters are specified within annotations.

The content type can be overwritten with the media-type annotation:

declare %output:media-type("text/plain") %rest:path("")
  function page:kiss() { 'keep it simple, stupid' };

Next, the content type can also be overwritten by specifying an output method. The following method mappings are available:

    • xmlapplication/xml
    • xhtmltext/html
    • htmltext/html
    • texttext/plain
    • rawapplication/octet-stream
    • json or jsonmlapplication/json

The following example will use text/html as content type:

declare
  %rest:path("")
  %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:start() {

<html xmlns="http://www.w3.org/1999/xhtml">
  <body>done</body>
</html>
};

References

RESTXQ has been proposed by Adam Retter. More information on all specifics can be found in the following two documents: