1
0
Fork 0

Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel

This commit is contained in:
Michael Hackstein 2013-03-26 14:01:47 +01:00
commit 4d32fb204b
17 changed files with 588 additions and 139 deletions

View File

@ -454,7 +454,7 @@ Install it as
arangosh> db._routing.save({
........> url: "/echo",
........> action: { controller: "org/arangodb/actions", do: "echoRequest" } });
........> action: { do: "org/arangodb/actions/echoRequest" } });
Reload the routing and check
@ -489,8 +489,7 @@ You may also pass options to the called function:
arangosh> db._routing.save({
........> url: "/echo",
........> action: {
........> controller: "org/arangodb/actions",
........> do: "echoRequest",
........> do: "org/arangodb/actions/echoRequest",
........> options: { "Hello": "World" } } });
You should now see the options in the result.
@ -651,8 +650,7 @@ Use the following for a permanent redirect:
arangosh> db._routing.save({
........> url: "/",
........> action: {
........> controller: "org/arangodb/actions",
........> do: "redirectRequest",
........> do: "org/arangodb/actions/redirectRequest",
........> options: {
........> permanently: true,
........> destination: "http://somewhere.else/" } } });
@ -707,7 +705,7 @@ should win in this case:
arangosh> db._routing.save({
........> middleware: [
........> { url: { match: "/*" }, action: { controller: "org/arangodb/actions", do: "logRequest" } }
........> { url: { match: "/*" }, action: { do: "org/arangodb/actions/logRequest" } }
........> ]
........> });

View File

