mirror of https://gitee.com/bigwinds/arangodb
1042 lines
36 KiB
Plaintext
1042 lines
36 KiB
Plaintext
////////////////////////////////////////////////////////////////////////////////
|
|
/// @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
|
|
/// <ul>
|
|
/// <li>@ref UserManualBasics</li>
|
|
/// <li>@ref FirstStepsArangoDB</li>
|
|
/// <li>@ref UserManualArangosh</li>
|
|
/// <li>@ref ShellCollection</li>
|
|
/// <li>@ref ShellDocument</li>
|
|
/// <li>@ref ShellEdge</li>
|
|
/// <li>@ref SimpleQueries</li>
|
|
/// <li>@ref Aql</li>
|
|
/// <li>@ref UserManualActions</li>
|
|
///
|
|
/// @latexonly\appendix@endlatexonly
|
|
/// <li>@ref CommandLine</li>
|
|
/// <li>@ref Glossary</li>
|
|
/// </ul>
|
|
/// @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
|
|
///
|
|
/// <ul>
|
|
/// <li>@ref UserManualBasics
|
|
/// <ul>
|
|
/// <li>@ref UserManualServerStartStop
|
|
/// <ul>
|
|
/// <li>@ref UserManualServerStartStopOptions</li>
|
|
/// </ul>
|
|
/// </li>
|
|
/// <li>@ref UserManualServerFE</li>
|
|
/// <li>@ref UserManualShellStartStop
|
|
/// <ul>
|
|
/// <li>@ref UserManualShellStartStopOptions</li>
|
|
/// </ul>
|
|
/// </li>
|
|
/// </li>
|
|
/// <li>@ref UserManualServerStartStopDebug
|
|
/// </li>
|
|
/// </ul>
|
|
/// </li>
|
|
/// </ul>
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @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:
|
|
///
|
|
/// <ul>
|
|
/// <li> Schema-free schemata let you combine the space efficiency of MySQL with
|
|
/// the performance power of NoSQL</li>
|
|
/// <li> Use ArangoDB as an application server and fuse your application and
|
|
/// database together for maximal throughput</li>
|
|
/// <li> JavaScript for all: no language zoo, you can use one language from your
|
|
/// browser to your back-end</li>
|
|
/// <li> ArangoDB is multi-threaded - exploit the power of all your cores</li>
|
|
/// <li> Flexible data modeling: model your data as combination of key-value pairs,
|
|
/// documents or graphs - perfect for social relations</li>
|
|
/// <li> Free index choice: use the correct index for your problem, be it a skip
|
|
/// list or a n-gram search</li>
|
|
/// <li> Configurable durability: let the application decide if it needs more
|
|
/// durability or more performance</li>
|
|
/// <li> No-nonsense storage: ArangoDB uses all of the power of modern storage
|
|
/// hardware, like SSD and large caches</li>
|
|
/// <li> It is open source (Apache Licence 2.0)</li>
|
|
/// </ul>
|
|
///
|
|
/// For more in-depth information
|
|
///
|
|
/// <ul>
|
|
/// <li> read more on the @EXTRES{http://www.arangodb.org/2012/03/07/avocadodbs-design-objectives,design goals of ArangoDB}</li>
|
|
/// <li> @EXTREF{http://vimeo.com/36411892,watch the video}@SPC- Martin Schoenert,
|
|
/// architect of ArangoDB, gives an introduction of what the ArangoDB project
|
|
/// is about.</li>
|
|
/// <li> or give it a @EXTRES{http://www.arangodb.org/try,try}.</li>
|
|
/// </ul>
|
|
///
|
|
/// 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 <img src="images/fe1.png" alt="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
|
|
///
|
|
/// <ul>
|
|
/// <li>@ref UserManualArangosh
|
|
/// </li>
|
|
/// </ul>
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @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
|
|
///
|
|
/// <ul>
|
|
/// <li>@ref UserManualActions
|
|
/// <ul>
|
|
/// <li>@ref UserManualActionsIntro</li>
|
|
/// <li>@ref UserManualActionsHelloWorld</li>
|
|
/// <li>@ref UserManualActionsMatches
|
|
/// <ul>
|
|
/// <li>@ref UserManualActionsMatchesExact</li>
|
|
/// <li>@ref UserManualActionsMatchesPrefix</li>
|
|
/// <li>@ref UserManualActionsMatchesParameterized</li>
|
|
/// <li>@ref UserManualActionsMatchesConstraint</li>
|
|
/// <li>@ref UserManualActionsMatchesOptional</li>
|
|
/// <li>@ref UserManualActionsMatchesMethod</li>
|
|
/// <li>@ref UserManualActionsMatching</li>
|
|
/// </ul>
|
|
/// </li>
|
|
/// <li>@ref UserManualActionsHelloJson</li>
|
|
/// <li>@ref UserManualActionsContent
|
|
/// <ul>
|
|
/// <li>@ref UserManualActionsContentStatic</li>
|
|
/// <li>@ref UserManualActionsContentAction</li>
|
|
/// <li>@ref UserManualActionsContentController</li>
|
|
/// <li>@ref UserManualActionsContentPrefix</li>
|
|
/// <li>@ref UserManualActionsContentMethod</li>
|
|
/// </ul>
|
|
/// </li>
|
|
/// <li>@ref UserManualActionsReqRes</li>
|
|
/// <li>@ref UserManualActionsAdvanced
|
|
/// <ul>
|
|
/// <li>@ref UserManualActionsAdvancedRedirects</li>
|
|
/// <li>@ref UserManualActionsAdvancedBundles</li>
|
|
/// <li>@ref UserManualActionsAdvancedMiddleware</li>
|
|
/// </ul>
|
|
// </li>
|
|
/// </ul>
|
|
/// </li>
|
|
/// </ul>
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @page UserManualActions Arango Actions
|
|
///
|
|
/// Please note, that user Actions in ArangoDB are still preliminary and details
|
|
/// are subject to change.
|
|
///
|
|
/// @EMBEDTOC{UserManualActionsTOC}
|
|
///
|
|
/// @section UserManualActionsIntro Introduction to User Actions
|
|
////////////////////////////////////////////////////////////////
|
|
///
|
|
/// In 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
|
|
/// <html>
|
|
/// <body>
|
|
/// Hello World
|
|
/// </body>
|
|
/// </html>
|
|
/// @endcode
|
|
///
|
|
/// if asked @LIT{GET /hello/world}.
|
|
///
|
|
/// The server needs to know what function to call or what document to deliver
|
|
/// if it receives a request. This is called routing. All the routing information
|
|
/// of ArangoDB is stored in a collection @LIT{_routing}. Each entry in this
|
|
/// collections describes how to deal with a particular request path.
|
|
///
|
|
/// For the above example, add the following document to the @{_routing}
|
|
/// collection:
|
|
///
|
|
/// @code
|
|
/// arangosh> db._routing.save({
|
|
/// ........> url: { match: "/hello/world" },
|
|
/// ........> content: {
|
|
/// ........> contentType: "text/html",
|
|
/// ........> body: "<html><body>Hello World</body></html>" }});
|
|
/// @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: "<html><body>Hallo World</body></html>"
|
|
/// }
|
|
/// }
|
|
/// @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:
|