!SECTION A Hello World Example for JSON If you change the example slightly, then a JSON object will be delivered. @startDocuBlockInline JSON_01_routingCreateJsonHelloWorld @EXAMPLE_ARANGOSH_OUTPUT{JSON_01_routingCreateJsonHelloWorld} |db._routing.save({ | url: "/hello/json", | content: { | contentType: "application/json", | body: '{"hello" : "world"}' | } }); require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_01_routingCreateJsonHelloWorld Again check with your browser or cURL 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 *contentType* to *"text/plain"* for the example. This makes it easier to check the example using a browser. Or use *curl* to access the server. @startDocuBlockInline JSON_02_routingCurlJsonHelloWorld @EXAMPLE_ARANGOSH_RUN{JSON_02_routingCurlJsonHelloWorld} var url = "/hello/json"; var response = logCurlRequest('GET', url); assert(response.code === 200); logJsonResponse(response); @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_02_routingCurlJsonHelloWorld @startDocuBlockInline JSON_03_routingCleanupJsonHelloWorld @EXAMPLE_ARANGOSH_OUTPUT{JSON_03_routingCleanupJsonHelloWorld} ~db._query("FOR route IN _routing FILTER route.url == '/hello/json' REMOVE route in _routing") ~require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_03_routingCleanupJsonHelloWorld !SECTION 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 Static Content You can specify a body and a content-type. @startDocuBlockInline JSON_05a_routingCreateContentTypeHelloWorld @EXAMPLE_ARANGOSH_OUTPUT{JSON_05a_routingCreateContentTypeHelloWorld} |db._routing.save({ | url: "/hello/contentType", | content: { | contentType: "text/html", | body: "Hello World" | } }); require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_05a_routingCreateContentTypeHelloWorld @startDocuBlockInline JSON_05b_routingCurlContentTypeHelloWorld @EXAMPLE_ARANGOSH_RUN{JSON_05b_routingCurlContentTypeHelloWorld} var url = "/hello/contentType"; var response = logCurlRequest('GET', url); assert(response.code === 200); logRawResponse(response); @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_05b_routingCurlContentTypeHelloWorld @startDocuBlockInline JSON_05c_routingCleanupContentTypeHelloWorld @EXAMPLE_ARANGOSH_OUTPUT{JSON_05c_routingCleanupContentTypeHelloWorld} ~db._query("FOR route IN _routing FILTER route.url == '/hello/contentType' REMOVE route in _routing") ~require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_05c_routingCleanupContentTypeHelloWorld If the content type is *text/plain* then you can use the short-cut ```js { content: "Hello World" } ``` !SUBSECTION A Simple Action The simplest dynamic action is: ```js { action: { do: "@arangodb/actions/echoRequest" } } ``` It is not advisable to store functions directly in the routing table. It is better to call functions defined in modules. In the above example the function can be accessed from JavaScript as: ```js require("@arangodb/actions").echoRequest ``` The function *echoRequest* is pre-defined. It takes the request objects and echos it in the response. The signature of such a function must be ```js function (req, res, options, next) ``` *Examples* @startDocuBlockInline JSON_06_routingCreateHelloEcho @EXAMPLE_ARANGOSH_OUTPUT{JSON_06_routingCreateHelloEcho} |db._routing.save({ | url: "/hello/echo", | action: { | do: "@arangodb/actions/echoRequest" | } }); ~require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_06_routingCreateHelloEcho Reload the routing and check http:// 127.0.0.1:8529/hello/echo You should see something like @startDocuBlockInline JSON_07_fetchroutingCreateHelloEcho @EXAMPLE_ARANGOSH_OUTPUT{JSON_07_fetchroutingCreateHelloEcho} arango.GET("/hello/echo") @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_07_fetchroutingCreateHelloEcho @startDocuBlockInline JSON_08_routingCleanupHelloEcho @EXAMPLE_ARANGOSH_OUTPUT{JSON_08_routingCleanupHelloEcho} ~db._query("FOR route IN _routing FILTER route.url == '/hello/echo' REMOVE route in _routing") ~require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_08_routingCleanupHelloEcho The request might contain *path*, *prefix*, *suffix*, and *urlParameters* attributes. *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 *prefix* and the remaining URL parts are stored as an array in *suffix*. If one or more parameters were matched, then the parameter values are stored in *urlParameters*. For example, if the url description is ```js { url: { match: "/hello/:name/:action" } } ``` and you request the path */hello/emil/jump*, then the request object will contain the following attribute ```js urlParameters: { name: "emil", action: "jump" } ``` !SUBSECTION Action Controller As an alternative to the simple action, you can use controllers. A controller is a module, defines the function *get*, *put*, *post*, *delete*, *head*, *patch*. If a request of the corresponding type is matched, the function will be called. *Examples* @startDocuBlockInline JSON_09_routingCreateEchoController @EXAMPLE_ARANGOSH_OUTPUT{JSON_09_routingCreateEchoController} |db._routing.save({ | url: "/hello/echo", | action: { | controller: "@arangodb/actions/echoController" | } }); ~require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_09_routingCreateEchoController Reload the routing and check http:// 127.0.0.1:8529/hello/echo: @startDocuBlockInline JSON_10_fetchroutingCreateEchoController @EXAMPLE_ARANGOSH_OUTPUT{JSON_10_fetchroutingCreateEchoController} arango.GET("/hello/echo") @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_10_fetchroutingCreateEchoController @startDocuBlockInline JSON_11_routingCleanupEchoController @EXAMPLE_ARANGOSH_OUTPUT{JSON_11_routingCleanupEchoController} ~db._query("FOR route IN _routing FILTER route.url == '/hello/echo' REMOVE route in _routing") ~require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_11_routingCleanupEchoController !SUBSECTION 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 ```js { url: { match: /hello/*" } } ``` You can use ```js { action: { prefixController: "@arangodb/actions" } } ``` to define a prefix controller. If the URL */hello/echoController* is given, then the module *@arangodb/actions/echoController* is used. If you use a prefix controller, you should make certain that no unwanted actions are available under the prefix. The definition ```js { action: "@arangodb/actions" } ``` is a short-cut for a prefix controller definition. !SUBSECTION Function Action You can also store a function directly in the routing table. *Examples* @startDocuBlockInline JSON_12a_routingCreateEchoFunction @EXAMPLE_ARANGOSH_OUTPUT{JSON_12a_routingCreateEchoFunction} |db._routing.save({ | url: "/hello/echo", | action: { | callback: "function(req,res) {res.statusCode=200; res.body='Hello'}" | } }); ~require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_12a_routingCreateEchoFunction @startDocuBlockInline JSON_12b_fetchroutingEchoFunction @EXAMPLE_ARANGOSH_OUTPUT{JSON_12b_fetchroutingEchoFunction} arango.GET("hello/echo") db._query("FOR route IN _routing FILTER route.url == '/hello/echo' REMOVE route in _routing") require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_12b_fetchroutingEchoFunction !SUBSECTION 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 *echoRequest* defined in the module *@arangodb/actions*. ```js function (req, res, options, next) { var result; result = { request: req, options: options }; res.responseCode = exports.HTTP_OK; res.contentType = "application/json"; res.body = JSON.stringify(result); } ``` Install it via: @startDocuBlockInline JSON_13_routingCreateEchoAction @EXAMPLE_ARANGOSH_OUTPUT{JSON_13_routingCreateEchoAction} |db._routing.save({ | url: "/echo", | action: { | do: "@arangodb/actions/echoRequest" | } }) ~require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_13_routingCreateEchoAction Reload the routing and check http:// 127.0.0.1:8529/hello/echo You should see something like @startDocuBlockInline JSON_14_fetchroutingRequestHelloEcho @EXAMPLE_ARANGOSH_OUTPUT{JSON_14_fetchroutingRequestHelloEcho} arango.GET("/hello/echo") db._query("FOR route IN _routing FILTER route.url == '/hello/echo' REMOVE route in _routing") require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_14_fetchroutingRequestHelloEcho You may also pass options to the called function: @startDocuBlockInline JSON_15_routingCreateEchoRequestOptions @EXAMPLE_ARANGOSH_OUTPUT{JSON_15_routingCreateEchoRequestOptions} |db._routing.save({ | url: "/echo", | action: { | do: "@arangodb/actions/echoRequest", | options: { | "Hello": "World" | } | } }); ~require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_15_routingCreateEchoRequestOptions You now see the options in the result: @startDocuBlockInline JSON_16_fetchroutingEchoRequestOptions @EXAMPLE_ARANGOSH_OUTPUT{JSON_16_fetchroutingEchoRequestOptions} arango.GET("/echo") db._query("FOR route IN _routing FILTER route.url == '/echo' REMOVE route in _routing") require("internal").reloadRouting() @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock JSON_16_fetchroutingEchoRequestOptions