@ -32,6 +32,8 @@
#include "Basics/StringUtils.h"
#include "Basics/WriteLocker.h"
#include "BasicsC/conversions.h"
#include "BasicsC/files.h"
#include "BasicsC/strings.h"
#include "Logger/Logger.h"
#include "Rest/HttpRequest.h"
#include "Rest/HttpResponse.h"
@ -39,7 +41,6 @@
#include "V8/v8-utils.h"
#include "V8Server/ApplicationV8.h"
#include "V8Server/v8-vocbase.h"
#include "3rdParty/V8/include/v8.h"
using namespace std;
using namespace triagens::basics;
@ -517,6 +518,10 @@ static HttpResponse* ExecuteActionVocbase (TRI_vocbase_t* vocbase,
response->setContentType(TRI_ObjectToString(res->Get(v8g->ContentTypeKey)));
}
// .............................................................................
// body
// .............................................................................
if (res->Has(v8g->BodyKey)) {
// check if we should apply result transformations
// transformations turn the result from one type into another
@ -524,10 +529,11 @@ static HttpResponse* ExecuteActionVocbase (TRI_vocbase_t* vocbase,
// putting a list of transformations into the res.transformations
// array, e.g. res.transformations = [ "base64encode" ]
v8::Handle<v8::Value> val = res->Get(v8g->TransformationsKey);
if (val->IsArray()) {
string out(TRI_ObjectToString(res->Get(v8g->BodyKey)));
v8::Handle<v8::Array> transformations = val.As<v8::Array>();
for (uint32_t i = 0; i < transformations->Length(); i++) {
v8::Handle<v8::Value> transformator = transformations->Get(v8::Integer::New(i));
string name = TRI_ObjectToString(transformator);
@ -554,6 +560,31 @@ static HttpResponse* ExecuteActionVocbase (TRI_vocbase_t* vocbase,
}
}
// .............................................................................
// body from file
// .............................................................................
else if (res->Has(v8g->BodyFromFileKey)) {
TRI_Utf8ValueNFC filename(TRI_UNKNOWN_MEM_ZONE, res->Get(v8g->BodyFromFileKey));
size_t length;
char* content = TRI_SlurpFile(TRI_UNKNOWN_MEM_ZONE, *filename, &length);
if (content != 0) {
response->body().appendText(content, length);
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, content);
}
else {
string msg = string("cannot read file '") + *filename + "': " + TRI_last_error();
response->body().appendText(msg.c_str());
response->setResponseCode(HttpResponse::SERVER_ERROR);
}
}
// .............................................................................
// headers
// .............................................................................
if (res->Has(v8g->HeadersKey)) {
v8::Handle<v8::Value> val = res->Get(v8g->HeadersKey);
v8::Handle<v8::Object> v8Headers = val.As<v8::Object>();
@ -740,6 +771,7 @@ void TRI_InitV8Actions (v8::Handle<v8::Context> context, ApplicationV8* applicat
// .............................................................................
v8g->BodyKey = v8::Persistent<v8::String>::New(TRI_V8_SYMBOL("body"));
v8g->BodyFromFileKey = v8::Persistent<v8::String>::New(TRI_V8_SYMBOL("bodyFromFile"));
v8g->ContentTypeKey = v8::Persistent<v8::String>::New(TRI_V8_SYMBOL("contentType"));
v8g->HeadersKey = v8::Persistent<v8::String>::New(TRI_V8_SYMBOL("headers"));
v8g->ParametersKey = v8::Persistent<v8::String>::New(TRI_V8_SYMBOL("parameters"));

View File

@ -35,6 +35,69 @@ var internal = require("internal");
// --SECTION-- module "arangodb"
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoShell
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief guesses the content type
////////////////////////////////////////////////////////////////////////////////
exports.guessContentType = function (filename) {
var re = /.*\.([^\.]*)$/;
var match = re.exec(filename);
var extension;
if (match === null) {
return "text/plain; charset=utf-8";
}
extension = match[1];
if (extension === "html") {
return "text/html; charset=utf-8";
}
if (extension === "xml") {
return "application/xml; charset=utf-8";
}
if (extension === "json") {
return "application/json; charset=utf-8";
}
if (extension === "js") {
return "application/x-javascript; charset=utf-8";
}
if (extension === "css") {
return "text/css; charset=utf-8";
}
if (extension === "png") {
return "image/png";
}
if (extension === "gif") {
return "image/gif";
}
if (extension === "jpg") {
return "image/jpg;
}
return "text/plain; charset=utf-8";
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- MODULE EXPORTS
// -----------------------------------------------------------------------------
@ -44,11 +107,19 @@ var internal = require("internal");
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief function "normalizeURL"
////////////////////////////////////////////////////////////////////////////////
exports.normalizeURL = internal.normalizeURL;
////////////////////////////////////////////////////////////////////////////////
/// @brief function "output"
////////////////////////////////////////////////////////////////////////////////
exports.output = function () { internal.output.apply(internal.output, arguments); };
exports.output = function () {
internal.output.apply(internal.output, arguments);
};
////////////////////////////////////////////////////////////////////////////////
/// @brief function "print"

View File

@ -46,7 +46,7 @@ var foxx = require("org/arangodb/foxx");
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url : "_admin/foxx/load",
url : "_admin/foxx/install",
context : "admin",
prefix : false,
@ -58,14 +58,11 @@ actions.defineHttp({
return;
}
if (! body.hasOwnProperty("manifest")) {
actions.resultBad(req,
res,
arangodb.ERROR_HTTP_BAD_PARAMETER,
"body must specify a 'manifest'");
}
var name = body.name;
var mount = body.mount;
var options = body.options || {};
result = foxx.loadManifest(body.manifest);
result = foxx.installApp(name, mount, options);
actions.resultOk(req, res, actions.HTTP_OK, result);
}
});

View File

@ -59,7 +59,7 @@ function routing (req, res) {
execute = function () {
if (action.route === undefined) {
actions.resultNotImplemented(req, res, "unknown path '" + path + "'");
actions.resultNotFound(req, res, arangodb.ERROR_HTTP_NOT_FOUND, "unknown path '" + path + "'");
return;
}

View File

@ -32,6 +32,8 @@ var arangodb = require("org/arangodb");
var fs = require("fs");
var internal = require("internal");
var guessContentType = arangodb.guessContentType;
// -----------------------------------------------------------------------------
// --SECTION-- ArangoApp
// -----------------------------------------------------------------------------
@ -68,40 +70,6 @@ function ArangoApp (routing, description) {
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief guesses the content type
////////////////////////////////////////////////////////////////////////////////
function guessContentType (filename, content) {
var re = /.*\.([^\.]*)$/;
var match = re.exec(filename);
var extension;
if (match === null) {
return "text/plain; charset=utf-8";
}
extension = match[1];
if (extension === "html") {
return "text/html; charset=utf-8";
}
if (extension === "xml") {
return "application/xml; charset=utf-8";
}
if (extension === "json") {
return "application/json; charset=utf-8";
}
if (extension === "js") {
return "application/x-javascript; charset=utf-8";
}
return "text/plain; charset=utf-8";
}
////////////////////////////////////////////////////////////////////////////////
/// @brief normalizes a path
////////////////////////////////////////////////////////////////////////////////
@ -431,7 +399,7 @@ ArangoApp.prototype.uploadStaticPages = function (prefix, path) {
filename = files[i];
}
contentType = guessContentType(file, content);
contentType = guessContentType(file);
collection.save({
application: this._name,

View File

@ -40,13 +40,17 @@ var internal = require("internal");
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief loads a foxx manifest
/// @brief install a fox application
////////////////////////////////////////////////////////////////////////////////
exports.loadManifest = function (name) {
var result = { manifest: name };
exports.installApp = function (name, mount, options) {
var req = {
name: name,
mount: mount,
options: options
};
return internal.arango.POST("/_admin/foxx/load", JSON.stringify(result));
return internal.arango.POST("/_admin/foxx/install", JSON.stringify(req));
};
////////////////////////////////////////////////////////////////////////////////

View File

@ -90,7 +90,7 @@
fs.isFile = internal.isFile;
////////////////////////////////////////////////////////////////////////////////
/// @brief joins two paths (dummy)
/// @brief joins two paths (dummy implementation)
////////////////////////////////////////////////////////////////////////////////
fs.join = function () {
@ -105,7 +105,7 @@
};
////////////////////////////////////////////////////////////////////////////////
/// @brief lists all files and directory under a given path
/// @brief lists all files and directories under a given path
////////////////////////////////////////////////////////////////////////////////
fs.listTree = internal.listTree;

View File

@ -608,7 +608,6 @@ function stop_color_print () {
var content;
var module;
var env;
var fun;
var key;
var sandbox;
@ -658,7 +657,7 @@ function stop_color_print () {
+ "\n});";
try {
fun = internal.executeScript(content, undefined, description.name);
var fun = internal.executeScript(content, undefined, description.name);
if (fun === undefined) {
throw "cannot create module context function for: " + content;
@ -919,49 +918,64 @@ function stop_color_print () {
/// @brief loads an init file from an application path
////////////////////////////////////////////////////////////////////////////////
Module.prototype.loadAppScript = function (appRoot, file, context) {
Module.prototype.loadAppScript = function (appRoot, file, appContext, context) {
var sandbox = {};
var fileContent;
var content;
var description;
var full;
var fun;
var result;
var key;
description = appRoot._appDescription;
try {
full = description.path + "/" + file;
content = internal.read(full);
fileContent = internal.read(full);
}
catch (err1) {
throw "cannot read file '" + full + "': " + err1 + " - " + err1.stack;
}
if (context !== undefined) {
for (key in context) {
if (context.hasOwnProperty(key) && key !== "__myenv__") {
sandbox[key] = context[key];
}
}
}
sandbox.module = appRoot;
sandbox.applicationContext = context;
sandbox.applicationContext = appContext;
sandbox.require = function (path) {
return appRoot.require(path);
};
content = "var func = function () {"
+ content
+ "\n};";
content = "(function (__myenv__) {";
fun = internal.executeScript(content, sandbox, full);
if (fun !== true || ! sandbox.hasOwnProperty("func")) {
throw "cannot create application function";
for (key in sandbox) {
if (sandbox.hasOwnProperty(key)) {
content += "var " + key + " = __myenv__['" + key + "'];";
}
}
content += "delete __myenv__;"
+ fileContent
+ "\n});";
try {
result = sandbox.func();
var fun = internal.executeScript(content, undefined, full);
if (fun === undefined) {
throw "cannot create application script: " + content;
}
fun(sandbox);
}
catch (err2) {
throw "Javascript exception in application file '" + full + "': " + err2+ " - " + err2.stack;
throw "JavaScript exception in application file '"
+ full + "': " + err2+ " - " + err2.stack;
}
return result;
};
////////////////////////////////////////////////////////////////////////////////

View File

@ -34,6 +34,69 @@ var internal = require("internal");
// --SECTION-- module "arangodb"
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ArangoShell
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief guesses the content type
////////////////////////////////////////////////////////////////////////////////
exports.guessContentType = function (filename) {
var re = /.*\.([^\.]*)$/;
var match = re.exec(filename);
var extension;
if (match === null) {
return "text/plain; charset=utf-8";
}
extension = match[1];
if (extension === "html") {
return "text/html; charset=utf-8";
}
if (extension === "xml") {
return "application/xml; charset=utf-8";
}
if (extension === "json") {
return "application/json; charset=utf-8";
}
if (extension === "js") {
return "application/x-javascript; charset=utf-8";
}
if (extension === "css") {
return "text/css; charset=utf-8";
}
if (extension === "png") {
return "image/png";
}
if (extension === "gif") {
return "image/gif";
}
if (extension === "jpg") {
return "image/jpg";
}
return "text/plain; charset=utf-8";
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- MODULE EXPORTS
// -----------------------------------------------------------------------------
@ -43,11 +106,19 @@ var internal = require("internal");
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief function "normalizeURL"
////////////////////////////////////////////////////////////////////////////////
exports.normalizeURL = internal.normalizeURL;
////////////////////////////////////////////////////////////////////////////////
/// @brief function "output"
////////////////////////////////////////////////////////////////////////////////
exports.output = function () { internal.output.apply(internal.output, arguments); };
exports.output = function () {
internal.output.apply(internal.output, arguments);
};
////////////////////////////////////////////////////////////////////////////////
/// @brief function "print"

View File

@ -30,6 +30,7 @@
var arangodb = require("org/arangodb");
var internal = require("internal");
var fs = require("fs");
var console = require("console");
var moduleExists = function(name) { return module.exists; };
@ -236,14 +237,22 @@ function lookupCallbackActionCallback (route, action) {
me = modelModule._package._environment = {};
if (cp !== "") {
me.appCollection = function (name) {
me.appCollectionName = function (name) {
return cp + "_" + name;
};
me.appCollection = function (name) {
return arangodb.db._collection(cp + "_" + name);
};
}
else {
me.appCollection = function (name) {
me.appCollectionName = function (name) {
return name;
};
me.appCollection = function (name) {
return arangodb.db._collection(name);
};
}
me.requireModel = function (path) {
@ -1100,7 +1109,7 @@ function reloadRouting () {
// lookup all routes
// .............................................................................
routing = internal.db._collection("_routing");
routing = arangodb.db._collection("_routing");
routes = routing.all();
// .............................................................................
@ -1731,6 +1740,28 @@ function redirectRequest (req, res, options, next) {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief redirects a request
////////////////////////////////////////////////////////////////////////////////
function pathHandler (req, res, options, next) {
var filename;
var result;
filename = fs.join(options.path, fs.join.apply(fs.join, req.suffix));
if (fs.exists(filename)) {
res.responseCode = exports.HTTP_OK;
res.contentType = arangodb.guessContentType(filename);
res.bodyFromFile = filename;
}
else {
res.responseCode = exports.HTTP_NOT_FOUND;
res.contentType = "text/plain";
res.body = "cannot find file '" + filename + "'";
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
@ -1777,6 +1808,7 @@ exports.resultException = resultException;
exports.echoRequest = echoRequest;
exports.logRequest = logRequest;
exports.redirectRequest = redirectRequest;
exports.pathHandler = pathHandler;
// some useful constants
exports.COLLECTION = "collection";

View File

@ -0,0 +1,293 @@
/*jslint indent: 2, nomen: true, maxlen: 120, sloppy: true, vars: true */
/*global module, require, exports */
////////////////////////////////////////////////////////////////////////////////
/// @brief Foxx application
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2013 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var internal = require("internal");
var arangodb = require("org/arangodb");
var fs = require("fs");
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Foxx
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief builds one assets of an app
////////////////////////////////////////////////////////////////////////////////
function buildAssetContent (app, assets) {
var files;
var i;
var j;
var m;
var match;
var content;
var reSub = /(.*)\/\*\*$/;
var reAll = /(.*)\/\*$/;
var rootDir = app._appDescription.path;
files = [];
for (j = 0; j < assets.length; ++j) {
var asset = assets[j];
match = reSub.exec(asset);
if (match !== null) {
var m = fs.listTree(fs.join(rootDir, match[1]));
for (i = 0; i < m.length; ++i) {
var filename = fs.join(rootDir, match[1], m[i]);
if (fs.isFile(filename)) {
files.push(filename);
}
}
}
else {
match = reAll.exec(asset);
if (match !== null) {
throw "not implemented";
}
else {
files.push(fs.join(rootDir, asset));
}
}
}
content = "";
for (i = 0; i < files.length; ++i) {
var c = fs.read(files[i]);
content += c;
}
return content;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief installs the assets of an app
////////////////////////////////////////////////////////////////////////////////
function installAssets (app, mount) {
var desc;
var path;
var routes;
desc = app._appDescription.manifest;
routes = {
urlPrefix: mount,
routes: []
};
if (desc.hasOwnProperty('assets')) {
for (path in desc.assets) {
if (desc.assets.hasOwnProperty(path)) {
var asset = desc.assets[path];
var content = buildAssetContent(app, asset);
var normalized = arangodb.normalizeURL("/" + path);
var type = arangodb.guessContentType(normalized);
var route = {
url: { match: normalized },
content: { contentType: type, body: content }
};
routes.routes.push(route);
}
}
}
if (desc.hasOwnProperty('files')) {
for (path in desc.files) {
if (desc.files.hasOwnProperty(path)) {
var directory = desc.files[path];
var normalized = arangodb.normalizeURL("/" + path);
var route = {
url: { match: normalized + "/*" },
action: {
"do": "org/arangodb/actions/pathHandler",
"options": {
path: fs.join(app._appDescription.path, directory)
}
}
};
routes.routes.push(route);
}
}
}
arangodb.db._collection("_routing").save(routes);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief sets up an app
////////////////////////////////////////////////////////////////////////////////
function setupApp (app, appContext) {
var desc;
var context;
desc = app._appDescription.manifest;
if (desc.hasOwnProperty("setup")) {
cp = appContext.collectionPrefix;
context = {};
if (cp !== "") {
context.appCollectionName = function (name) {
return cp + "_" + name;
};
context.appCollection = function (name) {
return internal.db._collection(cp + "_" + name);
};
}
else {
context.appCollectionName = function (name) {
return name;
};
context.appCollection = function (name) {
return internal.db._collection(name);
};
}
app.loadAppScript(app, desc.setup, appContext, context);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Foxx
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief installs a FOXX application
////////////////////////////////////////////////////////////////////////////////
exports.installApp = function (name, mount, options) {
'use strict';
var apps;
var description;
var i;
var version = options && options.version; // TODO currently ignored
var prefix = options && options.collectionPrefix;
var context = {};
var root = module.appRootModule(name); // TODO use version
if (root === null) {
if (version === undefined) {
throw "cannot find application '" + name + "'";
}
else {
throw "cannot find application '" + name + "' in version '" + version + "'";
}
}
description = root._appDescription.manifest;
if (mount === "") {
mount = "/";
}
else {
mount = internal.normalizeURL(mount);
}
if (mount[0] !== "/") {
throw "mount point must be absolute";
}
if (prefix === undefined) {
context.collectionPrefix = mount.substr(1).replace(/\//g, "_");
}
else {
context.collectionPrefix = prefix;
}
context.name = description.name;
context.version = description.version;
context.mount = mount;
apps = description.apps;
for (i in apps) {
if (apps.hasOwnProperty(i)) {
var file = apps[i];
context.appMount = i;
context.prefix = internal.normalizeURL(mount + "/" + i);
root.loadAppScript(root, file, context);
delete context.appMount;
delete context.prefix;
}
}
installAssets(root, mount);
setupApp(root, context);
return true;
};
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
/// -----------------------------------------------------------------------------
/// --SECTION-- END-OF-FILE
/// -----------------------------------------------------------------------------
/// Local Variables:
/// mode: outline-minor
/// outline-regexp: "/// @brief\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\|/\\*jslint"
/// End:

View File

@ -668,64 +668,10 @@ FormatMiddleware = function (allowedFormats, defaultFormat) {
};
};
////////////////////////////////////////////////////////////////////////////////
/// @brief loads a manifest file
////////////////////////////////////////////////////////////////////////////////
exports.installApp = function (name, mount, options) {
'use strict';
var version = options && options.version, // TODO currently ignored
prefix = options && options.collectionPrefix,
context = {},
apps,
description,
i,
root = module.appRootModule(name); // TODO use version
if (root === null) {
if (version === undefined) {
throw "cannot find application '" + name + "'";
} else {
throw "cannot find application '" + name + "' in version '" + version + "'";
}
}
description = root._appDescription;
if (mount === "") {
mount = "/";
} else {
mount = INTERNAL.normalizeURL(mount);
}
if (mount[0] !== "/") {
throw "mount point must be absolute";
}
if (prefix === undefined) {
context.collectionPrefix = mount.substr(1).replace(/\//g, "_");
} else {
context.collectionPrefix = prefix;
}
context.name = description.manifest.name;
context.version = description.manifest.version;
context.mount = mount;
apps = root._appDescription.manifest.apps;
for (i in apps) {
if (apps.hasOwnProperty(i)) {
var file = apps[i];
context.appMount = i;
context.prefix = INTERNAL.normalizeURL(mount + "/" + i);
root.loadAppScript(root, file, context);
}
}
};
/// We finish off with exporting FoxxApplication and the middlewares.
/// Everything else will remain our secret.
exports.installApp = require("org/arangodb/foxx-manager").installApp;
exports.FoxxApplication = FoxxApplication;
exports.BaseMiddleware = BaseMiddleware;
exports.FormatMiddleware = FormatMiddleware;

View File

@ -215,6 +215,14 @@ HttpResponse::HttpResponseCode HttpResponse::responseCode () const {
return _code;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief sets the response code
////////////////////////////////////////////////////////////////////////////////
void HttpResponse::setResponseCode (HttpResponseCode code) {
_code = code;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the content length
////////////////////////////////////////////////////////////////////////////////

View File

@ -205,6 +205,12 @@ namespace triagens {
HttpResponseCode responseCode () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief sets the response code
////////////////////////////////////////////////////////////////////////////////
void setResponseCode (HttpResponseCode);
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the content length
////////////////////////////////////////////////////////////////////////////////

View File

@ -89,6 +89,7 @@ typedef struct TRI_v8_global_s {
RevKey(),
ToKey(),
BodyKey(),
BodyFromFileKey(),
ContentTypeKey(),
IsSystemKey(),
IsVolatileKey(),
@ -294,6 +295,12 @@ typedef struct TRI_v8_global_s {
v8::Persistent<v8::String> BodyKey;
////////////////////////////////////////////////////////////////////////////////
/// @brief "bodyFromFile" key name
////////////////////////////////////////////////////////////////////////////////
v8::Persistent<v8::String> BodyFromFileKey;
////////////////////////////////////////////////////////////////////////////////
/// @brief "contentType" key name
////////////////////////////////////////////////////////////////////////////////

View File

@ -812,7 +812,9 @@ static v8::Handle<v8::Value> JS_IsFile (v8::Arguments const& argv) {
}
// return result
return scope.Close(TRI_ExistsFile(*name) ? v8::True() : v8::False());
bool isFile = TRI_ExistsFile(*name) && ! TRI_IsDirectory(*name);
return scope.Close(isFile ? v8::True() : v8::False());
}
////////////////////////////////////////////////////////////////////////////////