mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel
This commit is contained in:
commit
4d32fb204b
|
@ -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" } }
|
||||
........> ]
|
||||
........> });
|
||||
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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:
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -205,6 +205,12 @@ namespace triagens {
|
|||
|
||||
HttpResponseCode responseCode () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief sets the response code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setResponseCode (HttpResponseCode);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the content length
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue