diff --git a/Doxygen/arango-html.doxy b/Doxygen/arango-html.doxy
index 23544d86eb..3552f2c06d 100644
--- a/Doxygen/arango-html.doxy
+++ b/Doxygen/arango-html.doxy
@@ -1550,7 +1550,7 @@ HIDE_UNDOC_RELATIONS = YES
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
-HAVE_DOT = YES
+HAVE_DOT = NO
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
# allowed to run in parallel. When set to 0 (the default) doxygen will
diff --git a/arangod/Documentation/user-manual.dox b/arangod/Documentation/user-manual.dox
index 53ce920e07..9884003f1d 100644
--- a/arangod/Documentation/user-manual.dox
+++ b/arangod/Documentation/user-manual.dox
@@ -42,6 +42,7 @@
///
@ref ShellEdge
/// @ref SimpleQueries
/// @ref Aql
+/// @ref UserManualActions
///
/// @latexonly\appendix@endlatexonly
/// @ref CommandLine
@@ -56,6 +57,7 @@
/// @copydetails ShellEdgeTOC
/// @copydetails SimpleQueriesTOC
/// @copydetails AqlTOC
+/// @copydetails UserManualActionsTOC
/// @copydetails CommandLineTOC
/// @endif
////////////////////////////////////////////////////////////////////////////////
@@ -336,6 +338,103 @@
/// JSON output format.
////////////////////////////////////////////////////////////////////////////////
+// -----------------------------------------------------------------------------
+// --SECTION-- USER MANUAL ACTIONS
+// -----------------------------------------------------------------------------
+
+////////////////////////////////////////////////////////////////////////////////
+/// @page UserManualActionsTOC
+///
+///
+/// - @ref UserManualActions
+///
+///
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+/// @page UserManualActions Arango Actions
+///
+/// Please note, that user Actions in ArangoDB are still preliminary and details
+/// are subject to change.
+///
+/// @EMBEDTOC{UserManualActionsTOC}
+///
+/// @section UserManualActionsIntro Introduction to User Actions
+////////////////////////////////////////////////////////////////
+///
+/// In same ways the ArangoDB server behaves like a Web server. It responses to
+/// HTTP request by delivering JSON objects in general. The idea is that
+/// sometimes it is better to store parts of the business logic within
+/// AnrangoDB. For instance, if you want to apply some statistics to large
+/// data-set and you cannot easily express this as query, then you can define a
+/// action instead of transferring the whole data-set to the client and do the
+/// computation there. Actions are also useful if you want to restrict and
+/// filter data according to some complex permission system.
+///
+/// The ArangoDB server deliver all kinds of information, JSON being only one
+/// possible format. You can also generate HTML or images. However, a Web server
+/// is normally better suited for the task as it also implements various caching
+/// strategies, language selection, compression and so on. Having said that,
+/// there are still situations where it might be suitable to use the ArangoDB to
+/// deliver HTML pages - static or dynamic. An simple example is the built-in
+/// administration interface. You can access it using any modern browser and
+/// there is no need for a separate Apache or IIS.
+///
+/// In the following sections we will introduce you to actions within ArangoDB
+/// and how to define them. The examples start with delivering static HTML pages
+/// - even if this is not the primary use-case for actions. The later sections
+/// will then show you, how to code some pieces of your business logic and
+/// return JSON objects.
+///
+/// The interface is loosely modelled after the JavaScript classes for HTTP
+/// request and responses found in node.js and the middleware/routing aspects
+/// of connect.js and express.js.
+///
+/// Note that unlike node.js, ArangoDB is multi-threaded and there is no easy
+/// way to share state between queries inside the JavaScript engine. If such
+/// state information is required, you need to use the database itself.
+///
+/// @section UserManualActionsHelloWorld A Hello World
+///
+/// The client API or browser sends a HTTP request to the ArangoDB server and
+/// the server returns a HTTP response to the client. A HTTP requests consists
+/// of a method, normally @LIT{GET} or @LIT{POST} when using a browser, and a
+/// request path like "/hello/world". For a real Web server there are a zillion
+/// of other thing to consider, we will ignore this for the moment. The HTTP
+/// response contains a content type, describing how to interpret the returned
+/// data, and the data itself.
+///
+/// In the following example, we want to define action in ArangoDB, so that the
+/// server returns the HTML document
+///
+/// @code
+///
+///
+/// Hallo World
+///
+///
+/// @endcode
+///
+/// if asked @LIT{GET /hello/world}.
+///
+/// The server needs to know what function to call or what document to deliver
+/// if it receives a request. This is called routing. All the routing information
+/// of ArangoDB is stored in a collection @LIT{_routing}. Each entry in this
+/// collections describes how to deal with a particular request path.
+///
+/// For the above example, add the following document to the @{_routing}
+/// collection:
+///
+/// @code
+/// arangosh> db._routing.save({
+/// ........> path : "/hello/world",
+/// ........> callback: {
+/// ........> type: "static",
+/// ........> contentType: "text/html",
+/// ........> body: "Hello" }});
+/// @endcode
+///
+///
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
diff --git a/js/actions/system/api-system.js b/js/actions/system/api-system.js
index a010996761..2b5aa47f32 100644
--- a/js/actions/system/api-system.js
+++ b/js/actions/system/api-system.js
@@ -72,13 +72,12 @@ function Routing (req, res) {
console.error("trying callback #%d / %d: %s # %s", current, callbacks.length, typeof callback, callback);
- current++;
-
if (callback == null) {
actions.resultNotImplemented(req, res, "not implemented '" + req.suffix.join("/") + "'");
}
else {
- callback(req, res, next, options);
+ req.prefix = callback.path;
+ callback.func(req, res, next, options);
}
}
diff --git a/js/common/bootstrap/js-print.h b/js/common/bootstrap/js-print.h
index a33904850c..0ff184d7f1 100644
--- a/js/common/bootstrap/js-print.h
+++ b/js/common/bootstrap/js-print.h
@@ -54,7 +54,7 @@ static string JS_common_bootstrap_print =
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief prints objects to standard output\n"
"///\n"
- "/// @FUN{print(@FA{arg1}, @FA{arg2}, @FA{arg3}, ...)}\n"
+ "/// @FUN{internal.printShell(@FA{arg1}, @FA{arg2}, @FA{arg3}, ...)}\n"
"///\n"
"/// Only available in shell mode.\n"
"///\n"
diff --git a/js/server/modules/org/arangodb/actions.js b/js/server/modules/org/arangodb/actions.js
index 41074e3e38..46df00735f 100644
--- a/js/server/modules/org/arangodb/actions.js
+++ b/js/server/modules/org/arangodb/actions.js
@@ -56,12 +56,49 @@ var RoutingCache = {};
/// @{
////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+/// @brief looks up a callback for static data
+////////////////////////////////////////////////////////////////////////////////
+
+function LookupCallbackStatic (callback) {
+ var type;
+ var body;
+
+ type = callback.type || "text/plain";
+ body = callback.body || "";
+
+ return function (req, res) {
+ res.responseCode = exports.HTTP_OK;
+ res.contentType = type;
+ res.body = body;
+ };
+}
+
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up a callback
////////////////////////////////////////////////////////////////////////////////
function LookupCallback (callback) {
- if (typeof callback === "string") {
+ var type;
+
+ if (typeof callback === 'object') {
+ if ('type' in callback) {
+ type = callback.type;
+
+ if (type === "static") {
+ return LookupCallbackStatic(callback);
+ }
+ else {
+ console.error("unknown callback type '%s'", type);
+ return undefined;
+ }
+ }
+ else {
+ console.error("missing callback type in '%s'", JSON.stringify(callback));
+ return undefined;
+ }
+ }
+ else if (typeof callback === "string") {
var components;
var module;
var fn;
@@ -86,7 +123,6 @@ function LookupCallback (callback) {
}
if (fn in module) {
- console.error("lookup %s: %s", typeof module[fn], module[fn]);
return module[fn];
}
@@ -540,11 +576,21 @@ function Routing (method, path) {
result = [];
for (i = 0; i < topdown.length; ++i) {
- result = result.concat(topdown[i].callback);
+ var td = topdown[i];
+ var callback = td.callback;
+
+ for (j = 0; j < callback.length; ++j) {
+ result.push({ func : callback[j], path : td.path });
+ }
}
for (i = 0; i < bottomup.length; ++i) {
- result = result.concat(bottomup[i].callback);
+ var bu = bottomup[i];
+ var callback = bu.callback;
+
+ for (j = 0; j < callback.length; ++j) {
+ result.push({ func : callback[j], path : bu.path });
+ }
}
return result;
diff --git a/js/server/modules/org/arangodb/examples.js b/js/server/modules/org/arangodb/examples.js
index 31a536551b..f32d3ab397 100644
--- a/js/server/modules/org/arangodb/examples.js
+++ b/js/server/modules/org/arangodb/examples.js
@@ -1,7 +1,15 @@
var console = require("console");
+var actions = require("org/arangodb/actions");
exports.logRequest = function (req, res, next, options) {
console.log("received request: %s", JSON.stringify(req));
+ console.log("error: ", next);
next();
console.log("produced response: %s", JSON.stringify(res));
-}
+};
+
+exports.echoRequest = function (req, res) {
+ res.responseCode = actions.HTTP_OK;
+ res.contentType = "application/json";
+ res.body = JSON.stringify(req);
+};
\ No newline at end of file