diff --git a/js/server/modules/org/arangodb/actions.js b/js/server/modules/org/arangodb/actions.js index d8fbe017a2..4c079e5ad8 100644 --- a/js/server/modules/org/arangodb/actions.js +++ b/js/server/modules/org/arangodb/actions.js @@ -1034,7 +1034,61 @@ function flattenRoutingTree (tree) { //////////////////////////////////////////////////////////////////////////////// function foxxRouting (req, res, options, next) { - routeRequest(req, res, options.routing); + var mount = options.mount; + + try { + var app = foxxManager.lookupApp(mount); + var devel = app._isDevelopment; + + if (devel || ! options.hasOwnProperty('routing')) { + delete options.error; + + if (devel) { + foxxManager.rescanFoxx(mount); // TODO can move this to somewhere else? + } + + if (app._isBroken) { + throw app._error; + } + + options.routing = flattenRoutingTree(buildRoutingTree([foxxManager.routes(mount)])); + } + } + catch (err1) { + options.error = { + code: exports.HTTP_SERVER_ERROR, + num: arangodb.ERROR_HTTP_SERVER_ERROR, + msg: "failed to load foxx mounted at '" + mount + "'", + info: { exception: String(err1) } + }; + + if (err1.stack) { + options.error.info.stacktrace = String(err1.stack).split("\n"); + } + } + + if (options.hasOwnProperty('error')) { + exports.resultError(req, + res, + options.error.code, + options.error.num, + options.error.msg, + {}, + options.error.info); + } + else { + try { + routeRequest(req, res, options.routing); + } + catch (err2) { + resultException( + req, + res, + err2, + {}, + "failed to execute foxx mounted at '" + mount + "'"); + } + } } //////////////////////////////////////////////////////////////////////////////// @@ -1063,19 +1117,16 @@ function buildRouting (dbname) { routing = null; // install the foxx routes - var foxxes = foxxManager.appRoutes(); + var foxxes = foxxManager.mountPoints(); - for (i in foxxes) { - if (foxxes.hasOwnProperty(i)) { - var foxx = foxxes[i]; - var list = flattenRoutingTree(buildRoutingTree([foxx])); + for (i = 0; i < foxxes.length; ++i) { + var foxx = foxxes[i]; - routes.push({ - name: foxx.name, - url: { match: i + "/*" }, - action: { callback: foxxRouting, options: { routing: list } } - }); - } + routes.push({ + name: "foxx app mounted at '" + foxx + "'", + url: { match: foxx + "/*" }, + action: { callback: foxxRouting, options: { mount: foxx } } + }); } // build the routing tree @@ -2065,7 +2116,9 @@ function indexNotFound (req, res, collection, index, headers) { /// /// The function generates an error response. If @FA{verbose} is set to /// *true* or not specified (the default), then the error stack trace will -/// be included in the error message if available. +/// be included in the error message if available. If @FA{verbose} is a string +/// it will be prepended before the error message and the stacktrace will also +/// be included. /// @endDocuBlock //////////////////////////////////////////////////////////////////////////////// @@ -2076,14 +2129,29 @@ function resultException (req, res, err, headers, verbose) { var msg; var num; - if (verbose || verbose === undefined) { - msg = String(err.stack || err); - verbose = true; + var info = {}; + var showTrace = false; + + if (typeof verbose === 'string') { + msg = verbose; + info.exception = String(err); + showTrace = true; + } + else if (verbose || verbose === undefined) { + msg = "An error has occurred during execution"; + info.exception = String(err); + showTrace = true; } else { msg = String(err); } + if (showTrace) { + if (err.stack) { + info.stacktrace = String(err.stack).split("\n"); + } + } + if (err instanceof internal.ArangoError) { num = err.errorNum; code = exports.HTTP_BAD; @@ -2092,8 +2160,13 @@ function resultException (req, res, err, headers, verbose) { num = arangodb.ERROR_INTERNAL; } - if (err.errorMessage !== "" && ! verbose) { - msg = err.errorMessage; + if (err.errorMessage !== "") { + if (typeof verbose === 'string') { + info.message = err.errorMessage; + } + else { + msg = err.errorMessage; + } } switch (num) { @@ -2143,7 +2216,7 @@ function resultException (req, res, err, headers, verbose) { code = exports.HTTP_SERVER_ERROR; } - resultError(req, res, code, num, msg, headers); + resultError(req, res, code, num, msg, headers, info); } //////////////////////////////////////////////////////////////////////////////// @@ -2316,13 +2389,6 @@ function stringifyRequestAddress (req) { return out; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief updates the routing for one app -//////////////////////////////////////////////////////////////////////////////// - -function setFoxxRouting (mount, routes) { -} - // ----------------------------------------------------------------------------- // --SECTION-- MODULE EXPORTS // ----------------------------------------------------------------------------- @@ -2330,9 +2396,6 @@ function setFoxxRouting (mount, routes) { // load all actions from the actions directory exports.startup = startup; -// updates the routing information for one foxx application -exports.setFoxxRouting = setFoxxRouting; - // only for debugging exports.buildRouting = buildRouting; exports.buildRoutingTree = buildRoutingTree; diff --git a/js/server/modules/org/arangodb/foxx/arangoApp.js b/js/server/modules/org/arangodb/foxx/arangoApp.js index bcd7a54262..184b637c6f 100644 --- a/js/server/modules/org/arangodb/foxx/arangoApp.js +++ b/js/server/modules/org/arangodb/foxx/arangoApp.js @@ -122,7 +122,7 @@ var ArangoApp = function (config) { this._collectionPrefix = this._mount.substr(1).replace(/-/g, "_").replace(/\//g, "_") + "_"; this._context = new AppContext(this); - if (this._manifest.hasOwnProperty("defaultDocument")) { + if (! this._manifest.hasOwnProperty("defaultDocument")) { this._manifest.defaultDocument = "index.html"; } }; diff --git a/js/server/modules/org/arangodb/foxx/manager.js b/js/server/modules/org/arangodb/foxx/manager.js index f25a373caa..ae3b457c11 100644 --- a/js/server/modules/org/arangodb/foxx/manager.js +++ b/js/server/modules/org/arangodb/foxx/manager.js @@ -1234,30 +1234,31 @@ exports.initializeFoxx = function () { /// @brief refills the routing cache //////////////////////////////////////////////////////////////////////////////// - var refillCaches = function(computeRoutes) { + var refillCaches = function() { appCache = {}; var cursor = utils.tmp_getStorage().all(); - var config, app, route; - var routes = {}; + var config, app; + var routes = []; while (cursor.hasNext()) { config = cursor.next(); app = new ArangoApp(config); appCache[app._mount] = app; - - if (computeRoutes) { - route = routeApp(app); - - if (route) { - routes[app._mount] = route; - } - } + routes.push(app._mount); } return routes; }; + //////////////////////////////////////////////////////////////////////////////// + /// @brief routes of an foxx + //////////////////////////////////////////////////////////////////////////////// + + var routes = function(mount) { + return routeApp(lookupApp(mount)); + }; + //////////////////////////////////////////////////////////////////////////////// /// @brief Makes sure all system apps are mounted. //////////////////////////////////////////////////////////////////////////////// @@ -1280,7 +1281,6 @@ exports.initializeFoxx = function () { //////////////////////////////////////////////////////////////////////////////// var lookupApp = function(mount) { - require("console").log(Object.keys(appCache)); if (!appCache.hasOwnProperty(mount)) { throw "App not found"; } @@ -1484,7 +1484,6 @@ exports.initializeFoxx = function () { //////////////////////////////////////////////////////////////////////////////// var appConfig = function (mount, options) { - var root = computeRootAppPath(mount); var path = transformMountToPath(mount); @@ -1505,7 +1504,6 @@ exports.initializeFoxx = function () { mount: mount, isSystem: isSystemMount(mount), isDevelopment: false - }; }; @@ -1792,6 +1790,25 @@ exports.initializeFoxx = function () { executeGlobalContextFunction("reloadRouting"); }; + //////////////////////////////////////////////////////////////////////////////// + /// @brief Scans the sources of the given mountpoint and publishes the routes + /// + /// TODO: Long Documentation! + //////////////////////////////////////////////////////////////////////////////// + + var rescanFoxx = function(mount) { + checkParameter( + "scanFoxx()", + [ [ "Mount path", "string" ] ], + [ mount ] ); + + var old = lookupApp(mount); + + utils.tmp_getStorage().removeByExample({mount: mount}); + + _scanFoxx(mount, old._options); + }; + //////////////////////////////////////////////////////////////////////////////// /// @brief Internal install function. Check install. /// Does not check parameters and throws errors. @@ -1913,7 +1930,7 @@ exports.initializeFoxx = function () { //////////////////////////////////////////////////////////////////////////////// var initializeFoxx = function() { - refillCaches(false); + refillCaches(); checkMountedSystemApps(); }; @@ -1921,8 +1938,8 @@ exports.initializeFoxx = function () { /// @brief compute all app routes //////////////////////////////////////////////////////////////////////////////// - var appRoutes = function() { - return refillCaches(true); + var mountPoints = function() { + return refillCaches(); }; //////////////////////////////////////////////////////////////////////////////// @@ -1931,7 +1948,7 @@ exports.initializeFoxx = function () { var _toggleDevelopment = function(mount, activate) { var app = lookupApp(mount); - app.setDevelopment(activate); + app.development(activate); utils.updateApp(mount, app.toJSON()); executeGlobalContextFunction("reloadRouting"); }; @@ -1998,11 +2015,14 @@ exports.initializeFoxx = function () { exports.uninstall = uninstall; exports.replace = replace; exports.upgrade = upgrade; - exports.appRoutes = appRoutes; + exports.mountPoints = mountPoints; exports.development = setDevelopment; exports.production = setProduction; exports.configure = configure; exports.configuration = configuration; + exports.routes = routes; + exports.rescanFoxx = rescanFoxx; + exports.lookupApp = lookupApp; //////////////////////////////////////////////////////////////////////////////// /// @brief Exports from foxx utils module. diff --git a/js/server/modules/org/arangodb/foxx/routing.js b/js/server/modules/org/arangodb/foxx/routing.js index 09b2cd24cc..ec140bba52 100644 --- a/js/server/modules/org/arangodb/foxx/routing.js +++ b/js/server/modules/org/arangodb/foxx/routing.js @@ -41,7 +41,6 @@ var fs = require("fs"); var frontendDevelopmentMode = require("internal").frontendDevelopmentMode; var console = require("console"); - var setFoxxRouting = require("org/arangodb/actions").setFoxxRouting; // ----------------------------------------------------------------------------- // --SECTION-- private functions @@ -361,6 +360,7 @@ // mount all controllers var controllers = app._manifest.controllers; +// TODO better error handling, mark foxx as failed! try { for (i in controllers) { if (controllers.hasOwnProperty(i)) { @@ -424,7 +424,7 @@ // install all files and assets installAssets(app, routes); - // Trigger the setFoxxRouting in actions + // return the new routes return routes; } catch (err) {