1
0
Fork 0

added first go at user actions

This commit is contained in:
Frank Celler 2012-09-16 17:25:57 +02:00
parent 9212351c13
commit 4f6762436c
6 changed files with 162 additions and 10 deletions

View File

@ -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

View File

@ -42,6 +42,7 @@
/// <li>@ref ShellEdge</li>
/// <li>@ref SimpleQueries</li>
/// <li>@ref Aql</li>
/// <li>@ref UserManualActions</li>
///
/// @latexonly\appendix@endlatexonly
/// <li>@ref CommandLine</li>
@ -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
///
/// <ul>
/// <li>@ref UserManualActions
/// </li>
/// </ul>
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @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
/// <html>
/// <body>
/// Hallo World
/// </body>
/// </html>
/// @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: "<html><body>Hello</body></html>" }});
/// @endcode
///
///
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------

View File

@ -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);
}
}

View File

@ -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"

View File

@ -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;

View File

@ -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);
};