//////////////////////////////////////////////////////////////////////////////// /// @brief user guide guide /// /// @file /// /// DISCLAIMER /// /// Copyright 2012 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 2012, triAGENS GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- // --SECTION-- USER MANUAL // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @page UserManual ArangoDB's User Manual (@VERSION) /// /// @if LATEX /// /// @else /// @copydetails UserManualBasicsTOC /// @copydetails FirstStepsArangoDBTOC /// @copydetails UserManualArangoshTOC /// @copydetails ShellCollectionTOC /// @copydetails ShellDocumentTOC /// @copydetails ShellEdgeTOC /// @copydetails SimpleQueriesTOC /// @copydetails AqlTOC /// @copydetails UserManualActionsTOC /// @copydetails CommandLineTOC /// @endif //////////////////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- // --SECTION-- USER MANUAL BASICS // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @page UserManualBasicsTOC /// /// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// @page UserManualBasics About ArangoDB /// /// We recently started a new open source project - a universal nosql database /// called AvocadoDB which became ArangoDB in May 2012. /// /// Key features include: /// /// /// /// For more in-depth information /// /// /// /// The ArangoDB database groups documents into collections. Collections and /// documents can be accessed using queries. For simple queries involving just /// one collection and one search criteria, you can use a simple interface from /// within JavaScript code or other languages supported by an API. This /// interface allows you to select documents from one collection based on just /// one search criteria. For more complex queries, you can use the Arango Query /// Language (AQL), which is an evolution of SQL resp. UNQL for the NoSQL /// world. AQL allows you to use more then one collection, similar to joins from /// SQL, while still retaining the document and list structures like UNQL. /// /// The ArangoDB database packages comes with various programs: /// /// - @LIT{arangod}: The ArangoDB database daemon. This server program is /// intended to run as daemon process and to server the various clients /// connection to the server via TCP / HTTP. See @ref /// UserManualServerStartStop. /// - @LIT{arangosh}: The ArangoDB shell. A client that implements a /// read-eval-print loop (REPL) and provides functions to access and /// administrate the ArangoDB server. See @ref UserManualShellStartStop. /// - @LIT{arangoimp}: A bulk importer for the ArangoDB server. /// See @ref ImpManual /// /// @EMBEDTOC{UserManualBasicsTOC} /// /// @section UserManualServerStartStop Starting the ArangoDB Server /////////////////////////////////////////////////////////////////// /// /// The ArangoDB database server has two modes of operation: as server, where it /// will answer to client requests and an emergency console, in which you can /// access the database directly. The latter - as the name suggests - should /// only be used in case of an emergency, for example, a corrupted /// collection. Using the emergency console allows you to issue all commands /// normally available in actions and transactions. /// /// You should never start more than one server for the same database, /// independent from the mode of operation. /// /// The following command starts the ArangoDB database in server mode. You will /// be able to access the server using HTTP requests on port 8529. See @ref /// UserManualServerStartStopOptions "below" for a list of frequently used /// options, see @ref CommandLine "here" for a complete list. /// /// @TINYEXAMPLE{option-database-directory,starting the server} /// /// After starting the server, point your favorite browser to: /// /// @LIT{http://localhost:8529/} /// /// to access the administration front-end. /// /// @subsection UserManualServerStartStopOptions Frequently Used Options //////////////////////////////////////////////////////////////////////// /// /// The following command-line options are frequently used. For a full /// list of options see @ref CommandLine "here". /// /// @CMDOPT{@CA{database-directory}} //////////////////////////////////// /// /// Uses the @CA{database-directory} as base directory. There is an alternative /// version available for use in configuration files, see @ref /// CommandLineArango "here". /// /// @copydetails triagens::rest::ApplicationServer::_options //////////////////////////////////////////////////////////// /// /// @CMDOPT{--log @CA{level}} ///////////////////////////// /// /// Allows the user to choose the level of information which is logged by the /// server. The @CA{level} is specified as a string and can be one of the /// following values: fatal, error, warning, info, debug, trace. For more /// information see @ref CommandLineLogging "here". /// /// @copydetails triagens::arango::ArangoServer::_httpPort ////////////////////////////////////////////////////////// /// /// @CMDOPT{--daemon} ///////////////////// /// /// Runs the server as a daemon (as a background process). /// /// @section UserManualServerFE ArangoDB's Front-End //////////////////////////////////////////////////// /// /// The ArangoDB server has a graphical front-end, which allows you to inspect /// the current state of the server. You can read the front-end using the /// following URL: /// /// @LIT{http://localhost:8529/_admin} /// /// Unless you have loaded an application into the ArangoDB server, which remaps /// the paths, the front-end will also be available under /// /// @LIT{http://localhost:8529/}. /// /// @htmlonly ArangoDB Front-End@endhtmlonly /// @latexonly\includegraphics[width=12cm]{images/fe1.png}@endlatexonly /// /// The front-end allows you the browser through the collections and /// documents. If you need to administrate the database, please use /// the ArgangoDB shell described in the next section. /// /// @section UserManualShellStartStop Starting the ArangoDB Shell ///////////////////////////////////////////////////////////////// /// /// After the server has been @ref UserManualServerStartStop "started", /// you can use the ArangoDB shell to administrate the server. Without /// any arguments, the ArangoDB shell will try to contact the server /// on port 8529 on the localhost. For more information see @ref /// UserManualArangosh. /// /// @TINYEXAMPLE{arangosh-start,starting the shell} /// /// The shell will print its own version number and, if successfully connected /// to a server, the version number of the ArangoDB server. /// /// @subsection UserManualShellStartStopOptions Command-Line Options //////////////////////////////////////////////////////////////////// /// /// Use @LIT{--help} to get a list of command-line options: /// /// @TINYEXAMPLE{arangosh-options,shell options} /// /// @section UserManualServerStartStopDebug Starting the ArangoDB Emergency Console /////////////////////////////////////////////////////////////////////////////////// /// /// The following command starts a emergency console. See below for a list of /// frequently used options, see @ref CommandLine "here" for a complete list. /// /// @note Never start the emergency console for a database which also has a /// server attached to it. In general the ArangoDB shell is what you want. /// /// @EXAMPLE{start-emergency-console,emergency console} //////////////////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- // --SECTION-- USER MANUAL ARANGOSH // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @page UserManualArangoshTOC /// /// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// @page UserManualArangosh The Arango Shell /// /// @EMBEDTOC{UserManualArangoshTOC} /// /// @section UserManualArangoshOutput Arango Shell Output ///////////////////////////////////////////////////////// /// /// In general the Arango Shells prints its as output to standard output channel /// using the JSON stringifier. /// /// @code /// arangosh> db.five.all().toArray(); /// [{ _id : "2223655/3665447", _rev : 3665447, name : "one" }, /// { _id : "2223655/3730983", _rev : 3730983, name : "two" }, /// { _id : "2223655/3862055", _rev : 3862055, name : "four" }, /// { _id : "2223655/3993127", _rev : 3993127, name : "three" }] /// @endcode /// /// @CLEARPAGE /// @FUN{start_pretty_print()} /// /// While the standard JSON stringifier is very concise it is hard to read. /// Calling the function @FN{start_pretty_print} will enable the pretty printer /// which formats the output in a human readable way. /// /// @code /// arangosh> start_pretty_print(); /// using pretty printing /// arangosh> db.five.all().toArray(); /// [ /// { /// _id : "2223655/3665447", /// _rev : 3665447, /// name : "one" /// }, /// { /// _id : "2223655/3730983", /// _rev : 3730983, /// name : "two" /// }, /// { /// _id : "2223655/3862055", /// _rev : 3862055, /// name : "four" /// }, /// { /// _id : "2223655/3993127", /// _rev : 3993127, /// name : "three" /// } /// ] /// @endcode /// /// @CLEARPAGE /// @FUN{stop_pretty_print()} /// /// The functions disable the pretty printer, switching back to the standard /// JSON output format. //////////////////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- // --SECTION-- USER MANUAL ACTIONS // ----------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// /// @page UserManualActionsTOC /// /// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// @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 some ways the communication layer of the ArangoDB server behaves like a /// Web server. Unlike a Web server, it normally responses to HTTP requests by /// delivering JSON objects. Remember, documents in the database are just JSON /// objects. So, most of the time the HTTP response will contain a JSON document /// from the database as body. You can extract the documents stored in the /// database using HTTP @LIT{GET}. You can store documents using HTTP /// @LIT{POST}. /// /// However, there is something more. You can write small sniplets - so called /// actions - to extend the database. The idea of actions is that sometimes it /// is better to store parts of the business logic within AnrangoDB. /// /// The simplest example is the age of a person. Assume you store information /// about people in your database. It is an anti-pattern to store the age, /// because it changes every now and then. Therefore, you normally store the /// birthday and let the client decide what to do with it. However, if you have /// many different clients, it might be easier to enrich the person document /// with the age using actions once on the server side. /// /// Or, for instance, if you want to apply some statistics to large data-sets /// and you cannot easily express this as query. You can define a action instead /// of transferring the whole data to the client and do the computation on the /// client. /// /// Actions are also useful if you want to restrict and filter data according to /// some complex permission system. /// /// The ArangoDB server can 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. /// /// The following sections will explain actions within ArangoDB and show 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 Example ////////////////////////////////////////////////////////////// /// /// 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 @LIT{/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 /// /// /// Hello 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({ /// ........> url: { match: "/hello/world" }, /// ........> content: { /// ........> contentType: "text/html", /// ........> body: "Hello World" }}); /// @endcode /// /// In order to activate the new routing, you must either restart the server /// or call the internal reload function. /// /// @code /// arangosh> require("org/arangodb/routing").reload() /// @endcode /// /// Now use the browser and access /// /// @LIT{http://localhost:8529/hello/world} /// /// You should see the @LIT{Hello World} in our browser. /// /// @section UserManualActionsMatches Matching an URL ///////////////////////////////////////////////////// /// /// There are a lot of options for the @LIT{url} attribute. If you define /// different routing for the same path, then the following simple rule is /// applied in order to determine which match wins: If there are two matches, /// then the more specific wins. I. e, if there is a wildcard match and an exact /// match, the exact match is prefered. If there is a short and a long match, /// the longer match wins. /// /// @subsection UserManualActionsMatchesExact Exact Match /// /// If the definition is /// /// @code /// { url: { match: "/hello/world" } } /// @endcode /// /// then the match must be exact. Only the request for @LIT{/hello/world} will /// match, everything else, e. g. @LIT{/hello/world/my} or @LIT{/hello/world2}, /// will not match. /// /// The following definition is a short-cut for an exact match. /// /// @code /// { url: "/hello/world" } /// @endcode /// /// @subsection UserManualActionsMatchesPrefix Prefix Match /// /// If the definition is /// /// @code /// { url: { match: "/hello/world/*" } } /// @endcode /// /// then the match can be a prefix match. The requests for @LIT{/hello/world}, /// @LIT{/hello/world/my}, and @LIT{/hello/world/how/are/you} will all /// match. However @LIT{/hello/world2} does not match. Prefix matches within an /// URL part, i. e. @LIT{/hello/world*}, are not allowed. The wildcard must /// occur at the end, i. e. /// /// @code /// /hello/*/world /// @endcode /// /// is also disallowed. /// /// If you define two routes /// /// @code /// { url: { match: "/hello/world/*" } } /// { url: { match: "/hello/world/emil" } } /// @endcode /// /// then the second route will be used for @LIT{/hello/world/emil} because it is /// more specific. /// /// @subsection UserManualActionsMatchesParameterized Parameterized Match /// /// A parameterized match is similar to a prefix match, but the parameters are /// also allowed inside the URL path. /// /// If the definition is /// /// @code /// { url: { match: "/hello/:name/world" } } /// @endcode /// /// then the URL must have three parts, the first part being @LIT{hello} and the /// third part @LIT{world}. For example, @LIT{/hello/emil/world} will match, /// while @LIT{/hello/emil/meyer/world} will not. /// /// @subsection UserManualActionsMatchesConstraint Constraint Match /// /// A constraint match is similar to a parameterized match, but the parameters /// carries a constraint. /// /// If the definition is /// /// @code /// { url: { match: "/hello/:name/world", constraint: { name: "/[a-z]+/" } } /// @endcode /// /// then the URL must have three parts, the first part being @LIT{hello} and the /// third part @LIT{world}. The second part must be all lowercase. /// /// It is possible to use more then one constraint for the same URL part. /// /// @code /// { url: { match: "/hello/:name|:id/world", /// constraint: { name: "/[a-z]+/", id: "/[0-9]+/" } } /// @endcode /// /// @subsection UserManualActionsMatchesOptional Optional Match /// /// An optional match is similar to a parameterized match, but the last /// parameter is optional. /// /// If the definition is /// /// @code /// { url: { match: "/hello/:name?", constraint: { name: "/[a-z]+/" } } /// @endcode /// /// then the URL @LIT{/hello} and @LIT{/hello/emil} will match. /// /// If the definitions are /// /// @code /// { url: { match: "/hello/world" } } /// { url: { match: "/hello/:name", constraint: { name: "/[a-z]+/" } } /// { url: { match: "/hello/*" } } /// @endcode /// /// then the URL @LIT{/hello/world} will be matched by the first route, because it /// is the most specific. The URL @LIT{/hello/you} will be matched by the second /// route, because it is more specific than the prefix match. /// /// @subsection UserManualActionsMatchesMethod Method Restriction /// /// You can restrict the match to specific methods. /// /// If the definition is /// /// @code /// { url: { match: "/hello/world", methods: [ "post", "put" ] } /// @endcode /// /// then only @LIT{POST} and @LIT{PUT} requests will match. /// /// @subsection UserManualActionsMatching More on Matching /// /// Remember that the more specific match wins. /// /// - A match without parameter or wildcard is more specific than a match with /// parameters or wildcard. /// - A match with parameter is more specific than a match with a wildcard. /// - If there is more than one parameter, specificity is applied from left to /// right. /// /// Consider the following definitions /// /// @code /// (1) { url: { match: "/hello/world" } } /// (2) { url: { match: "/hello/:name", constraint: { name: "/[a-z]+/" } } /// (3) { url: { match: "/:something/world" } /// (4) { url: { match: "/hello/*" } } /// @endcode /// /// Then /// /// - @LIT{/hello/world} is match by (1) /// - @LIT{/hello/emil} is match by (2) /// - @LIT{/your/world} is match by (3) /// - @LIT{/hello/you} is match by (4) /// /// You can write the following document into the @LIT{_routing} collection /// to test the above examples. /// /// @code /// { /// routes: [ /// { url: { match: "/hello/world" }, content: "route 1" }, /// { url: { match: "/hello/:name|:id", constraint: { name: "/[a-z]+/", id: "/[0-9]+/" } }, content: "route 2" }, /// { url: { match: "/:something/world" }, content: "route 3" }, /// { url: { match: "/hello/*" }, content: "route 4" }, /// ] /// } /// @endcode /// /// @section UserManualActionsHelloJson A Hello World Example for JSON ////////////////////////////////////////////////////////////////////// /// /// If you change the example slightly, then a JSON object will be delivered. /// /// @code /// arangosh> db._routing.save({ /// ........> url: "/hello/json", /// ........> content: { /// ........> contentType: "application/json", /// ........> body: "{ \"hello\" : \"world\" }" }}); /// arangosh> require("internal").reloadRouting() /// @endcode /// /// Again check with your browser /// /// @LIT{http://localhost:8529/hello/json} /// /// Depending on your browser and installed add-ons you will either see the /// JSON object or a download dialog. If your browser wants to open an external /// application to display the JSON object, you can change the @LIT{contentType} /// to @LIT{"text/plain"} for the example. This makes it easier to check the /// example using a browser. Or use @LIT{curl} to access the server. /// /// @code /// bash> curl "http://127.0.0.1:8529/hello/json" && echo /// { "hello" : "world" } /// @endcode /// /// @section UserManualActionsContent Delivering Content //////////////////////////////////////////////////////// /// /// There are a lot of different ways on how to deliver content. We have already /// seen the simplest one, where static content is delivered. The fun, however, /// starts when delivering dynamic content. /// /// @subsection UserManualActionsContentStatic Static Content /// /// You can specify a body and a content-type. /// /// @code /// { content: { /// contentType: "text/html", /// body: "Hallo World" /// } /// } /// @endcode /// /// If the content type is @LIT{text/plain} then you can use the short-cut /// /// @code /// { content: "Hallo World" } /// @endcode /// /// @subsection UserManualActionsContentAction A Simple Action /// /// The simplest dynamic action is: /// /// @code /// { action: "org/arangodb/actions/echoRequest" } /// @endcode /// /// It is not possible to store functions directly in the routing table, but you /// can call functions defined in modules. In the above example the function can /// be accessed from JavaScript as: /// /// @LIT{require("org/arangodb/actions").echoRequest} /// /// The function @LIT{echoRequest} is pre-defined. It takes the request objects /// and echos it in the response. /// /// The signature of such a function must be /// /// @code /// function (req, res, next, options) /// @endcode /// /// For example /// /// @code /// arangosh> db._routing.save({ /// ........> url: "/hello/echo", /// ........> action: "org/arangodb/actions/echoRequest" }); /// @endcode /// /// Reload the routing and check /// /// @LIT{http://127.0.0.1:8529/hello/echo} /// /// You should see something like /// /// @code /// { /// "request": { /// "path": "/hello/echo", /// "headers": { /// "accept-encoding": "gzip, deflate", /// "accept-language": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3", /// "connection": "keep-alive", /// "content-length": "0", /// "host": "localhost:8529", /// "user-agent": "Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0" /// }, /// "requestType": "GET", /// "parameters": { } /// }, /// "options": { } /// } /// @endcode /// /// The request might contain @LIT{path}, @LIT{prefix}, @LIT{suffix}, and /// @LIT{urlParameters} attributes. @LIT{path} is the complete path as supplied /// by the user and always available. If a prefix was matched, then this prefix /// is stored in the attribute @LIT{prefix} and the remaining URL parts are /// stored as an array in @LIT{suffix}. If one or more parameters were matched, /// then the parameter values are stored in @LIT{urlParameters}. /// /// For example, if the url description is /// /// @code /// { url: { match: "/hello/:name/:action" } } /// @endcode /// /// and you request the path @LIT{/hello/emil/jump}, then the request object /// will contain the following attribute /// /// @code /// urlParameters: { name: "emil", action: "jump" } } /// @endcode /// /// @subsection UserManualActionsContentController Action Controller /// /// As an alternative to the simple action, you can use controllers. A /// controller is a module, defines the function @LIT{get}, @LIT{put}, /// @LIT{post}, @LIT{delete}, @LIT{head}, @LIT{patch}. If a request of /// the corresponding type is matched, the function will be called. /// /// For example /// /// @code /// arangosh> db._routing.save({ /// ........> url: "/hello/echo", /// ........> action: { controller: "org/arangodb/actions/echoController" } }); /// @endcode /// /// @subsection UserManualActionsContentPrefix Prefix Action Controller /// /// The controller is selected when the definition is read. There is a /// more flexible, but slower and maybe insecure variant, the prefix /// controller. /// /// Assume that the url is a prefix match /// /// @code /// { url: { match: /hello/*" } } /// @endcode /// /// You can use /// /// @code /// { prefixController: "org/arangodb/actions" } /// @endcode /// /// to define a prefix controller. If the URL @LIT{/hello/echoController} is /// given, then the module @LIT{org/arangodb/actions/echoController} is used. /// /// If you use an prefix controller, you should make certain that no unwanted /// actions are available under the prefix. /// /// @subsection UserManualActionsContentMethod Method Restriction /// /// You can restrict the match to specific methods. /// /// If the definition is /// /// @code /// { controller: "org/arangodb/actions/echoController", methods: [ "post", "put" ] } /// @endcode /// /// then only @LIT{POST} and @LIT{PUT} requests will match. /// /// @section UserManualActionsReqRes Requests and Responses /////////////////////////////////////////////////////////// /// /// The controller must define handler functions which take a request object and /// fill the response object. /// /// A very simple example is the function @LIT{echoRequest} defined in /// the module @LIT{org/arangodb/actions}. /// /// @code /// function (req, res, next, options) { /// var result; /// /// result = { request: req, options: options }; /// /// res.responseCode = exports.HTTP_OK; /// res.contentType = "application/json"; /// res.body = JSON.stringify(result); /// } /// @endcode /// /// Install it as /// /// @code /// arangosh> db._routing.save({ /// ........> url: "/echo", /// ........> action: "org/arangodb/actions/echoRequest" }); /// @endcode /// /// Reload the routing and check /// /// @LIT{http://127.0.0.1:8529/hello/echo} /// /// You should see something like /// /// @code /// { /// "request": { /// "prefix": "/hello/echo", /// "suffix": [ /// "hello", /// "echo" /// ], /// "path": "/hello/echo", /// "headers": { /// "accept-encoding": "gzip, deflate", /// "accept-language": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3", /// "connection": "keep-alive", /// "content-length": "0", /// "host": "localhost:8529", /// "user-agent": "Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0" /// }, /// "requestType": "GET", /// "parameters": { } /// }, /// "options": { } /// } /// @endcode /// /// Note that /// /// @code /// arangosh> db._routing.save({ /// ........> url: "/echo", /// ........> action: "org/arangodb/actions/echoRequest" }); /// @endcode /// /// is a short-cut for /// /// @code /// arangosh> db._routing.save({ /// ........> url: "/echo", /// ........> action: { do: "org/arangodb/actions/echoRequest" } }); /// @endcode /// /// The latter form allows you to pass options to the called function: /// /// @code /// arangosh> db._routing.save({ /// ........> url: "/echo", /// ........> action: { /// ........> do: "org/arangodb/actions/echoRequest", /// ........> options: { "Hallo": "World" } } }); /// @endcode /// /// You should now see the options in the result. /// /// @code /// { /// "request": { /// "prefix": "/hello/echo-long", /// ... /// }, /// "options": { /// "option": "my option1" /// } /// } /// @endcode /// /// @section UserManualActionsAdvanced Advanced Usages ////////////////////////////////////////////////////// /// /// For detailed information see the reference manual. /// /// @subsection UserManualActionsAdvancedRedirects Redirects /// /// Use the following for a permanent redirect: /// /// @code /// arangosh> db._routing.save({ /// ........> url: "/", /// ........> action: { /// ........> do: "org/arangodb/actions/redirectRequest", /// ........> options: { /// ........> permanently: true, /// ........> destination: "http://somewhere.else/" } } }); /// @endcode /// /// @subsection UserManualActionsAdvancedBundles Routing Bundles /// /// Instead of adding all routes for package separately, you can /// specify a bundle. /// /// @code /// { /// routes: [ /// { url: "/url1", content: "..." }, /// { url: "/url2", content: "..." }, /// { url: "/url3", content: "..." }, /// ... /// ] /// } /// @endcode /// /// The advantage is, that you can put all your routes into one document /// and use a common prefix. /// /// @code /// { /// urlPrefix: "/test", /// /// routes: [ /// { url: "/url1", content: "..." }, /// { url: "/url2", content: "..." }, /// { url: "/url3", content: "..." }, /// ... /// ] /// } /// @endcode /// /// will define the URL @LIT{/test/url1}, @LIT{/test/url2}, and /// @LIT{/test/url3}. /// /// @subsection UserManualActionsAdvancedMiddleware Writing Middleware /// /// Assume, you want to log every request. In this case you can easily define /// an action for the whole url-space @LIT{/}. This action simply logs /// the requests, calls the next in line, and logs the response. /// /// @code /// exports.logRequest = function (req, res, next, options) { /// console.log("received request: %s", JSON.stringify(req)); /// next(); /// console.log("produced response: %s", JSON.stringify(res)); /// }; /// @endcode /// /// This functions is available as @LIT{org/arangodb/actions/logRequest}. /// You need to tell ArangoDB that it is should use a prefix match and /// that the shortest match should win in this case: /// /// @code /// arangosh> db._routing.save({ /// ........> middleware: [ /// ........> { url: { match: "/*" }, action: "org/arangodb/actions/logRequest" } /// ........> ] /// ........> }); /// @endcode //////////////////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- // --SECTION-- END-OF-FILE // ----------------------------------------------------------------------------- // Local Variables: // mode: c++ // mode: outline-minor // outline-regexp: "\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @section\\|/// @subsection\\|/// @\\}\\)" // End: