Changes

Jump to navigation Jump to search
629 bytes added ,  15:57, 27 February 2020
no edit summary
A first RESTXQ function is shown below:
<pre classsyntaxhighlight lang="brush:xquery">
module namespace page = 'http://basex.org/examples/web-page';
<title>Hello { $who }!</title>
</response>
};</presyntaxhighlight>
If the URI http://localhost:8984/hello/World is accessed, the result will be:
<pre classsyntaxhighlight lang="brush:xml">
&lt;response&gt;
&lt;title&gt;Hello World!&lt;/title&gt;
&lt;/response&gt;
</presyntaxhighlight>
The next function demonstrates a POST request:
<pre classsyntaxhighlight lang="brush:xquery">
declare
%rest:path("/form")
&lt;/response&gt;
};
</presyntaxhighlight>
If you post something (e.g. using curl or the embedded form at http://localhost:8984/)...
<pre classsyntaxhighlight lang="brush:shell">
curl -i -X POST --data "message='CONTENT'" http://localhost:8984/form
</presyntaxhighlight>
...you will receive something similar to the following result:
<pre classsyntaxhighlight lang="brush:shell">
HTTP/1.1 200 OK
Content-Type: application/xml; charset=UTF-8
Content-Length: 107
Server: Jetty(8.1.11.v20130520)
</presyntaxhighlight>
<pre classsyntaxhighlight lang="brush:xml">
<response type="form">
<message>'CONTENT'</message>
<user-agent>curl/7.31.0</user-agent>
</response>
</presyntaxhighlight>
=Request=
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 <code>$variable</code> will be cast to an <code>xs:integer</code> before being bound:
<pre classsyntaxhighlight lang="brush:xquery">
declare %rest:path("/a/path/{$with}/some/{$variable}")
function page:test($with, $variable as xs:integer) { ... };
</presyntaxhighlight>
<!-- TODO how matching works -->
Variables can be enhanced by regular expressions:
<pre classsyntaxhighlight lang="brush:xquery">
(: Matches all paths with "app" as first, a number as second, and "order" as third segment :)
declare %rest:path("app/{$code=[0-9]+}/order")
declare %rest:path("app/{$path=.+}")
function page:others($path) { ... };
</presyntaxhighlight>
<!-- TODO how matching works -->
* '''HTTP Content Types''': A function will only be invoked if the HTTP {{Code|Content-Type}} header of the request matches one of the given content types. Example:
<pre classsyntaxhighlight lang="brush:xquery">%rest:consumes("application/xml", "text/xml")</presyntaxhighlight>
* '''HTTP Accept''': A function will only be invoked if the HTTP {{Code|Accept}} header of the request matches one of the defined content types. Example:
<pre classsyntaxhighlight lang="brush:xquery">%rest:produces("application/atom+xml")</presyntaxhighlight>
By default, both content types are {{Code|*/*}}. Quality factors supplied by a client will also be considered in the path selection process. If a client supplies the following accept header…
Server-side quality factors are supported as well: If multiple function candidates are left over after the above steps, the <code>qs</code> parameter will be considered. The function with the highest quality factor will be favored:
<pre classsyntaxhighlight lang="brush:xquery">
%rest:produces("text/html;qs=1")
%rest:produces("*/*;qs=0.8")
</presyntaxhighlight>
Note that the annotation will ''not'' affect the content type of the actual response. You will need to supply an additional <code>[[#Output|%output:media-type]]</code> annotation.
The following function will be called if GET or POST is used as request method:
<pre classsyntaxhighlight lang="brush:xquery">
declare %rest:GET %rest:POST %rest:path("/post")
function page:post() { "This was a GET or POST request" };
</presyntaxhighlight>
The POST and PUT annotations may optionally take a string literal in order to map the HTTP request body to a [[#Parameters|function argument]]. Once again, the target variable must be embraced by curly brackets:
<pre classsyntaxhighlight lang="brush:xquery">
declare %rest:PUT("{$body}") %rest:path("/put")
function page:put($body) { "Request body: " || $body };
</presyntaxhighlight>
====Custom Methods====
Custom HTTP methods can be specified with the {{Code|%rest:method}} annotation. An optional body variable can be supplied as second argument:
<pre classsyntaxhighlight lang="brush:xquery">
declare
%rest:path("binary-size")
"Size of body: " || bin:length($body)
};
</presyntaxhighlight>
{{Mark|Updated with Version 9.3:}}
Conversion options for {{Option|JSON}}, {{Option|CSV}} and {{Option|HTML}} can also be specified via annotations with the <code>input</code> prefix. The following function interprets the input as text with the CP1252 encoding and treats the first line as header:
<pre classsyntaxhighlight lang="brush:xquery">
declare
%rest:path("/store.csv")
"Number of rows: " || count($csv/csv/record)
};
</presyntaxhighlight>
===Multipart Types===
A function that is capable of handling multipart types is identical to other RESTXQ functions:
<pre classsyntaxhighlight lang="brush:xquery">
declare
%rest:path("/multipart")
"Number of items: " || count($data)
};
</presyntaxhighlight>
==Parameters==
The value of the ''first parameter'', if found in the [[Request_Module#Conventions|query component]], will be assigned to the variable specified as ''second parameter''. If no value is specified in the HTTP request, all additional parameters will be bound to the variable (if no additional parameter is given, an empty sequence will be bound):
<pre classsyntaxhighlight lang="brush:xquery">
declare
%rest:path("/params")
<result id="{ $id }" sum="{ sum($add) }"/>
};
</presyntaxhighlight>
===HTML Form Fields===
Form parameters are specified the same way as [[#Query Parameters|query parameters]]. Their values are the result of HTML forms submitted with the content type <code>application/x-www-form-urlencoded</code>.
<pre classsyntaxhighlight lang="brush:xquery">
%rest:form-param("parameter", "{$value}", "default")
</presyntaxhighlight>
====File Uploads====
Files can be uploaded to the server by using the content type {{Code|multipart/form-data}} (the HTML5 {{Code|multiple}} attribute enables the upload of multiple files):
<pre classsyntaxhighlight lang="brush:xml">
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="files" multiple="multiple"/>
<input type="submit"/>
</form>
</presyntaxhighlight>
The file contents are placed in a [[Map Module|map]], with the filename serving as key. The following example shows how uploaded files can be stored in a temporary directory:
<pre classsyntaxhighlight lang="brush:xquery">
declare
%rest:POST
)
};
</presyntaxhighlight>
===HTTP Headers===
Header parameters are specified the same way as [[#Query Parameters|query parameters]]:
<pre classsyntaxhighlight lang="brush:xquery">
%rest:header-param("User-Agent", "{$user-agent}")
%rest:header-param("Referer", "{$referer}", "none")
</presyntaxhighlight>
===Cookies===
Cookie parameters are specified the same way as [[#Query Parameters|query parameters]]:
<pre classsyntaxhighlight lang="brush:xquery">
%rest:cookie-param("username", "{$user}")
%rest:cookie-param("authentication", "{$auth}", "no_auth")
</presyntaxhighlight>
==Query Execution==
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|460}} will be returned instead:
<pre classsyntaxhighlight lang="brush:xquery">
(: If fast enough, returns the result. Otherwise, if called again, raises 460 :)
declare
}</ul>
};
</presyntaxhighlight>
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>460</code>, and the second one will return <xml>stopped</xml>.
<pre classsyntaxhighlight lang="brush:xquery">
declare
%rest:path("/compute")
<xml>stopped</xml>
};
</presyntaxhighlight>
The following things should be noted:
Custom responses can be generated in XQuery by returning an <code>rest:response</code> element, an <code>http:response</code> child node that matches the syntax of the [http://expath.org/spec/http-client EXPath HTTP Client Module] specification, and optional child nodes that will be serialized as usual. A function that yields a response on an unknown resource may look as follows:
<pre classsyntaxhighlight lang="brush:xquery">
declare %output:method("text") %rest:path("") function page:error404() {
<rest:response>
"The requested resource is not available."
};
</presyntaxhighlight>
==Forwards and Redirects==
The server can invite the client (e.g., the web browser) to make a second request to another URL by sending a 302 response:
<pre classsyntaxhighlight lang="brush:xml">
<rest:response>
<http:response status="302">
</http:response>
</rest:response>
</presyntaxhighlight>
The convenience function {{Function|Web|web:redirect}} can be called to create such a response.
In the XQuery context, redirects are particularly helpful if [[XQuery Update|Updates]] are performed. An updating request may send a redirect to a second function that generates a success message, or evaluates an updated database:
<pre classsyntaxhighlight lang="brush:xquery">
declare %updating %rest:path('/app/init') function local:create() {
db:create('app', <root/>, 'root.xml'),
'Stored documents: ' || count(db:open('app'))
};
</presyntaxhighlight>
===Forwards===
A server-side redirect is called forwarding. It reduces traffic among client and server, and the forwarding will not change the URL seen from the client’s perspective:
<pre classsyntaxhighlight lang="brush:xml">
<rest:forward>new-location</rest:forward>
</presyntaxhighlight>
The fragment can also be created with the convenience function {{Function|Web|web:forward}}.
In main modules, serialization parameters may be specified in the query prolog. These parameters will then apply to all functions in a module. In the following example, the content type of the response is overwritten with the {{Code|media-type}} parameter:
<pre classsyntaxhighlight lang="brush:xquery">
declare option output:media-type 'text/plain';
'Keep it simple, stupid'
};
</presyntaxhighlight>
===Annotations===
Global serialization parameters can be overwritten via <code>%output</code> annotations. The following example serializes XML nodes as JSON, using the [[JSON Module|JsonML]] format:
<pre classsyntaxhighlight lang="brush:xquery">
declare
%rest:path("cities")
}
};
</presyntaxhighlight>
The next function, when called, generates XHTML headers, and {{Code|text/html}} will be set as content type:
<pre classsyntaxhighlight lang="brush:xquery">
declare
%rest:path("done")
</html>
};
</presyntaxhighlight>
===Response Element===
Serialization parameters can also be specified in a REST reponse element in a query. Serialization parameters will be overwritten:
<pre classsyntaxhighlight lang="brush:xquery">
declare %rest:path("version3") function page:version3() {
<rest:response>
'Not that simple anymore'
};
</presyntaxhighlight>
=Error Handling=
With the {{Function|Web|web:error}} function, you can abort query evaluation and enforce a premature HTTP response with the supplied status code and response body text:
<pre classsyntaxhighlight lang="brush:xquery">
declare
%rest:path("/teapot")
web:error(418, "I'm a pretty teapot")
};
</presyntaxhighlight>
The XQuery error code and the stack trace will be suppressed in the body of the HTTP response.
Errors may occur unexpectedly. However, they can also be triggered by a query, as demonstrated by the following example:
<pre classsyntaxhighlight lang="brush:xquery">
declare
%rest:path("/check/{$user}")
'User "' || $user || '" is unknown'
};
</presyntaxhighlight>
==Catch HTTP Errors==
Errors that occur outside RESTXQ can be caught by adding {{Code|error-page}} elements with an error code and a target location to the {{Code|web.xml}} configuration file (find more details in the [http://www.eclipse.org/jetty/documentation/current/custom-error-pages.html Jetty Documentation]):
<pre classsyntaxhighlight lang="brush:xml">
<error-page>
<error-code>404</error-code>
<location>/error404</location>
</error-page>
</presyntaxhighlight>
The target location may be another RESTXQ function. The [[Request Module#request:attribute|request:attribute]] function can be used to request details on the caught error:
<pre classsyntaxhighlight lang="brush:xquery">
declare %rest:path("/error404") function page:error404() {
"URL: " || request:attribute("javax.servlet.error.request_uri") || ", " ||
"Error message: " || request:attribute("javax.servlet.error.message")
};
</presyntaxhighlight>
=User Authentication=
The following example returns the current host name:
<pre classsyntaxhighlight lang="brush:xquery">
import module namespace request = "http://exquery.org/ns/request";
'Remote host name: ' || request:remote-hostname()
};
</presyntaxhighlight>
=References=
Bureaucrats, editor, reviewer, Administrators
13,550

edits

Navigation menu